This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new b280370a983 Few UI fixes and details improvements (#7434)
b280370a983 is described below
commit b280370a983aca2fa5c065960c25786e9b40341b
Author: Harikrishna <[email protected]>
AuthorDate: Tue May 2 17:06:54 2023 +0530
Few UI fixes and details improvements (#7434)
* Better hover label and message for generate API/secret keys form
* Added a message to select network during instance deployment
* Removed project icon in dashboard listing
* Disable network operations for the user who does not have permission
* UI allignments
* added document help for sticky policy secion under load balancer
* Added tooltips and some form layout changes
* donot display options to configure when stickypolicy is none
* Network selection message allignment
* Fixed the grid view to be uniform in infra summary page
---
.../loadbalancer/CreateLBStickinessPolicyCmd.java | 2 +-
ui/public/locales/en.json | 5 +-
ui/src/components/header/ProjectMenu.vue | 12 --
ui/src/components/view/ActionButton.vue | 5 +-
ui/src/config/section/network.js | 3 +
ui/src/config/section/user.js | 1 +
ui/src/views/AutogenView.vue | 11 +-
ui/src/views/compute/DeployVM.vue | 5 +-
ui/src/views/infra/InfraSummary.vue | 4 +-
ui/src/views/network/LoadBalancing.vue | 121 ++++++++++++---------
10 files changed, 97 insertions(+), 72 deletions(-)
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java
index 45e6f81a0aa..66a15984ae4 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java
@@ -68,7 +68,7 @@ public class CreateLBStickinessPolicyCmd extends
BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.METHOD_NAME,
type = CommandType.STRING,
required = true,
- description = "name of the load balancer stickiness policy
method, possible values can be obtained from listNetworks API")
+ description = "name of the load balancer stickiness policy
method, possible values are LbCookie, AppCookie, SourceBased")
private String stickinessMethodName;
@Parameter(name = ApiConstants.PARAM_LIST, type = CommandType.MAP,
description = "param list. Example:
param[0].name=cookiename¶m[0].value=LBCookie ")
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index dfa813238be..5284a3b1379 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -123,6 +123,7 @@
"label.action.expunge.instance": "Expunge instance",
"label.action.force.reconnect": "Force reconnect",
"label.action.generate.keys": "Generate keys",
+"label.action.generate.api.secret.keys": "Generate New API/Secret Keys",
"label.action.get.diagnostics": "Get diagnostics data",
"label.action.health.monitor": "Health monitor",
"label.action.image.store.read.only": "Make image store read-only",
@@ -2691,7 +2692,7 @@
"message.failed.to.add": "Failed to add",
"message.failed.to.assign.vms": "Failed to assign VMs",
"message.failed.to.remove": "Failed to remove",
-"message.generate.keys": "Please confirm that you would like to generate new
keys for this user.",
+"message.generate.keys": "Please confirm that you would like to generate new
API/Secret keys for this user.",
"message.chart.statistic.info": "The shown charts are self-adjustable, that
means, if the value gets close to the limit or overpass it, it will grow to
adjust the shown value",
"message.guest.traffic.in.advanced.zone": "Guest network traffic is
communication between end-user virtual machines. Specify a range of VLAN IDs or
VXLAN network identifiers (VNIs) to carry guest traffic for each physical
network.",
"message.guest.traffic.in.basic.zone": "Guest network traffic is communication
between end-user virtual machines. Specify a range of IP addresses that
CloudStack can assign to guest VMs. Make sure this range does not overlap the
reserved system IP range.",
@@ -2743,6 +2744,7 @@
"message.linstor.resourcegroup.description": "Linstor resource group to use
for primary storage.",
"message.listnsp.not.return.providerid": "error: listNetworkServiceProviders
API doesn't return VirtualRouter provider ID.",
"message.load.host.failed": "Failed to load hosts.",
+"message.loadbalancer.stickypolicy.configuration": "Customize the load
balancer stickiness policy:",
"message.loading.add.interface.static.route": "Adding interface Static
Route...",
"message.loading.add.network.static.route": "Adding network Static Route...",
"message.loading.add.policy.rule": "Adding Policy rule...",
@@ -2786,6 +2788,7 @@
"message.network.offering.promiscuous.mode": "Applicable for guest networks on
VMware hypervisor only.\nReject - The switch drops any outbound frame from a
virtual machine adapter with a source MAC address that is different from the
one in the .vmx configuration file.\nAccept - The switch does not perform
filtering, and permits all outbound frames.\nNone - Default to value from
global setting.",
"message.network.removenic": "Please confirm that want to remove this NIC,
which will also remove the associated network from the VM.",
"message.network.secondaryip": "Please confirm that you would like to acquire
a new secondary IP for this NIC. \n NOTE: You need to manually configure the
newly-acquired secondary IP inside the virtual machine.",
+"message.network.selection": "Choose one or more networks to attach the
instance to. A new network can also be created here.",
"message.network.updateip": "Please confirm that you would like to change the
IP address for this NIC on VM.",
"message.network.usage.info.data.points": "Each data point represents the
difference in data traffic since the last data point.",
"message.network.usage.info.sum.of.vnics": "The network usage shown is made up
of the sum of data traffic from all the vNICs in the VM.",
diff --git a/ui/src/components/header/ProjectMenu.vue
b/ui/src/components/header/ProjectMenu.vue
index 722bc2877d6..11b1a7957e4 100644
--- a/ui/src/components/header/ProjectMenu.vue
+++ b/ui/src/components/header/ProjectMenu.vue
@@ -27,18 +27,6 @@
@focus="fetchData"
showSearch>
- <template #suffixIcon>
- <a-tooltip placement="bottom">
- <template #title>
- <span>{{ $t('label.projects') }}</span>
- </template>
- <span class="custom-suffix-icon">
- <ProjectOutlined v-if="!loading" class="ant-select-suffix" />
- <LoadingOutlined v-else />
- </span>
- </a-tooltip>
- </template>
-
<a-select-option
v-for="(project, index) in projects"
:key="index"
diff --git a/ui/src/components/view/ActionButton.vue
b/ui/src/components/view/ActionButton.vue
index 5f5761cbe1c..f15ec2fd9f3 100644
--- a/ui/src/components/view/ActionButton.vue
+++ b/ui/src/components/view/ActionButton.vue
@@ -47,7 +47,10 @@
:key="actionIndex"
arrowPointAtCenter
placement="bottomRight">
- <template #title>
+ <template v-if="action.hoverLabel" #title>
+ {{ $t(action.hoverLabel) }}
+ </template>
+ <template v-else #title>
{{ $t(action.label) }}
</template>
<a-badge
diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js
index c83c1ddb8fd..281479dc73c 100644
--- a/ui/src/config/section/network.js
+++ b/ui/src/config/section/network.js
@@ -130,6 +130,7 @@ export default {
icon: 'edit-outlined',
label: 'label.update.network',
dataView: true,
+ disabled: (record, user) => { return (record.account !==
user.userInfo.account && !['Admin',
'DomainAdmin'].includes(user.userInfo.roletype)) },
popup: true,
component: shallowRef(defineAsyncComponent(() =>
import('@/views/network/UpdateNetwork.vue')))
},
@@ -139,6 +140,7 @@ export default {
label: 'label.restart.network',
message: 'message.restart.network',
dataView: true,
+ disabled: (record, user) => { return (record.account !==
user.userInfo.account && !['Admin',
'DomainAdmin'].includes(user.userInfo.roletype)) },
args: (record, store, isGroupAction) => {
var fields = []
if (isGroupAction || record.vpcid == null) {
@@ -177,6 +179,7 @@ export default {
label: 'label.action.delete.network',
message: 'message.action.delete.network',
dataView: true,
+ disabled: (record, user) => { return (record.account !==
user.userInfo.account && !['Admin',
'DomainAdmin'].includes(user.userInfo.roletype)) },
groupAction: true,
popup: true,
groupMap: (selection) => { return selection.map(x => { return { id:
x } }) }
diff --git a/ui/src/config/section/user.js b/ui/src/config/section/user.js
index c5a3325e892..eef9ea3f939 100644
--- a/ui/src/config/section/user.js
+++ b/ui/src/config/section/user.js
@@ -68,6 +68,7 @@ export default {
api: 'registerUserKeys',
icon: 'file-protect-outlined',
label: 'label.action.generate.keys',
+ hoverLabel: 'label.action.generate.api.secret.keys',
message: 'message.generate.keys',
dataView: true
},
diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue
index fd241fee163..44c5b5bea19 100644
--- a/ui/src/views/AutogenView.vue
+++ b/ui/src/views/AutogenView.vue
@@ -20,7 +20,7 @@
<a-affix :offsetTop="this.$store.getters.shutdownTriggered ? 103 : 78">
<a-card class="breadcrumb-card" style="z-index: 10">
<a-row>
- <a-col :span="device === 'mobile' ? 24 : 12" style="padding-left:
12px">
+ <a-col :span="device === 'mobile' ? 24 : 12" style="padding-left:
12px; margin-top: 10px">
<breadcrumb :resource="resource">
<template #end>
<a-button
@@ -34,14 +34,14 @@
</a-button>
<a-switch
v-if="!dataView && ['vm', 'volume', 'zone', 'cluster',
'host', 'storagepool', 'managementserver'].includes($route.name)"
- style="margin-left: 8px"
+ style="margin-left: 8px; margin-bottom: 3px"
:checked-children="$t('label.metrics')"
:un-checked-children="$t('label.metrics')"
:checked="$store.getters.metrics"
@change="(checked, event) => { $store.dispatch('SetMetrics',
checked) }"/>
<a-switch
v-if="!projectView && hasProjectId"
- style="margin-left: 8px"
+ style="margin-left: 8px; margin-bottom: 3px"
:checked-children="$t('label.projects')"
:un-checked-children="$t('label.projects')"
:checked="$store.getters.listAllProjects"
@@ -54,7 +54,7 @@
v-if="!dataView && filters && filters.length > 0"
:placeholder="$t('label.filterby')"
:value="filterValue"
- style="min-width: 120px; margin-left: 10px"
+ style="min-width: 120px; margin-left: 10px; margin-top:
-4px"
@change="changeFilter"
showSearch
optionFilterProp="label"
@@ -84,7 +84,7 @@
</a-col>
<a-col
:span="device === 'mobile' ? 24 : 12"
- :style="device === 'mobile' ? { float: 'right', 'margin-top':
'12px', 'margin-bottom': '-6px', display: 'table' } : { float: 'right',
display: 'table', 'margin-bottom': '-6px' }" >
+ :style="device === 'mobile' ? { float: 'right', 'margin-top':
'12px', 'margin-bottom': '-6px', display: 'table' } : { float: 'right',
display: 'table', 'margin-bottom': '-4px' }" >
<slot name="action" v-if="dataView &&
$route.path.startsWith('/publicip')"></slot>
<action-button
v-else
@@ -99,6 +99,7 @@
<search-view
v-if="!dataView"
:searchFilters="searchFilters"
+ style="min-width: 120px; margin-left: 10px; margin-top: 5px"
:searchParams="searchParams"
:apiName="apiName"
@search="onSearch"
diff --git a/ui/src/views/compute/DeployVM.vue
b/ui/src/views/compute/DeployVM.vue
index 42eda874a87..064dac21e79 100644
--- a/ui/src/views/compute/DeployVM.vue
+++ b/ui/src/views/compute/DeployVM.vue
@@ -387,7 +387,10 @@
:status="zoneSelected ? 'process' : 'wait'"
v-if="zone && zone.networktype !== 'Basic'">
<template #description>
- <div v-if="zoneSelected">
+ <div v-if="zoneSelected" style="margin-top: 5px">
+ <div style="margin-bottom: 10px">
+ {{ $t('message.network.selection') }}
+ </div>
<div v-if="vm.templateid && templateNics &&
templateNics.length > 0">
<instance-nics-network-select-list-view
:nics="templateNics"
diff --git a/ui/src/views/infra/InfraSummary.vue
b/ui/src/views/infra/InfraSummary.vue
index 941d15b440d..8411dca373c 100644
--- a/ui/src/views/infra/InfraSummary.vue
+++ b/ui/src/views/infra/InfraSummary.vue
@@ -149,8 +149,10 @@
</a-col>
<template v-for="(section, index) in sections" :key="index">
<a-col
+ :xs="12"
+ :sm="8"
:md="6"
- style="margin-bottom: 12px"
+ :style="{ marginBottom: '12px' }"
v-if="routes[section]">
<chart-card :loading="loading">
<div class="chart-card-inner">
diff --git a/ui/src/views/network/LoadBalancing.vue
b/ui/src/views/network/LoadBalancing.vue
index 460d3529a0e..a03bc38e71f 100644
--- a/ui/src/views/network/LoadBalancing.vue
+++ b/ui/src/views/network/LoadBalancing.vue
@@ -267,7 +267,6 @@
</a-modal>
<a-modal
- :title="$t('label.configure.sticky.policy')"
:visible="stickinessModalVisible"
:footer="null"
:afterClose="closeModal"
@@ -276,6 +275,16 @@
:okButtonProps="{ props: {htmlType: 'submit'}}"
@cancel="stickinessModalVisible = false">
+ <template #title>
+ <span>{{ $t('label.configure.sticky.policy') }}</span>
+ <a
+ style="margin-left: 5px"
+ :href="$config.docBase +
'/adminguide/networking/external_firewalls_and_load_balancers.html#sticky-session-policies-for-load-balancer-rules'"
+ target="_blank">
+ <question-circle-outlined />
+ </a>
+ </template>
+
<span v-show="stickinessModalLoading" class="modal-loading">
<loading-outlined />
</span>
@@ -288,7 +297,10 @@
v-ctrl-enter="handleSubmitStickinessForm"
class="custom-ant-form"
>
- <a-form-item name="methodname" ref="methodname"
:label="$t('label.stickiness.method')">
+ <a-form-item name="methodname" ref="methodname">
+ <template #label>
+ <tooltip-label :title="$t('label.stickiness.method')"
:tooltip="createLoadBalancerStickinessPolicyParams.methodname.description"
:tooltip-placement="'right'"/>
+ </template>
<a-select
v-focus="true"
v-model:value="form.methodname"
@@ -307,58 +319,66 @@
<a-form-item
name="name"
ref="name"
- :label="$t('label.sticky.name')"
v-show="stickinessPolicyMethod === 'LbCookie' ||
stickinessPolicyMethod ===
'AppCookie' || stickinessPolicyMethod === 'SourceBased'">
<a-input v-model:value="form.name" />
+ <template #label>
+ <tooltip-label :title="$t('label.sticky.name')"
:tooltip="createLoadBalancerStickinessPolicyParams.name.description"
:tooltip-placement="'right'"/>
+ </template>
</a-form-item>
- <a-form-item
- name="cookieName"
- ref="cookieName"
- :label="$t('label.sticky.cookie-name')"
- v-show="stickinessPolicyMethod === 'LbCookie' ||
stickinessPolicyMethod ===
- 'AppCookie'">
- <a-input v-model:value="form.cookieName" />
- </a-form-item>
- <a-form-item
- name="mode"
- ref="mode"
- :label="$t('label.sticky.mode')"
- v-show="stickinessPolicyMethod === 'LbCookie' ||
stickinessPolicyMethod ===
- 'AppCookie'">
- <a-input v-model:value="form.mode" />
- </a-form-item>
- <a-form-item name="nocache" ref="nocache"
:label="$t('label.sticky.nocache')" v-show="stickinessPolicyMethod ===
'LbCookie'">
- <a-checkbox v-model:checked="form.nocache"></a-checkbox>
- </a-form-item>
- <a-form-item name="indirect" ref="indirect"
:label="$t('label.sticky.indirect')" v-show="stickinessPolicyMethod ===
'LbCookie'">
- <a-checkbox v-model:checked="form.indirect"></a-checkbox>
- </a-form-item>
- <a-form-item name="postonly" ref="postonly"
:label="$t('label.sticky.postonly')" v-show="stickinessPolicyMethod ===
'LbCookie'">
- <a-checkbox v-model:checked="form.postonly"></a-checkbox>
- </a-form-item>
- <a-form-item name="domain" ref="domain" :label="$t('label.domain')"
v-show="stickinessPolicyMethod === 'LbCookie'">
- <a-input v-model:value="form.domain" />
- </a-form-item>
- <a-form-item name="length" ref="length"
:label="$t('label.sticky.length')" v-show="stickinessPolicyMethod ===
'AppCookie'">
- <a-input v-model:value="form.length" type="number" />
- </a-form-item>
- <a-form-item name="holdtime" ref="holdtime"
:label="$t('label.sticky.holdtime')" v-show="stickinessPolicyMethod ===
'AppCookie'">
- <a-input v-model:value="form.holdtime" type="number" />
- </a-form-item>
- <a-form-item name="requestLearn" ref="requestLearn"
:label="$t('label.sticky.request-learn')" v-show="stickinessPolicyMethod ===
'AppCookie'">
- <a-checkbox v-model:checked="form.requestLearn"></a-checkbox>
- </a-form-item>
- <a-form-item name="prefix" ref="prefix"
:label="$t('label.sticky.prefix')" v-show="stickinessPolicyMethod ===
'AppCookie'">
- <a-checkbox v-model:checked="form.prefix"></a-checkbox>
- </a-form-item>
- <a-form-item name="tablesize" ref="tablesize"
:label="$t('label.sticky.tablesize')" v-show="stickinessPolicyMethod ===
'SourceBased'">
- <a-input v-model:value="form.tablesize" />
- </a-form-item>
- <a-form-item name="expire" ref="expire"
:label="$t('label.sticky.expire')" v-show="stickinessPolicyMethod ===
'SourceBased'">
- <a-input v-model:value="form.expire" />
- </a-form-item>
-
+ <div v-if="stickinessPolicyMethod !== 'none'">
+ <br/>
+ {{ $t('message.loadbalancer.stickypolicy.configuration') }}
+ <br/>
+ <a-card>
+ <a-form-item
+ name="cookieName"
+ ref="cookieName"
+ :label="$t('label.sticky.cookie-name')"
+ v-show="stickinessPolicyMethod === 'LbCookie' ||
stickinessPolicyMethod ===
+ 'AppCookie'">
+ <a-input v-model:value="form.cookieName" />
+ </a-form-item>
+ <a-form-item
+ name="mode"
+ ref="mode"
+ :label="$t('label.sticky.mode')"
+ v-show="stickinessPolicyMethod === 'LbCookie' ||
stickinessPolicyMethod ===
+ 'AppCookie'">
+ <a-input v-model:value="form.mode" />
+ </a-form-item>
+ <a-form-item name="nocache" ref="nocache"
:label="$t('label.sticky.nocache')" v-show="stickinessPolicyMethod ===
'LbCookie'">
+ <a-checkbox v-model:checked="form.nocache"></a-checkbox>
+ </a-form-item>
+ <a-form-item name="indirect" ref="indirect"
:label="$t('label.sticky.indirect')" v-show="stickinessPolicyMethod ===
'LbCookie'">
+ <a-checkbox v-model:checked="form.indirect"></a-checkbox>
+ </a-form-item>
+ <a-form-item name="postonly" ref="postonly"
:label="$t('label.sticky.postonly')" v-show="stickinessPolicyMethod ===
'LbCookie'">
+ <a-checkbox v-model:checked="form.postonly"></a-checkbox>
+ </a-form-item>
+ <a-form-item name="domain" ref="domain"
:label="$t('label.domain')" v-show="stickinessPolicyMethod === 'LbCookie'">
+ <a-input v-model:value="form.domain" />
+ </a-form-item>
+ <a-form-item name="length" ref="length"
:label="$t('label.sticky.length')" v-show="stickinessPolicyMethod ===
'AppCookie'">
+ <a-input v-model:value="form.length" type="number" />
+ </a-form-item>
+ <a-form-item name="holdtime" ref="holdtime"
:label="$t('label.sticky.holdtime')" v-show="stickinessPolicyMethod ===
'AppCookie'">
+ <a-input v-model:value="form.holdtime" type="number" />
+ </a-form-item>
+ <a-form-item name="requestLearn" ref="requestLearn"
:label="$t('label.sticky.request-learn')" v-show="stickinessPolicyMethod ===
'AppCookie'">
+ <a-checkbox v-model:checked="form.requestLearn"></a-checkbox>
+ </a-form-item>
+ <a-form-item name="prefix" ref="prefix"
:label="$t('label.sticky.prefix')" v-show="stickinessPolicyMethod ===
'AppCookie'">
+ <a-checkbox v-model:checked="form.prefix"></a-checkbox>
+ </a-form-item>
+ <a-form-item name="tablesize" ref="tablesize"
:label="$t('label.sticky.tablesize')" v-show="stickinessPolicyMethod ===
'SourceBased'">
+ <a-input v-model:value="form.tablesize" />
+ </a-form-item>
+ <a-form-item name="expire" ref="expire"
:label="$t('label.sticky.expire')" v-show="stickinessPolicyMethod ===
'SourceBased'">
+ <a-input v-model:value="form.expire" />
+ </a-form-item>
+ </a-card>
+ </div>
<div :span="24" class="action-button">
<a-button @click="stickinessModalVisible = false">{{
$t('label.cancel') }}</a-button>
<a-button type="primary" ref="submit"
@click="handleSubmitStickinessForm">{{ $t('label.ok') }}</a-button>
@@ -804,6 +824,7 @@ export default {
},
beforeCreate () {
this.createLoadBalancerRuleParams =
this.$getApiParams('createLoadBalancerRule')
+ this.createLoadBalancerStickinessPolicyParams =
this.$getApiParams('createLBStickinessPolicy')
},
created () {
this.initForm()