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
This commit is contained in:
Harikrishna 2023-05-02 17:06:54 +05:30 committed by GitHub
parent 8b5bfb145e
commit b280370a98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 97 additions and 72 deletions

View File

@ -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&param[0].value=LBCookie ")

View File

@ -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.",

View File

@ -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"

View File

@ -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

View File

@ -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 } }) }

View File

@ -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
},

View File

@ -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"

View File

@ -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"

View File

@ -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">

View File

@ -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()