Skip to content

Commit b280370

Browse files
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
1 parent 8b5bfb1 commit b280370

10 files changed

Lines changed: 97 additions & 72 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd {
6868
@Parameter(name = ApiConstants.METHOD_NAME,
6969
type = CommandType.STRING,
7070
required = true,
71-
description = "name of the load balancer stickiness policy method, possible values can be obtained from listNetworks API")
71+
description = "name of the load balancer stickiness policy method, possible values are LbCookie, AppCookie, SourceBased")
7272
private String stickinessMethodName;
7373

7474
@Parameter(name = ApiConstants.PARAM_LIST, type = CommandType.MAP, description = "param list. Example: param[0].name=cookiename&param[0].value=LBCookie ")

ui/public/locales/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
"label.action.expunge.instance": "Expunge instance",
124124
"label.action.force.reconnect": "Force reconnect",
125125
"label.action.generate.keys": "Generate keys",
126+
"label.action.generate.api.secret.keys": "Generate New API/Secret Keys",
126127
"label.action.get.diagnostics": "Get diagnostics data",
127128
"label.action.health.monitor": "Health monitor",
128129
"label.action.image.store.read.only": "Make image store read-only",
@@ -2691,7 +2692,7 @@
26912692
"message.failed.to.add": "Failed to add",
26922693
"message.failed.to.assign.vms": "Failed to assign VMs",
26932694
"message.failed.to.remove": "Failed to remove",
2694-
"message.generate.keys": "Please confirm that you would like to generate new keys for this user.",
2695+
"message.generate.keys": "Please confirm that you would like to generate new API/Secret keys for this user.",
26952696
"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",
26962697
"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.",
26972698
"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 @@
27432744
"message.linstor.resourcegroup.description": "Linstor resource group to use for primary storage.",
27442745
"message.listnsp.not.return.providerid": "error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID.",
27452746
"message.load.host.failed": "Failed to load hosts.",
2747+
"message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:",
27462748
"message.loading.add.interface.static.route": "Adding interface Static Route...",
27472749
"message.loading.add.network.static.route": "Adding network Static Route...",
27482750
"message.loading.add.policy.rule": "Adding Policy rule...",
@@ -2786,6 +2788,7 @@
27862788
"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.",
27872789
"message.network.removenic": "Please confirm that want to remove this NIC, which will also remove the associated network from the VM.",
27882790
"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.",
2791+
"message.network.selection": "Choose one or more networks to attach the instance to. A new network can also be created here.",
27892792
"message.network.updateip": "Please confirm that you would like to change the IP address for this NIC on VM.",
27902793
"message.network.usage.info.data.points": "Each data point represents the difference in data traffic since the last data point.",
27912794
"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.",

ui/src/components/header/ProjectMenu.vue

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,6 @@
2727
@focus="fetchData"
2828
showSearch>
2929

30-
<template #suffixIcon>
31-
<a-tooltip placement="bottom">
32-
<template #title>
33-
<span>{{ $t('label.projects') }}</span>
34-
</template>
35-
<span class="custom-suffix-icon">
36-
<ProjectOutlined v-if="!loading" class="ant-select-suffix" />
37-
<LoadingOutlined v-else />
38-
</span>
39-
</a-tooltip>
40-
</template>
41-
4230
<a-select-option
4331
v-for="(project, index) in projects"
4432
:key="index"

ui/src/components/view/ActionButton.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@
4747
:key="actionIndex"
4848
arrowPointAtCenter
4949
placement="bottomRight">
50-
<template #title>
50+
<template v-if="action.hoverLabel" #title>
51+
{{ $t(action.hoverLabel) }}
52+
</template>
53+
<template v-else #title>
5154
{{ $t(action.label) }}
5255
</template>
5356
<a-badge

ui/src/config/section/network.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export default {
130130
icon: 'edit-outlined',
131131
label: 'label.update.network',
132132
dataView: true,
133+
disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) },
133134
popup: true,
134135
component: shallowRef(defineAsyncComponent(() => import('@/views/network/UpdateNetwork.vue')))
135136
},
@@ -139,6 +140,7 @@ export default {
139140
label: 'label.restart.network',
140141
message: 'message.restart.network',
141142
dataView: true,
143+
disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) },
142144
args: (record, store, isGroupAction) => {
143145
var fields = []
144146
if (isGroupAction || record.vpcid == null) {
@@ -177,6 +179,7 @@ export default {
177179
label: 'label.action.delete.network',
178180
message: 'message.action.delete.network',
179181
dataView: true,
182+
disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) },
180183
groupAction: true,
181184
popup: true,
182185
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }

ui/src/config/section/user.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export default {
6868
api: 'registerUserKeys',
6969
icon: 'file-protect-outlined',
7070
label: 'label.action.generate.keys',
71+
hoverLabel: 'label.action.generate.api.secret.keys',
7172
message: 'message.generate.keys',
7273
dataView: true
7374
},

ui/src/views/AutogenView.vue

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<a-affix :offsetTop="this.$store.getters.shutdownTriggered ? 103 : 78">
2121
<a-card class="breadcrumb-card" style="z-index: 10">
2222
<a-row>
23-
<a-col :span="device === 'mobile' ? 24 : 12" style="padding-left: 12px">
23+
<a-col :span="device === 'mobile' ? 24 : 12" style="padding-left: 12px; margin-top: 10px">
2424
<breadcrumb :resource="resource">
2525
<template #end>
2626
<a-button
@@ -34,14 +34,14 @@
3434
</a-button>
3535
<a-switch
3636
v-if="!dataView && ['vm', 'volume', 'zone', 'cluster', 'host', 'storagepool', 'managementserver'].includes($route.name)"
37-
style="margin-left: 8px"
37+
style="margin-left: 8px; margin-bottom: 3px"
3838
:checked-children="$t('label.metrics')"
3939
:un-checked-children="$t('label.metrics')"
4040
:checked="$store.getters.metrics"
4141
@change="(checked, event) => { $store.dispatch('SetMetrics', checked) }"/>
4242
<a-switch
4343
v-if="!projectView && hasProjectId"
44-
style="margin-left: 8px"
44+
style="margin-left: 8px; margin-bottom: 3px"
4545
:checked-children="$t('label.projects')"
4646
:un-checked-children="$t('label.projects')"
4747
:checked="$store.getters.listAllProjects"
@@ -54,7 +54,7 @@
5454
v-if="!dataView && filters && filters.length > 0"
5555
:placeholder="$t('label.filterby')"
5656
:value="filterValue"
57-
style="min-width: 120px; margin-left: 10px"
57+
style="min-width: 120px; margin-left: 10px; margin-top: -4px"
5858
@change="changeFilter"
5959
showSearch
6060
optionFilterProp="label"
@@ -84,7 +84,7 @@
8484
</a-col>
8585
<a-col
8686
:span="device === 'mobile' ? 24 : 12"
87-
:style="device === 'mobile' ? { float: 'right', 'margin-top': '12px', 'margin-bottom': '-6px', display: 'table' } : { float: 'right', display: 'table', 'margin-bottom': '-6px' }" >
87+
:style="device === 'mobile' ? { float: 'right', 'margin-top': '12px', 'margin-bottom': '-6px', display: 'table' } : { float: 'right', display: 'table', 'margin-bottom': '-4px' }" >
8888
<slot name="action" v-if="dataView && $route.path.startsWith('/publicip')"></slot>
8989
<action-button
9090
v-else
@@ -99,6 +99,7 @@
9999
<search-view
100100
v-if="!dataView"
101101
:searchFilters="searchFilters"
102+
style="min-width: 120px; margin-left: 10px; margin-top: 5px"
102103
:searchParams="searchParams"
103104
:apiName="apiName"
104105
@search="onSearch"

ui/src/views/compute/DeployVM.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,10 @@
387387
:status="zoneSelected ? 'process' : 'wait'"
388388
v-if="zone && zone.networktype !== 'Basic'">
389389
<template #description>
390-
<div v-if="zoneSelected">
390+
<div v-if="zoneSelected" style="margin-top: 5px">
391+
<div style="margin-bottom: 10px">
392+
{{ $t('message.network.selection') }}
393+
</div>
391394
<div v-if="vm.templateid && templateNics && templateNics.length > 0">
392395
<instance-nics-network-select-list-view
393396
:nics="templateNics"

ui/src/views/infra/InfraSummary.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,10 @@
149149
</a-col>
150150
<template v-for="(section, index) in sections" :key="index">
151151
<a-col
152+
:xs="12"
153+
:sm="8"
152154
:md="6"
153-
style="margin-bottom: 12px"
155+
:style="{ marginBottom: '12px' }"
154156
v-if="routes[section]">
155157
<chart-card :loading="loading">
156158
<div class="chart-card-inner">

ui/src/views/network/LoadBalancing.vue

Lines changed: 71 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@
267267
</a-modal>
268268

269269
<a-modal
270-
:title="$t('label.configure.sticky.policy')"
271270
:visible="stickinessModalVisible"
272271
:footer="null"
273272
:afterClose="closeModal"
@@ -276,6 +275,16 @@
276275
:okButtonProps="{ props: {htmlType: 'submit'}}"
277276
@cancel="stickinessModalVisible = false">
278277

278+
<template #title>
279+
<span>{{ $t('label.configure.sticky.policy') }}</span>
280+
<a
281+
style="margin-left: 5px"
282+
:href="$config.docBase + '/adminguide/networking/external_firewalls_and_load_balancers.html#sticky-session-policies-for-load-balancer-rules'"
283+
target="_blank">
284+
<question-circle-outlined />
285+
</a>
286+
</template>
287+
279288
<span v-show="stickinessModalLoading" class="modal-loading">
280289
<loading-outlined />
281290
</span>
@@ -288,7 +297,10 @@
288297
v-ctrl-enter="handleSubmitStickinessForm"
289298
class="custom-ant-form"
290299
>
291-
<a-form-item name="methodname" ref="methodname" :label="$t('label.stickiness.method')">
300+
<a-form-item name="methodname" ref="methodname">
301+
<template #label>
302+
<tooltip-label :title="$t('label.stickiness.method')" :tooltip="createLoadBalancerStickinessPolicyParams.methodname.description" :tooltip-placement="'right'"/>
303+
</template>
292304
<a-select
293305
v-focus="true"
294306
v-model:value="form.methodname"
@@ -307,58 +319,66 @@
307319
<a-form-item
308320
name="name"
309321
ref="name"
310-
:label="$t('label.sticky.name')"
311322
v-show="stickinessPolicyMethod === 'LbCookie' || stickinessPolicyMethod ===
312323
'AppCookie' || stickinessPolicyMethod === 'SourceBased'">
313324
<a-input v-model:value="form.name" />
325+
<template #label>
326+
<tooltip-label :title="$t('label.sticky.name')" :tooltip="createLoadBalancerStickinessPolicyParams.name.description" :tooltip-placement="'right'"/>
327+
</template>
314328
</a-form-item>
315-
<a-form-item
316-
name="cookieName"
317-
ref="cookieName"
318-
:label="$t('label.sticky.cookie-name')"
319-
v-show="stickinessPolicyMethod === 'LbCookie' || stickinessPolicyMethod ===
320-
'AppCookie'">
321-
<a-input v-model:value="form.cookieName" />
322-
</a-form-item>
323-
<a-form-item
324-
name="mode"
325-
ref="mode"
326-
:label="$t('label.sticky.mode')"
327-
v-show="stickinessPolicyMethod === 'LbCookie' || stickinessPolicyMethod ===
328-
'AppCookie'">
329-
<a-input v-model:value="form.mode" />
330-
</a-form-item>
331-
<a-form-item name="nocache" ref="nocache" :label="$t('label.sticky.nocache')" v-show="stickinessPolicyMethod === 'LbCookie'">
332-
<a-checkbox v-model:checked="form.nocache"></a-checkbox>
333-
</a-form-item>
334-
<a-form-item name="indirect" ref="indirect" :label="$t('label.sticky.indirect')" v-show="stickinessPolicyMethod === 'LbCookie'">
335-
<a-checkbox v-model:checked="form.indirect"></a-checkbox>
336-
</a-form-item>
337-
<a-form-item name="postonly" ref="postonly" :label="$t('label.sticky.postonly')" v-show="stickinessPolicyMethod === 'LbCookie'">
338-
<a-checkbox v-model:checked="form.postonly"></a-checkbox>
339-
</a-form-item>
340-
<a-form-item name="domain" ref="domain" :label="$t('label.domain')" v-show="stickinessPolicyMethod === 'LbCookie'">
341-
<a-input v-model:value="form.domain" />
342-
</a-form-item>
343-
<a-form-item name="length" ref="length" :label="$t('label.sticky.length')" v-show="stickinessPolicyMethod === 'AppCookie'">
344-
<a-input v-model:value="form.length" type="number" />
345-
</a-form-item>
346-
<a-form-item name="holdtime" ref="holdtime" :label="$t('label.sticky.holdtime')" v-show="stickinessPolicyMethod === 'AppCookie'">
347-
<a-input v-model:value="form.holdtime" type="number" />
348-
</a-form-item>
349-
<a-form-item name="requestLearn" ref="requestLearn" :label="$t('label.sticky.request-learn')" v-show="stickinessPolicyMethod === 'AppCookie'">
350-
<a-checkbox v-model:checked="form.requestLearn"></a-checkbox>
351-
</a-form-item>
352-
<a-form-item name="prefix" ref="prefix" :label="$t('label.sticky.prefix')" v-show="stickinessPolicyMethod === 'AppCookie'">
353-
<a-checkbox v-model:checked="form.prefix"></a-checkbox>
354-
</a-form-item>
355-
<a-form-item name="tablesize" ref="tablesize" :label="$t('label.sticky.tablesize')" v-show="stickinessPolicyMethod === 'SourceBased'">
356-
<a-input v-model:value="form.tablesize" />
357-
</a-form-item>
358-
<a-form-item name="expire" ref="expire" :label="$t('label.sticky.expire')" v-show="stickinessPolicyMethod === 'SourceBased'">
359-
<a-input v-model:value="form.expire" />
360-
</a-form-item>
361-
329+
<div v-if="stickinessPolicyMethod !== 'none'">
330+
<br/>
331+
{{ $t('message.loadbalancer.stickypolicy.configuration') }}
332+
<br/>
333+
<a-card>
334+
<a-form-item
335+
name="cookieName"
336+
ref="cookieName"
337+
:label="$t('label.sticky.cookie-name')"
338+
v-show="stickinessPolicyMethod === 'LbCookie' || stickinessPolicyMethod ===
339+
'AppCookie'">
340+
<a-input v-model:value="form.cookieName" />
341+
</a-form-item>
342+
<a-form-item
343+
name="mode"
344+
ref="mode"
345+
:label="$t('label.sticky.mode')"
346+
v-show="stickinessPolicyMethod === 'LbCookie' || stickinessPolicyMethod ===
347+
'AppCookie'">
348+
<a-input v-model:value="form.mode" />
349+
</a-form-item>
350+
<a-form-item name="nocache" ref="nocache" :label="$t('label.sticky.nocache')" v-show="stickinessPolicyMethod === 'LbCookie'">
351+
<a-checkbox v-model:checked="form.nocache"></a-checkbox>
352+
</a-form-item>
353+
<a-form-item name="indirect" ref="indirect" :label="$t('label.sticky.indirect')" v-show="stickinessPolicyMethod === 'LbCookie'">
354+
<a-checkbox v-model:checked="form.indirect"></a-checkbox>
355+
</a-form-item>
356+
<a-form-item name="postonly" ref="postonly" :label="$t('label.sticky.postonly')" v-show="stickinessPolicyMethod === 'LbCookie'">
357+
<a-checkbox v-model:checked="form.postonly"></a-checkbox>
358+
</a-form-item>
359+
<a-form-item name="domain" ref="domain" :label="$t('label.domain')" v-show="stickinessPolicyMethod === 'LbCookie'">
360+
<a-input v-model:value="form.domain" />
361+
</a-form-item>
362+
<a-form-item name="length" ref="length" :label="$t('label.sticky.length')" v-show="stickinessPolicyMethod === 'AppCookie'">
363+
<a-input v-model:value="form.length" type="number" />
364+
</a-form-item>
365+
<a-form-item name="holdtime" ref="holdtime" :label="$t('label.sticky.holdtime')" v-show="stickinessPolicyMethod === 'AppCookie'">
366+
<a-input v-model:value="form.holdtime" type="number" />
367+
</a-form-item>
368+
<a-form-item name="requestLearn" ref="requestLearn" :label="$t('label.sticky.request-learn')" v-show="stickinessPolicyMethod === 'AppCookie'">
369+
<a-checkbox v-model:checked="form.requestLearn"></a-checkbox>
370+
</a-form-item>
371+
<a-form-item name="prefix" ref="prefix" :label="$t('label.sticky.prefix')" v-show="stickinessPolicyMethod === 'AppCookie'">
372+
<a-checkbox v-model:checked="form.prefix"></a-checkbox>
373+
</a-form-item>
374+
<a-form-item name="tablesize" ref="tablesize" :label="$t('label.sticky.tablesize')" v-show="stickinessPolicyMethod === 'SourceBased'">
375+
<a-input v-model:value="form.tablesize" />
376+
</a-form-item>
377+
<a-form-item name="expire" ref="expire" :label="$t('label.sticky.expire')" v-show="stickinessPolicyMethod === 'SourceBased'">
378+
<a-input v-model:value="form.expire" />
379+
</a-form-item>
380+
</a-card>
381+
</div>
362382
<div :span="24" class="action-button">
363383
<a-button @click="stickinessModalVisible = false">{{ $t('label.cancel') }}</a-button>
364384
<a-button type="primary" ref="submit" @click="handleSubmitStickinessForm">{{ $t('label.ok') }}</a-button>
@@ -804,6 +824,7 @@ export default {
804824
},
805825
beforeCreate () {
806826
this.createLoadBalancerRuleParams = this.$getApiParams('createLoadBalancerRule')
827+
this.createLoadBalancerStickinessPolicyParams = this.$getApiParams('createLBStickinessPolicy')
807828
},
808829
created () {
809830
this.initForm()

0 commit comments

Comments
 (0)