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

commit 62feb24de657772a01ed145e0a6476306a1d7374
Merge: 540dcc1040a feb9509547a
Author: Rohit Yadav <rohit.ya...@shapeblue.com>
AuthorDate: Fri Aug 11 15:15:27 2023 +0530

    Merge remote-tracking branch 'origin/4.18'
    
    Signed-off-by: Rohit Yadav <rohit.ya...@shapeblue.com>

 ui/public/locales/en.json                          |  7 ++-
 ui/src/components/header/UserMenu.vue              |  9 ++-
 ui/src/components/menu/SideMenu.vue                |  2 -
 ui/src/components/view/DetailsTab.vue              | 15 +++++
 ui/src/components/view/InfoCard.vue                | 72 +++++++++++++++-------
 ui/src/components/view/ListView.vue                | 39 ++++++++++--
 ui/src/components/widgets/CopyLabel.vue            | 51 +++++++++++++++
 ui/src/config/section/account.js                   |  4 +-
 ui/src/config/section/compute.js                   | 22 ++++---
 ui/src/config/section/domain.js                    |  4 +-
 ui/src/config/section/image.js                     | 26 ++++++--
 ui/src/config/section/network.js                   | 16 ++---
 ui/src/config/section/project.js                   |  4 +-
 ui/src/config/section/storage.js                   | 13 ++--
 ui/src/views/compute/CreateAutoScaleVmGroup.vue    | 38 ++++++++----
 ui/src/views/compute/DeployVM.vue                  | 40 +++++++-----
 ui/src/views/compute/InstanceTab.vue               | 43 +++++++++++--
 .../views/compute/wizard/TemplateIsoRadioGroup.vue | 14 ++---
 ui/src/views/dashboard/CapacityDashboard.vue       |  2 +-
 ui/src/views/image/TemplateZones.vue               |  4 +-
 ui/src/views/storage/CreateVolume.vue              | 39 +++++++++++-
 21 files changed, 354 insertions(+), 110 deletions(-)

diff --cc ui/src/components/header/UserMenu.vue
index 42df0446463,0c7434594be..dfa84c77b65
--- a/ui/src/components/header/UserMenu.vue
+++ b/ui/src/components/header/UserMenu.vue
@@@ -27,36 -27,50 +27,40 @@@
      <a-dropdown>
        <span class="user-menu-dropdown action">
          <span v-if="image">
-           <resource-icon :image="image" size="2x" style="margin-right: 5px"/>
+           <resource-icon :image="image" size="4x" style="margin-right: 5px; 
margin-top: -3px"/>
          </span>
 -        <a-avatar v-else-if="userInitials" class="user-menu-avatar avatar" 
size="small" :style="{ backgroundColor: '#1890ff', color: 'white' }">
 +        <a-avatar v-else-if="userInitials" class="user-menu-avatar avatar" 
size="small" :style="{ backgroundColor: $config.theme['@primary-color'], color: 
'white' }">
            {{ userInitials }}
          </a-avatar>
 -        <a-avatar v-else class="user-menu-avatar avatar" size="small" 
:style="{ backgroundColor: '#1890ff', color: 'white' }">
 +        <a-avatar v-else class="user-menu-avatar avatar" size="small" 
:style="{ backgroundColor: $config.theme['@primary-color'], color: 'white' }">
            <template #icon><user-outlined /></template>
          </a-avatar>
          <span>{{ nickname() }}</span>
        </span>
        <template #overlay>
 -        <a-menu class="user-menu-wrapper">
 -          <router-link :to="{ path: '/accountuser/' + 
$store.getters.userInfo.id }">
 -            <a-menu-item class="user-menu-item" key="0">
 -                <UserOutlined class="user-menu-item-icon" />
 -                <span class="user-menu-item-name">{{ $t('label.profilename') 
}}</span>
 -            </a-menu-item>
 -          </router-link>
 -          <router-link :to="{ path: '/account/' + 
$store.getters.userInfo.accountid, query: { tab: 'limits' } }">
 -            <a-menu-item class="user-menu-item" key="0">
 -                <ControlOutlined class="user-menu-item-icon" />
 -                <span class="user-menu-item-name">{{ $t('label.limits') 
}}</span>
 -            </a-menu-item>
 -          </router-link>
 -          <a @click="toggleUseBrowserTimezone">
 -            <a-menu-item class="user-menu-item" key="1">
 -                <ClockCircleOutlined class="user-menu-item-icon" />
 -                <span class="user-menu-item-name" style="margin-right: 
5px">{{ $t('label.use.local.timezone') }}</span>
 -                <a-switch :checked="$store.getters.usebrowsertimezone" />
 -            </a-menu-item>
 -          </a>
 -          <a :href="$config.docBase" target="_blank">
 -            <a-menu-item class="user-menu-item" key="2">
 -              <QuestionCircleOutlined class="user-menu-item-icon" />
 -              <span class="user-menu-item-name">{{ $t('label.help') }}</span>
 -            </a-menu-item>
 -          </a>
 +        <a-menu class="user-menu-wrapper" @click="handleClickMenu">
 +          <a-menu-item class="user-menu-item" key="profile">
 +            <UserOutlined class="user-menu-item-icon" />
 +            <span class="user-menu-item-name">{{ $t('label.profilename') 
}}</span>
 +          </a-menu-item>
++          <a-menu-item class="user-menu-item" key="limits">
++            <ControlOutlined class="user-menu-item-icon" />
++            <span class="user-menu-item-name">{{ $t('label.limits') }}</span>
++          </a-menu-item>
 +          <a-menu-item class="user-menu-item" key="timezone">
 +            <ClockCircleOutlined class="user-menu-item-icon" />
 +            <span class="user-menu-item-name" style="margin-right: 5px">{{ 
$t('label.use.local.timezone') }}</span>
 +            <a-switch :checked="$store.getters.usebrowsertimezone" />
 +          </a-menu-item>
 +          <a-menu-item class="user-menu-item" key="document">
 +            <QuestionCircleOutlined class="user-menu-item-icon" />
 +            <span class="user-menu-item-name">{{ $t('label.help') }}</span>
 +          </a-menu-item>
            <a-menu-divider/>
 -          <a href="javascript:;" @click="handleLogout">
 -            <a-menu-item class="user-menu-item" key="3">
 -              <LogoutOutlined class="user-menu-item-icon" />
 -              <span class="user-menu-item-name">{{ $t('label.logout') 
}}</span>
 -            </a-menu-item>
 -          </a>
 +          <a-menu-item class="user-menu-item" key="logout">
 +            <LogoutOutlined class="user-menu-item-icon" />
 +            <span class="user-menu-item-name">{{ $t('label.logout') }}</span>
 +          </a-menu-item>
          </a-menu>
        </template>
      </a-dropdown>
@@@ -137,22 -151,6 +141,25 @@@ export default 
          })
        })
      },
 +    handleClickMenu (item) {
 +      switch (item.key) {
 +        case 'profile':
 +          this.$router.push(`/accountuser/${this.$store.getters.userInfo.id}`)
 +          break
++        case 'limits':
++          
this.$router.push(`/account/${this.$store.getters.userInfo.accountid}?tab=limits`)
++          break
 +        case 'timezone':
 +          this.toggleUseBrowserTimezone()
 +          break
 +        case 'document':
 +          window.open(this.$config.docBase, '_blank')
 +          break
 +        case 'logout':
 +          this.handleLogout()
 +          break
 +      }
 +    },
      handleLogout () {
        return this.Logout({}).then(() => {
          this.$router.push('/user/login')
diff --cc ui/src/components/view/DetailsTab.vue
index e276e05bcb0,e359f14d86b..301686c3433
--- a/ui/src/components/view/DetailsTab.vue
+++ b/ui/src/components/view/DetailsTab.vue
@@@ -51,6 -51,21 +51,21 @@@
                {{ dataResource.rootdisksize }} GB
              </div>
            </div>
+           <div v-else-if="['template', 'iso'].includes($route.meta.name) && 
item === 'size'">
+             <div>
 -              {{ parseFloat(dataResource.size / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GB
++              {{ parseFloat(dataResource.size / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GiB
+             </div>
+           </div>
+           <div v-else-if="['volume', 'snapshot', 'template', 
'iso'].includes($route.meta.name) && item === 'physicalsize'">
+             <div>
 -              {{ parseFloat(dataResource.physicalsize / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GB
++              {{ parseFloat(dataResource.physicalsize / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GiB
+             </div>
+           </div>
+           <div v-else-if="['volume', 'snapshot', 'template', 
'iso'].includes($route.meta.name) && item === 'virtualsize'">
+             <div>
 -              {{ parseFloat(dataResource.virtualsize / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GB
++              {{ parseFloat(dataResource.virtualsize / (1024.0 * 1024.0 * 
1024.0)).toFixed(2) }} GiB
+             </div>
+           </div>
            <div v-else-if="['name', 'type'].includes(item)">
              <span v-if="['USER.LOGIN', 'USER.LOGOUT', 'ROUTER.HEALTH.CHECKS', 
'FIREWALL.CLOSE', 
'ALERT.SERVICE.DOMAINROUTER'].includes(dataResource[item])">{{ 
$t(dataResource[item].toLowerCase()) }}</span>
              <span v-else>{{ dataResource[item] }}</span>
diff --cc ui/src/components/view/InfoCard.vue
index df1411ad5fe,72df182d80e..550bba74409
--- a/ui/src/components/view/InfoCard.vue
+++ b/ui/src/components/view/InfoCard.vue
@@@ -144,9 -124,9 +144,9 @@@
                icon="barcode-outlined"
                type="dashed"
                size="small"
 -              :copyResource="resource.id"
 +              :copyResource="String(resource.id)"
                @onClick="$message.success($t('label.copied.clipboard'))" />
-             <span style="margin-left: 10px;">{{ resource.id }}</span>
+             <span style="margin-left: 10px;"><copy-label :label="resource.id" 
/></span>
            </div>
          </div>
          <div class="resource-detail-item" v-if="resource.ostypename && 
resource.ostypeid">
diff --cc ui/src/components/view/ListView.vue
index 69dc3a1c559,38b8b519138..8352a179afe
--- a/ui/src/components/view/ListView.vue
+++ b/ui/src/components/view/ListView.vue
@@@ -37,150 -37,180 +37,171 @@@
          </a-menu>
        </div>
      </template>
 -    <template #footer>
 -      <span v-if="hasSelected">
 -        {{ `Selected ${selectedRowKeys.length} items` }}
 -      </span>
 -    </template>
 -
 -    <!--
 -    <div #expandedRowRender="{ resource }">
 -      <info-card :resource="resource style="margin-left: 0px; width: 50%">
 -        <div #actions style="padding-top: 12px">
 -          <a-tooltip
 -            v-for="(action, actionIndex) in $route.meta.actions"
 -            :key="actionIndex"
 -            placement="bottom">
 -            <template #title>
 -              {{ $t(action.label) }}
 -            </template>
 -            <a-button
 -              v-if="action.api in $store.getters.apis && action.dataView &&
 -                ('show' in action ? action.show(resource, 
$store.getters.userInfo) : true)"
 -              :icon="action.icon"
 -              :type="action.icon === 'delete' ? 'danger' : (action.icon === 
'plus' ? 'primary' : 'default')"
 -              shape="circle"
 -              style="margin-right: 5px; margin-top: 12px"
 -              @click="$parent.execAction(action)"
 -            >
 -            </a-button>
 -          </a-tooltip>
 -        </div>
 -      </info-card>
 -    </div>
 -    -->
 +    <template #bodyCell="{ column, text, record }">
 +      <template v-if="column.key === 'name'">
 +        <span v-if="['vm'].includes($route.path.split('/')[1])" 
style="margin-right: 5px">
 +          <span v-if="record.icon && record.icon.base64image">
-             <resource-icon :image="record.icon.base64image" size="1x"/>
++            <resource-icon :image="record.icon.base64image" size="2x"/>
 +          </span>
-           <os-logo v-else :osId="record.ostypeid" 
:osName="record.osdisplayname" size="lg" />
++          <os-logo v-else :osId="record.ostypeid" 
:osName="record.osdisplayname" size="2x" />
 +        </span>
 +        <span style="min-width: 120px" >
 +          <QuickView
 +            style="margin-left: 5px"
 +            :actions="actions"
 +            :resource="record"
 +            :enabled="quickViewEnabled() && actions.length > 0 && columns && 
columns[0].dataIndex === 'name' "
 +            @exec-action="$parent.execAction"/>
 +          <span v-if="$route.path.startsWith('/project')" 
style="margin-right: 5px">
 +            <tooltip-button type="dashed" size="small" icon="LoginOutlined" 
@onClick="changeProject(record)" />
 +          </span>
 +          <span v-if="$showIcon() && 
!['vm'].includes($route.path.split('/')[1])" style="margin-right: 5px">
-             <resource-icon v-if="$showIcon() && record.icon && 
record.icon.base64image" :image="record.icon.base64image" size="1x"/>
-             <os-logo v-else-if="record.ostypename" 
:osName="record.ostypename" size="1x" />
++            <resource-icon v-if="$showIcon() && record.icon && 
record.icon.base64image" :image="record.icon.base64image" size="2x"/>
++            <os-logo v-else-if="record.ostypename" 
:osName="record.ostypename" size="2x" />
 +            <render-icon v-else-if="typeof $route.meta.icon ==='string'" 
style="font-size: 16px;" :icon="$route.meta.icon"/>
 +            <render-icon v-else style="font-size: 16px;" 
:svgIcon="$route.meta.icon" />
 +          </span>
 +          <span v-else :style="{ 'margin-right': record.ostypename ? '5px' : 
'0' }">
 +            <os-logo v-if="record.ostypename" :osName="record.ostypename" 
size="1x" />
 +          </span>
  
 -    <template #name="{text, record}">
 -      <span v-if="['vm'].includes($route.path.split('/')[1])" 
style="margin-right: 5px">
 -        <span v-if="record.icon && record.icon.base64image">
 -          <resource-icon :image="record.icon.base64image" size="2x"/>
 +          <span v-if="record.hasannotations">
 +            <span v-if="record.id">
 +              <router-link :to="{ path: $route.path + '/' + record.id }">{{ 
text }}</router-link>
 +              <router-link :to="{ path: $route.path + '/' + record.id, query: 
{ tab: 'comments' } }"><message-filled style="padding-left: 10px" 
size="small"/></router-link>
 +            </span>
 +            <router-link v-else :to="{ path: $route.path + '/' + record.name 
}" >{{ text }}</router-link>
 +          </span>
 +          <span v-else-if="$route.path.startsWith('/globalsetting')">{{ text 
}}</span>
 +          <span v-else-if="$route.path.startsWith('/alert')">
 +            <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ $t(text.toLowerCase()) }}</router-link>
 +            <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ $t(text.toLowerCase()) }}</router-link>
 +          </span>
 +          <span v-else-if="$route.path.startsWith('/tungstenfabric')">
 +            <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ $t(text.toLowerCase()) }}</router-link>
 +            <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ $t(text.toLowerCase()) }}</router-link>
 +          </span>
 +          <span v-else-if="isTungstenPath()">
 +            <router-link :to="{ path: $route.path + '/' + record.uuid, query: 
{ zoneid: record.zoneid } }" v-if="record.uuid && record.zoneid">{{ 
$t(text.toLowerCase()) }}</router-link>
 +            <router-link :to="{ path: $route.path + '/' + record.uuid, query: 
{ zoneid: $route.query.zoneid } }" v-else-if="record.uuid && 
$route.query.zoneid">{{ $t(text.toLowerCase()) }}</router-link>
 +            <router-link :to="{ path: $route.path }" v-else>{{ 
$t(text.toLowerCase()) }}</router-link>
 +          </span>
 +          <span v-else>
 +            <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ text }}</router-link>
 +            <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ text }}</router-link>
 +          </span>
          </span>
 -        <os-logo v-else :osId="record.ostypeid" 
:osName="record.osdisplayname" size="2x" />
 -      </span>
 -      <span style="min-width: 120px" >
 +      </template>
 +      <template v-if="record.clustertype === 'ExternalManaged' && 
$route.path.split('/')[1] === 'kubernetes' && ['cpunumber', 'memory', 
'size'].includes(column.key)">
 +        <span>{{ text <= 0 ? 'N/A' : text }}</span>
 +      </template>
 +      <template v-if="column.key === 'templatetype'">
 +        <router-link :to="{ path: $route.path + '/' + record.templatetype 
}">{{ text }}</router-link>
 +      </template>
 +      <template v-if="column.key === 'type'">
 +        <span v-if="['USER.LOGIN', 'USER.LOGOUT', 'ROUTER.HEALTH.CHECKS', 
'FIREWALL.CLOSE', 'ALERT.SERVICE.DOMAINROUTER'].includes(text)">{{ 
$t(text.toLowerCase()) }}</span>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +
 +      <template v-if="column.key === 'schedule'">
 +          {{ text }}
 +          <br/>
 +          ({{ generateHumanReadableSchedule(text) }})
 +      </template>
 +      <template v-if="column.key === 'displayname'">
          <QuickView
            style="margin-left: 5px"
            :actions="actions"
            :resource="record"
 -          :enabled="quickViewEnabled() && actions.length > 0 && columns && 
columns[0].dataIndex === 'name' "
 +          :enabled="quickViewEnabled() && actions.length > 0 && columns && 
columns[0].dataIndex === 'displayname' "
            @exec-action="$parent.execAction"/>
 -        <span v-if="$route.path.startsWith('/project')" style="margin-right: 
5px">
 -          <tooltip-button type="dashed" size="small" icon="LoginOutlined" 
@onClick="changeProject(record)" />
 -        </span>
 +        <router-link :to="{ path: $route.path + '/' + record.id }">{{ text 
}}</router-link>
 +      </template>
 +      <template v-if="column.key === 'username'">
          <span v-if="$showIcon() && 
!['vm'].includes($route.path.split('/')[1])" style="margin-right: 5px">
-           <resource-icon v-if="$showIcon() && record.icon && 
record.icon.base64image" :image="record.icon.base64image" size="1x"/>
+           <resource-icon v-if="$showIcon() && record.icon && 
record.icon.base64image" :image="record.icon.base64image" size="2x"/>
 -          <os-logo v-else-if="record.ostypename" :osName="record.ostypename" 
size="2x" />
 -          <render-icon v-else-if="typeof $route.meta.icon ==='string'" 
style="font-size: 16px;" :icon="$route.meta.icon"/>
 -          <render-icon v-else style="font-size: 16px;" 
:svgIcon="$route.meta.icon" />
 -        </span>
 -        <span v-else :style="{ 'margin-right': record.ostypename ? '5px' : 
'0' }">
 -          <os-logo v-if="record.ostypename" :osName="record.ostypename" 
size="1x" />
 +          <user-outlined v-else style="font-size: 16px;" />
          </span>
 -
 -        <span v-if="record.hasannotations">
 -          <span v-if="record.id">
 -            <router-link :to="{ path: $route.path + '/' + record.id }">{{ 
text }}</router-link>
 -            <router-link :to="{ path: $route.path + '/' + record.id, query: { 
tab: 'comments' } }"><message-filled style="padding-left: 10px" 
size="small"/></router-link>
 -          </span>
 -          <router-link v-else :to="{ path: $route.path + '/' + record.name }" 
>{{ text }}</router-link>
 +        <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="['/accountuser', '/vpnuser'].includes($route.path)">{{ text 
}}</router-link>
 +        <router-link :to="{ path: '/accountuser', query: { username: 
record.username, domainid: record.domainid } }" 
v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +      <template v-if="column.key === 'entityid'">
 +        <router-link :to="{ path: generateCommentsPath(record), query: { tab: 
'comments' } }">{{ record.entityname }}</router-link>
 +      </template>
 +      <template v-if="column.key === 'entitytype'">
 +        {{ generateHumanReadableEntityType(record) }}
 +      </template>
 +      <template v-if="column.key === 'adminsonly' && 
['Admin'].includes($store.getters.userInfo.roletype)">
 +        <a-checkbox :checked="record.adminsonly" :value="record.id" 
v-if="record.userid === $store.getters.userInfo.id" @change="e => 
updateAdminsOnly(e)" />
 +        <a-checkbox :checked="record.adminsonly" disabled v-else />
 +      </template>
 +      <template v-if="column.key === 'ipaddress'" href="javascript:;">
 +        <router-link v-if="['/publicip', '/privategw'].includes($route.path)" 
:to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
-         <span v-else>{{ text }}</span>
++        <span v-else>
++          <copy-label :label="text" />
+         </span>
 -        <span v-else-if="$route.path.startsWith('/globalsetting')">{{ text 
}}</span>
 -        <span v-else-if="$route.path.startsWith('/preferences')">{{ text 
}}</span>
 -        <span v-else-if="$route.path.startsWith('/alert')">
 -          <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ $t(text.toLowerCase()) }}</router-link>
 -          <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ $t(text.toLowerCase()) }}</router-link>
 +        <span v-if="record.issourcenat">
 +          &nbsp;
 +          <a-tag>source-nat</a-tag>
          </span>
 -        <span v-else-if="$route.path.startsWith('/tungstenfabric')">
 -          <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ $t(text.toLowerCase()) }}</router-link>
 -          <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ $t(text.toLowerCase()) }}</router-link>
 +        <span v-if="record.isstaticnat">
 +          &nbsp;
 +          <a-tag>static-nat</a-tag>
          </span>
 -        <span v-else-if="isTungstenPath()">
 -          <router-link :to="{ path: $route.path + '/' + record.uuid, query: { 
zoneid: record.zoneid } }" v-if="record.uuid && record.zoneid">{{ 
$t(text.toLowerCase()) }}</router-link>
 -          <router-link :to="{ path: $route.path + '/' + record.uuid, query: { 
zoneid: $route.query.zoneid } }" v-else-if="record.uuid && 
$route.query.zoneid">{{ $t(text.toLowerCase()) }}</router-link>
 -          <router-link :to="{ path: $route.path }" v-else>{{ 
$t(text.toLowerCase()) }}</router-link>
 +      </template>
 +      <template v-if="column.key === 'ip6address'" href="javascript:;">
 +        <span>{{ ipV6Address(text, record) }}</span>
 +      </template>
 +      <template v-if="column.key === 'publicip'">
 +        <router-link v-if="['/autoscalevmgroup'].includes($route.path)" 
:to="{ path: '/publicip' + '/' + record.publicipid }">{{ text }}</router-link>
 +        <router-link v-else :to="{ path: $route.path + '/' + record.id }">{{ 
text }}</router-link>
 +      </template>
 +      <template v-if="column.key === 'traffictype'">
 +        {{ text }}
 +      </template>
 +      <template v-if="column.key === 'vmname'">
 +        <router-link :to="{ path: createPathBasedOnVmType(record.vmtype, 
record.virtualmachineid) }">{{ text }}</router-link>
 +      </template>
 +      <template v-if="column.key === 'virtualmachinename'">
 +        <router-link :to="{ path: getVmRouteUsingType(record) + 
record.virtualmachineid }">{{ text }}</router-link>
 +      </template>
++      <template v-if="column.key === 'volumename'">
++        <router-link :to="{ path: '/volume/' + record.volumeid }">{{ text 
}}</router-link>
++      </template>
++      <template v-if="column.key === 'size'">
++        <span v-if="text">
++          {{ parseFloat(parseFloat(text) / 1024.0 / 1024.0 / 
1024.0).toFixed(2) }} GiB
+         </span>
 -        <span v-else>
 -          <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="record.id">{{ text }}</router-link>
 -          <router-link :to="{ path: $route.path + '/' + record.name }" 
v-else>{{ text }}</router-link>
++      </template>
++      <template v-if="column.key === 'physicalsize'">
++        <span v-if="text">
++          {{ parseFloat(parseFloat(text) / 1024.0 / 1024.0 / 
1024.0).toFixed(2) }} GiB
+         </span>
++      </template>
++      <template v-if="column.key === 'physicalnetworkname'">
++        <router-link :to="{ path: '/physicalnetwork/' + 
record.physicalnetworkid }">{{ text }}</router-link>
++      </template>
++      <template v-if="column.key === 'serviceofferingname'">
++        <router-link :to="{ path: '/computeoffering/' + 
record.serviceofferingid }">{{ text }}</router-link>
++      </template>
 +      <template v-if="column.key === 'hypervisor'">
 +        <span v-if="$route.name === 'hypervisorcapability'">
 +        <router-link :to="{ path: $route.path + '/' + record.id }">{{ text 
}}</router-link>
        </span>
 -    </template>
 -    <template #templatetype="{ text, record }">
 -      <router-link :to="{ path: $route.path + '/' + record.templatetype }">{{ 
text }}</router-link>
 -    </template>
 -    <template #type="{ text }">
 -      <span v-if="['USER.LOGIN', 'USER.LOGOUT', 'ROUTER.HEALTH.CHECKS', 
'FIREWALL.CLOSE', 'ALERT.SERVICE.DOMAINROUTER'].includes(text)">{{ 
$t(text.toLowerCase()) }}</span>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #displayname="{text, record}">
 -      <QuickView
 -        style="margin-left: 5px"
 -        :actions="actions"
 -        :resource="record"
 -        :enabled="quickViewEnabled() && actions.length > 0 && columns && 
columns[0].dataIndex === 'displayname' "
 -        @exec-action="$parent.execAction"/>
 -      <router-link :to="{ path: $route.path + '/' + record.id }">{{ text 
}}</router-link>
 -    </template>
 -    <template #username="{text, record}">
 -      <span v-if="$showIcon() && !['vm'].includes($route.path.split('/')[1])" 
style="margin-right: 5px">
 -        <resource-icon v-if="$showIcon() && record.icon && 
record.icon.base64image" :image="record.icon.base64image" size="2x"/>
 -        <user-outlined v-else style="font-size: 16px;" />
 +      <span v-else-if="$route.name === 'guestoshypervisormapping'">
 +        <QuickView
 +          style="margin-left: 5px"
 +          :actions="actions"
 +          :resource="record"
 +          :enabled="quickViewEnabled() && actions.length > 0 && columns && 
columns[0].dataIndex === 'hypervisor' "
 +          @exec-action="$parent.execAction"/>
 +        <router-link :to="{ path: $route.path + '/' + record.id }">{{ text 
}}</router-link>
        </span>
 -      <router-link :to="{ path: $route.path + '/' + record.id }" 
v-if="['/accountuser', '/vpnuser'].includes($route.path)">{{ text 
}}</router-link>
 -      <router-link :to="{ path: '/accountuser', query: { username: 
record.username, domainid: record.domainid } }" 
v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
        <span v-else>{{ text }}</span>
      </template>
 -    <template #entityid="{ record }" href="javascript:;">
 -      <router-link :to="{ path: generateCommentsPath(record), query: { tab: 
'comments' } }">{{ record.entityname }}</router-link>
 -    </template>
 -    <template #entitytype="{ record }" href="javascript:;">
 -      {{ generateHumanReadableEntityType(record) }}
 -    </template>
 -    <template #adminsonly="{ record }" 
v-if="['Admin'].includes($store.getters.userInfo.roletype)" href="javascript:;">
 -      <a-checkbox :checked="record.adminsonly" :value="record.id" 
v-if="record.userid === $store.getters.userInfo.id" @change="e => 
updateAdminsOnly(e)" />
 -      <a-checkbox :checked="record.adminsonly" disabled v-else />
 -    </template>
 -    <template #ipaddress="{ text, record }" href="javascript:;">
 -      <router-link v-if="['/publicip', '/privategw'].includes($route.path)" 
:to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
 -      <span v-else>
 -        <copy-label :label="text" />
 -      </span>
 -      <span v-if="record.issourcenat">
 -        &nbsp;
 -        <a-tag>source-nat</a-tag>
 -      </span>
 -      <span v-if="record.isstaticnat">
 -        &nbsp;
 -        <a-tag>static-nat</a-tag>
 -      </span>
 -    </template>
 -    <template #ip6address="{ text, record }" href="javascript:;">
 -      <span>{{ ipV6Address(text, record) }}</span>
 -    </template>
 -    <template #publicip="{ text, record }">
 -      <router-link v-if="['/autoscalevmgroup'].includes($route.path)" :to="{ 
path: '/publicip' + '/' + record.publicipid }">{{ text }}</router-link>
 -      <router-link v-else :to="{ path: $route.path + '/' + record.id }">{{ 
text }}</router-link>
 -    </template>
 -    <template #traffictype="{ text }" href="javascript:;">
 -      {{ text }}
 -    </template>
 -    <template #vmname="{ text, record }">
 -      <router-link :to="{ path: createPathBasedOnVmType(record.vmtype, 
record.virtualmachineid) }">{{ text }}</router-link>
 -    </template>
 -    <template #virtualmachinename="{ text, record }">
 -      <router-link :to="{ path: '/vm/' + record.virtualmachineid }">{{ text 
}}</router-link>
 -    </template>
 -    <template #volumename="{ text, record }">
 -      <router-link :to="{ path: '/volume/' + record.volumeid }">{{ text 
}}</router-link>
 -    </template>
 -    <template #size="{ text }">
 -      <span v-if="text">
 -        {{ parseFloat(parseFloat(text) / 1024.0 / 1024.0 / 1024.0).toFixed(2) 
}} GiB
 -      </span>
 -    </template>
 -    <template #physicalsize="{ text }">
 -      <span v-if="text">
 -        {{ parseFloat(parseFloat(text) / 1024.0 / 1024.0 / 1024.0).toFixed(2) 
}} GiB
 -      </span>
 -    </template>
 -    <template #physicalnetworkname="{ text, record }">
 -      <router-link :to="{ path: '/physicalnetwork/' + 
record.physicalnetworkid }">{{ text }}</router-link>
 -    </template>
 -    <template #serviceofferingname="{ text, record }">
 -      <router-link :to="{ path: '/computeoffering/' + 
record.serviceofferingid }">{{ text }}</router-link>
 -    </template>
 -    <template #hypervisor="{ text, record }">
 -      <span v-if="$route.name === 'hypervisorcapability'">
 +    <template v-if="column.key === 'osname'">
 +      <span v-if="$route.name === 'guestos'">
          <router-link :to="{ path: $route.path + '/' + record.id }">{{ text 
}}</router-link>
        </span>
        <span v-else>{{ text }}</span>
@@@ -189,22 -219,25 +210,25 @@@
        <status v-if="$route.path.startsWith('/host')" 
:text="getHostState(record)" displayText />
        <status v-else :text="text ? text : ''" displayText :styles="{ 
'min-width': '80px' }" />
      </template>
 -    <template #status="{ text }">
++    <template v-if="column.key === 'status'">
+       <status :text="text ? text : ''" displayText />
+     </template>
 -    <template #allocationstate="{ text }">
 +    <template v-if="column.key === 'allocationstate'">
        <status :text="text ? text : ''" displayText />
      </template>
 -    <template #resourcestate="{ text }">
 +    <template v-if="column.key === 'resourcestate'">
        <status :text="text ? text : ''" displayText />
      </template>
 -    <template #powerstate="{ text }">
 +    <template v-if="column.key === 'powerstate'">
        <status :text="text ? text : ''" displayText />
      </template>
 -    <template #agentstate="{ text }">
 +    <template v-if="column.key === 'agentstate'">
        <status :text="text ? text : ''" displayText />
      </template>
 -    <template #quotastate="{ text }">
 +    <template v-if="column.key === 'quotastate'">
        <status :text="text ? text : ''" displayText />
      </template>
 -    <template #vlan="{ text, record }">
 +    <template v-if="column.key === 'vlan'">
        <a href="javascript:;">
          <router-link v-if="$route.path === '/guestvlans'" :to="{ path: 
'/guestvlans/' + record.id }">{{ text }}</router-link>
        </a>
@@@ -230,213 -260,193 +254,214 @@@
        <router-link v-if="record.storageid" :to="{ path: '/storagepool/' + 
record.storageid }">{{ text }}</router-link>
        <span v-else>{{ text }}</span>
      </template>
 -
 -    <template
 -      v-for="(value, name) in thresholdMapping"
 -      :key="name"
 -      #[name]="{ text, record }"
 -      href="javascript:;">
 -      <span>
 -        <span v-if="record[value.disable]" class="alert-disable-threshold">
 -          {{ text }}
 -        </span>
 -        <span v-else-if="record[value.notification]" 
class="alert-notification-threshold">
 -          {{ text }}
 -        </span>
 -        <span style="padding: 10%;" v-else>
 -          {{ text }}
 +    <template v-for="(value, name) in thresholdMapping" :key="name">
 +      <template v-if="column.key === name">
 +        <span>
 +          <span v-if="record[value.disable]" class="alert-disable-threshold">
 +            {{ text }}
 +          </span>
 +          <span v-else-if="record[value.notification]" 
class="alert-notification-threshold">
 +            {{ text }}
 +          </span>
 +          <span style="padding: 10%;" v-else>
 +            {{ text }}
 +          </span>
          </span>
 -      </span>
 +      </template>
      </template>
  
 -    <template #level="{ text, record }">
 -      <router-link :to="{ path: '/event/' + record.id }">{{ text 
}}</router-link>
 -    </template>
 +      <template v-if="column.key === 'level'">
 +        <router-link :to="{ path: '/event/' + record.id }">{{ text 
}}</router-link>
 +      </template>
  
 -    <template #clustername="{ text, record }">
 -      <router-link :to="{ path: '/cluster/' + record.clusterid }">{{ text 
}}</router-link>
 -    </template>
 -    <template #podname="{ text, record }">
 -      <router-link :to="{ path: '/pod/' + record.podid }">{{ text 
}}</router-link>
 -    </template>
 -    <template #account="{ text, record }">
 -      <template v-if="record.owner">
 -        <template v-for="(item, idx) in record.owner" :key="idx">
 -          <span style="margin-right:5px">
 -            <span v-if="$store.getters.userInfo.roletype !== 'User'">
 -              <router-link v-if="'user' in item" :to="{ path: '/accountuser', 
query: { username: item.user, domainid: record.domainid }}">{{ item.account + 
'(' + item.user + ')' }}</router-link>
 -              <router-link v-else :to="{ path: '/account', query: { name: 
item.account, domainid: record.domainid, dataView: true } }">{{ item.account 
}}</router-link>
 +      <template v-if="column.key === 'clustername'">
 +        <router-link :to="{ path: '/cluster/' + record.clusterid }">{{ text 
}}</router-link>
 +      </template>
 +      <template v-if="column.key === 'podname'">
 +        <router-link :to="{ path: '/pod/' + record.podid }">{{ text 
}}</router-link>
 +      </template>
 +      <template v-if="column.key === 'account'">
 +        <template v-if="record.owner">
 +          <template v-for="(item, idx) in record.owner" :key="idx">
 +            <span style="margin-right:5px">
 +              <span v-if="$store.getters.userInfo.roletype !== 'User'">
 +                <router-link v-if="'user' in item" :to="{ path: 
'/accountuser', query: { username: item.user, domainid: record.domainid }}">{{ 
item.account + '(' + item.user + ')' }}</router-link>
 +                <router-link v-else :to="{ path: '/account', query: { name: 
item.account, domainid: record.domainid, dataView: true } }">{{ item.account 
}}</router-link>
 +              </span>
 +              <span v-else>{{ item.user ? item.account + '(' + item.user + 
')' : item.account }}</span>
              </span>
 -            <span v-else>{{ item.user ? item.account + '(' + item.user + ')' 
: item.account }}</span>
 -          </span>
 +          </template>
 +        </template>
 +        <template v-if="text && !text.startsWith('PrjAcct-')">
 +          <router-link
 +            v-if="'quota' in record && 
$router.resolve(`${$route.path}/${record.account}`).matched[0].redirect !== 
'/exception/404'"
 +            :to="{ path: `${$route.path}/${record.account}`, query: { 
account: record.account, domainid: record.domainid, quota: true } }">{{ text 
}}</router-link>
 +          <router-link :to="{ path: '/account/' + record.accountid }" 
v-else-if="record.accountid">{{ text }}</router-link>
 +          <router-link :to="{ path: '/account', query: { name: 
record.account, domainid: record.domainid, dataView: true } }" 
v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
 +          <span v-else>{{ text }}</span>
          </template>
        </template>
 -      <template v-if="text && !text.startsWith('PrjAcct-')">
 -        <router-link
 -          v-if="'quota' in record && 
$router.resolve(`${$route.path}/${record.account}`).matched[0].redirect !== 
'/exception/404'"
 -          :to="{ path: `${$route.path}/${record.account}`, query: { account: 
record.account, domainid: record.domainid, quota: true } }">{{ text 
}}</router-link>
 -        <router-link :to="{ path: '/account/' + record.accountid }" 
v-else-if="record.accountid">{{ text }}</router-link>
 -        <router-link :to="{ path: '/account', query: { name: record.account, 
domainid: record.domainid, dataView: true } }" 
v-else-if="$store.getters.userInfo.roletype !== 'User'">{{ text }}</router-link>
 +      <template v-if="column.key === 'resource'">
 +        <resource-label :resourceType="record.resourcetype" 
:resourceId="record.resourceid" :resourceName="record.resourcename" />
 +      </template>
 +      <template v-if="column.key === 'domain'">
 +        <router-link v-if="record.domainid && 
!record.domainid.toString().includes(',') && $store.getters.userInfo.roletype 
!== 'User'" :to="{ path: '/domain/' + record.domainid, query: { tab: 'details' 
} }">{{ text }}</router-link>
          <span v-else>{{ text }}</span>
        </template>
 -    </template>
 -    <template #resource="{ record }">
 -      <resource-label :resourceType="record.resourcetype" 
:resourceId="record.resourceid" :resourceName="record.resourcename" />
 -    </template>
 -    <template #domain="{ text, record }">
 -      <router-link v-if="record.domainid && 
!record.domainid.toString().includes(',') && $store.getters.userInfo.roletype 
!== 'User'" :to="{ path: '/domain/' + record.domainid, query: { tab: 'details' 
} }">{{ text }}</router-link>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #domainpath="{ text, record }">
 -      <router-link v-if="record.domainid && !record.domainid.includes(',') && 
$router.resolve('/domain/' + record.domainid).matched[0].redirect !== 
'/exception/404'" :to="{ path: '/domain/' + record.domainid, query: { tab: 
'details' } }">{{ text }}</router-link>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #zone="{ text, record }">
 -      <router-link v-if="record.zoneid && !record.zoneid.includes(',') && 
$router.resolve('/zone/' + record.zoneid).matched[0].redirect !== 
'/exception/404'" :to="{ path: '/zone/' + record.zoneid }">{{ text 
}}</router-link>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #zonename="{ text, record }">
 -      <router-link v-if="$router.resolve('/zone/' + 
record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zone/' 
+ record.zoneid }">{{ text }}</router-link>
 -      <router-link v-else-if="$router.resolve('/zones/' + 
record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zones/' 
+ record.zoneid }">{{ text }}</router-link>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #rolename="{ text, record }">
 -      <router-link v-if="record.roleid && $router.resolve('/role/' + 
record.roleid).matched[0].redirect !== '/exception/404'" :to="{ path: '/role/' 
+ record.roleid }">{{ text }}</router-link>
 -      <span v-else>{{ text }}</span>
 -    </template>
 -    <template #templateversion="{ record }">
 -      <span>  {{ record.version }} </span>
 -    </template>
 -    <template #softwareversion="{ record }">
 -      <span>  {{ record.softwareversion ? record.softwareversion : 'N/A' }} 
</span>
 -    </template>
 -    <template #access="{ record }">
 -      <status :text="record.readonly ? 'ReadOnly' : 'ReadWrite'" displayText 
/>
 -    </template>
 -    <template #requiresupgrade="{ record }">
 -      <status :text="record.requiresupgrade ? 'warning' : ''" />
 -      {{ record.requiresupgrade ? 'Yes' : 'No' }}
 -    </template>
 -    <template #loadbalancerrule="{ record }">
 -      <span>  {{ record.loadbalancerrule }} </span>
 -    </template>
 -    <template #autoscalingenabled="{ record }">
 -      <status :text="record.autoscalingenabled ? 'Enabled' : 'Disabled'" />
 -      {{ record.autoscalingenabled ? 'Enabled' : 'Disabled' }}
 -    </template>
 -    <template #current="{record}">
 -      <status :text="record.current ? record.current.toString() : 'false'" />
 -    </template>
 -    <template #created="{ text }">
 -      {{ $toLocaleDate(text) }}
 -    </template>
 -    <template #sent="{ text }">
 -      {{ $toLocaleDate(text) }}
 -    </template>
 -    <template #order="{ text, record }">
 -      <div class="shift-btns">
 -        <a-tooltip :name="text" placement="top">
 -          <template #title>{{ $t('label.move.to.top') }}</template>
 -          <a-button
 -            shape="round"
 -            @click="moveItemTop(record)"
 -            class="shift-btn">
 -            <DoubleLeftOutlined class="shift-btn shift-btn--rotated" />
 -          </a-button>
 -        </a-tooltip>
 -        <a-tooltip placement="top">
 -          <template #title>{{ $t('label.move.to.bottom') }}</template>
 -          <a-button
 -            shape="round"
 -            @click="moveItemBottom(record)"
 -            class="shift-btn">
 -            <DoubleRightOutlined class="shift-btn shift-btn--rotated" />
 -          </a-button>
 -        </a-tooltip>
 -        <a-tooltip placement="top">
 -          <template #title>{{ $t('label.move.up.row') }}</template>
 -          <a-button shape="round" @click="moveItemUp(record)" 
class="shift-btn">
 -            <CaretUpOutlined class="shift-btn" />
 -          </a-button>
 -        </a-tooltip>
 -        <a-tooltip placement="top">
 -          <template #title>{{ $t('label.move.down.row') }}</template>
 -          <a-button shape="round" @click="moveItemDown(record)" 
class="shift-btn">
 -            <CaretDownOutlined class="shift-btn" />
 -          </a-button>
 -        </a-tooltip>
 -      </div>
 -    </template>
 +      <template v-if="column.key === 'domainpath'">
 +        <router-link v-if="record.domainid && !record.domainid.includes(',') 
&& $router.resolve('/domain/' + record.domainid).matched[0].redirect !== 
'/exception/404'" :to="{ path: '/domain/' + record.domainid, query: { tab: 
'details' } }">{{ text }}</router-link>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +      <template v-if="column.key === 'zone'">
 +        <router-link v-if="record.zoneid && !record.zoneid.includes(',') && 
$router.resolve('/zone/' + record.zoneid).matched[0].redirect !== 
'/exception/404'" :to="{ path: '/zone/' + record.zoneid }">{{ text 
}}</router-link>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +      <template v-if="column.key === 'zonename'">
 +        <router-link v-if="$router.resolve('/zone/' + 
record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zone/' 
+ record.zoneid }">{{ text }}</router-link>
++        <router-link v-else-if="$router.resolve('/zones/' + 
record.zoneid).matched[0].redirect !== '/exception/404'" :to="{ path: '/zones/' 
+ record.zoneid }">{{ text }}</router-link>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +      <template v-if="column.key === 'rolename'">
 +        <router-link v-if="record.roleid && $router.resolve('/role/' + 
record.roleid).matched[0].redirect !== '/exception/404'" :to="{ path: '/role/' 
+ record.roleid }">{{ text }}</router-link>
 +        <span v-else>{{ text }}</span>
 +      </template>
 +      <template v-if="column.key === 'templateversion'">
 +        <span>  {{ record.version }} </span>
 +      </template>
 +      <template v-if="column.key === 'softwareversion'">
 +        <span>  {{ record.softwareversion ? record.softwareversion : 'N/A' }} 
</span>
 +      </template>
 +      <template v-if="column.key === 'access'">
 +        <status :text="record.readonly ? 'ReadOnly' : 'ReadWrite'" 
displayText />
 +      </template>
 +      <template v-if="column.key === 'requiresupgrade'">
 +        <status :text="record.requiresupgrade ? 'warning' : ''" />
 +        {{ record.requiresupgrade ? 'Yes' : 'No' }}
 +      </template>
 +      <template v-if="column.key === 'loadbalancerrule'">
 +        <span>  {{ record.loadbalancerrule }} </span>
 +      </template>
 +      <template v-if="column.key === 'autoscalingenabled'">
 +        <status :text="record.autoscalingenabled ? 'Enabled' : 'Disabled'" />
 +        {{ record.autoscalingenabled ? 'Enabled' : 'Disabled' }}
 +      </template>
 +      <template v-if="column.key === 'current'">
 +        <status :text="record.current ? record.current.toString() : 'false'" 
/>
 +      </template>
 +      <template v-if="column.key === 'enabled'">
 +        <status :text="record.enabled ? record.enabled.toString() : 'false'" 
/>
 +        {{ record.enabled ? 'Enabled' : 'Disabled' }}
 +      </template>
 +      <template v-if="['created', 'sent'].includes(column.key)">
 +        {{ $toLocaleDate(text) }}
 +      </template>
 +      <template v-if="['startdate', 'enddate'].includes(column.key) && 
['vm'].includes($route.path.split('/')[1])">
 +        {{ getDateAtTimeZone(text, record.timezone) }}
 +      </template>
 +      <template v-if="column.key === 'order'">
 +        <div class="shift-btns">
 +          <a-tooltip :name="text" placement="top">
 +            <template #title>{{ $t('label.move.to.top') }}</template>
 +            <a-button
 +              shape="round"
 +              @click="moveItemTop(record)"
 +              class="shift-btn">
 +              <DoubleLeftOutlined class="shift-btn shift-btn--rotated" />
 +            </a-button>
 +          </a-tooltip>
 +          <a-tooltip placement="top">
 +            <template #title>{{ $t('label.move.to.bottom') }}</template>
 +            <a-button
 +              shape="round"
 +              @click="moveItemBottom(record)"
 +              class="shift-btn">
 +              <DoubleRightOutlined class="shift-btn shift-btn--rotated" />
 +            </a-button>
 +          </a-tooltip>
 +          <a-tooltip placement="top">
 +            <template #title>{{ $t('label.move.up.row') }}</template>
 +            <a-button shape="round" @click="moveItemUp(record)" 
class="shift-btn">
 +              <CaretUpOutlined class="shift-btn" />
 +            </a-button>
 +          </a-tooltip>
 +          <a-tooltip placement="top">
 +            <template #title>{{ $t('label.move.down.row') }}</template>
 +            <a-button shape="round" @click="moveItemDown(record)" 
class="shift-btn">
 +              <CaretDownOutlined class="shift-btn" />
 +            </a-button>
 +          </a-tooltip>
 +        </div>
 +      </template>
  
 -    <template #value="{ text, record }">
 -      <a-input
 -        v-if="editableValueKey === record.key"
 -        v-focus="true"
 -        :defaultValue="record.value"
 -        :disabled="!('updateConfiguration' in $store.getters.apis)"
 -        v-model:value="editableValue"
 -        @keydown.esc="editableValueKey = null"
 -        @pressEnter="saveValue(record)">
 -      </a-input>
 -      <div v-else style="width: 200px; word-break: break-all">
 -        {{ text }}
 -      </div>
 -    </template>
 -    <template #actions="{ record }">
 -      <tooltip-button
 -        :tooltip="$t('label.edit')"
 -        :disabled="!('updateConfiguration' in $store.getters.apis)"
 -        v-if="editableValueKey !== record.key"
 -        icon="edit-outlined"
 -        @onClick="editValue(record)" />
 -      <tooltip-button
 -        :tooltip="$t('label.cancel')"
 -        @onClick="editableValueKey = null"
 -        v-if="editableValueKey === record.key"
 -        iconType="CloseCircleTwoTone"
 -        iconTwoToneColor="#f5222d" />
 -      <tooltip-button
 -        :tooltip="$t('label.ok')"
 -        :disabled="!('updateConfiguration' in $store.getters.apis)"
 -        @onClick="saveValue(record)"
 -        v-if="editableValueKey === record.key"
 -        iconType="CheckCircleTwoTone"
 -        iconTwoToneColor="#52c41a" />
 -      <tooltip-button
 -        :tooltip="$t('label.reset.config.value')"
 -        @onClick="resetConfig(record)"
 -        v-if="editableValueKey !== record.key"
 -        icon="reload-outlined"
 -        :disabled="!('updateConfiguration' in $store.getters.apis)" />
 +      <template v-if="column.key === 'value'">
 +        <a-input
 +          v-if="editableValueKey === record.key"
 +          v-focus="true"
 +          :defaultValue="record.value"
 +          :disabled="!('updateConfiguration' in $store.getters.apis)"
 +          v-model:value="editableValue"
 +          @keydown.esc="editableValueKey = null"
 +          @pressEnter="saveValue(record)">
 +        </a-input>
 +        <div v-else style="width: 200px; word-break: break-all">
 +          {{ text }}
 +        </div>
 +      </template>
 +      <template v-if="column.key === 'actions'">
 +        <tooltip-button
 +          :tooltip="$t('label.edit')"
 +          :disabled="!('updateConfiguration' in $store.getters.apis)"
 +          v-if="editableValueKey !== record.key"
 +          icon="edit-outlined"
 +          @onClick="editValue(record)" />
 +        <tooltip-button
 +          :tooltip="$t('label.cancel')"
 +          @onClick="editableValueKey = null"
 +          v-if="editableValueKey === record.key"
 +          iconType="CloseCircleTwoTone"
 +          iconTwoToneColor="#f5222d" />
 +        <tooltip-button
 +          :tooltip="$t('label.ok')"
 +          :disabled="!('updateConfiguration' in $store.getters.apis)"
 +          @onClick="saveValue(record)"
 +          v-if="editableValueKey === record.key"
 +          iconType="CheckCircleTwoTone"
 +          iconTwoToneColor="#52c41a" />
 +        <tooltip-button
 +          :tooltip="$t('label.reset.config.value')"
 +          @onClick="resetConfig(record)"
 +          v-if="editableValueKey !== record.key"
 +          icon="reload-outlined"
 +          :disabled="!('updateConfiguration' in $store.getters.apis)" />
 +      </template>
 +      <template v-if="column.key === 'tariffActions'">
 +        <tooltip-button
 +          :tooltip="$t('label.edit')"
 +          v-if="editableValueKey !== record.key"
 +          :disabled="!('quotaTariffUpdate' in $store.getters.apis)"
 +          icon="edit-outlined"
 +          @onClick="editTariffValue(record)" />
 +        <slot></slot>
 +      </template>
 +      <template v-if="column.key === 'vmScheduleActions'">
 +        <tooltip-button
 +          :tooltip="$t('label.edit')"
 +          :disabled="!('updateVMSchedule' in $store.getters.apis)"
 +          icon="edit-outlined"
 +          @onClick="updateVMSchedule(record)" />
 +        <tooltip-button
 +          :tooltip="$t('label.remove')"
 +          :disabled="!('deleteVMSchedule' in $store.getters.apis)"
 +          icon="delete-outlined"
 +          :danger="true"
 +          type="primary"
 +          @onClick="removeVMSchedule(record)" />
 +      </template>
      </template>
 -    <template #tariffActions="{ record }">
 -      <tooltip-button
 -        :tooltip="$t('label.edit')"
 -        v-if="editableValueKey !== record.key"
 -        :disabled="!('quotaTariffUpdate' in $store.getters.apis)"
 -        icon="edit-outlined"
 -        @onClick="editTariffValue(record)" />
 -      <slot></slot>
 +    <template #footer>
 +      <span v-if="hasSelected">
 +        {{ `Selected ${selectedRowKeys.length} items` }}
 +      </span>
      </template>
    </a-table>
  </template>
diff --cc ui/src/config/section/compute.js
index 6d2c55b4111,e9a16ff6322..99634e330c2
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@@ -455,7 -454,7 +454,7 @@@ export default 
        docHelp: 'plugins/cloudstack-kubernetes-service.html',
        permission: ['listKubernetesClusters'],
        columns: (store) => {
-         var fields = ['name', 'state', 'clustertype', 'size', 'cpunumber', 
'memory']
 -        var fields = ['name', 'state', 'size', 'cpunumber', 'memory', 
'kubernetesversionname']
++        var fields = ['name', 'state', 'clustertype', 'size', 'cpunumber', 
'memory', 'kubernetesversionname']
          if (['Admin', 'DomainAdmin'].includes(store.userInfo.roletype)) {
            fields.push('account')
          }
diff --cc ui/src/config/section/network.js
index b5ebc0f8694,3105798b0a4..153e6c5df5f
--- a/ui/src/config/section/network.js
+++ b/ui/src/config/section/network.js
@@@ -323,8 -319,8 +323,8 @@@ export default 
        docHelp: 
'adminguide/networking_and_traffic.html#reserving-public-ip-addresses-and-vlans-for-accounts',
        permission: ['listPublicIpAddresses'],
        resourceType: 'PublicIpAddress',
-       columns: ['ipaddress', 'state', 'associatednetworkname', 'vpcname', 
'virtualmachinename', 'allocated', 'account', 'zonename'],
-       details: ['ipaddress', 'id', 'associatednetworkname', 
'virtualmachinename', 'networkid', 'issourcenat', 'isstaticnat', 
'virtualmachinename', 'vmipaddress', 'vlan', 'allocated', 'account', 
'zonename'],
 -      columns: ['ipaddress', 'state', 'associatednetworkname', 
'virtualmachinename', 'allocated', 'account', 'domain', 'zonename'],
++      columns: ['ipaddress', 'state', 'associatednetworkname', 'vpcname', 
'virtualmachinename', 'allocated', 'account', 'domain', 'zonename'],
+       details: ['ipaddress', 'id', 'associatednetworkname', 
'virtualmachinename', 'networkid', 'issourcenat', 'isstaticnat', 
'virtualmachinename', 'vmipaddress', 'vlan', 'allocated', 'account', 'domain', 
'zonename'],
        filters: ['allocated', 'reserved', 'free'],
        component: shallowRef(() => 
import('@/views/network/PublicIpResource.vue')),
        tabs: [{
diff --cc ui/src/views/compute/CreateAutoScaleVmGroup.vue
index 3797077ba6d,b764f8185e2..084828ef9c5
--- a/ui/src/views/compute/CreateAutoScaleVmGroup.vue
+++ b/ui/src/views/compute/CreateAutoScaleVmGroup.vue
@@@ -34,8 -34,8 +34,8 @@@
                    <div style="margin-top: 15px">
                      <span>{{ $t('message.select.a.zone') }}</span><br/>
                      <a-form-item :label="$t('label.zoneid')" name="zoneid" 
ref="zoneid">
 -                      <div v-if="zones.length <= 9">
 +                      <div v-if="zones.length <= 8">
-                         <a-row type="flex" :gutter="5" justify="start">
+                         <a-row type="flex" :gutter="[16,18]" justify="start">
                            <div v-for="(zoneItem, idx) in zones" :key="idx">
                              <a-radio-group
                                :key="idx"
@@@ -2942,6 -2939,15 +2945,15 @@@ export default 
      margin: 0 0 1.2rem;
    }
  
+   .zone-radio-button {
+     width:100%;
 -    min-width: 225px;
++    min-width: 345px;
+     height: 60px;
+     display: flex;
+     padding-left: 20px;
+     align-items: center;
+   }
+ 
    .vm-info-card {
      .ant-card-body {
        min-height: 250px;
diff --cc ui/src/views/compute/DeployVM.vue
index 507b902e11f,bb94c87db74..fc45f8cf2f8
--- a/ui/src/views/compute/DeployVM.vue
+++ b/ui/src/views/compute/DeployVM.vue
@@@ -34,8 -34,8 +34,8 @@@
                    <div style="margin-top: 15px">
                      <span>{{ $t('message.select.a.zone') }}</span><br/>
                      <a-form-item :label="$t('label.zoneid')" name="zoneid" 
ref="zoneid">
 -                      <div v-if="zones.length <= 9">
 +                      <div v-if="zones.length <= 8">
-                         <a-row type="flex" :gutter="5" justify="start">
+                         <a-row type="flex" :gutter="[16, 18]" justify="start">
                            <div v-for="(zoneItem, idx) in zones" :key="idx">
                              <a-radio-group
                                :key="idx"
@@@ -2721,6 -2696,15 +2724,15 @@@ export default 
      margin: 0 0 1.2rem;
    }
  
+   .zone-radio-button {
+     width:100%;
 -    min-width: 225px;
++    min-width: 345px;
+     height: 60px;
+     display: flex;
+     padding-left: 20px;
+     align-items: center;
+   }
+ 
    .vm-info-card {
      .ant-card-body {
        min-height: 250px;
diff --cc ui/src/views/compute/InstanceTab.vue
index 927fa3db7b4,4ab7fb6f2d5..a69d044ea8e
--- a/ui/src/views/compute/InstanceTab.vue
+++ b/ui/src/views/compute/InstanceTab.vue
@@@ -294,8 -307,8 +312,9 @@@ import DetailsTab from '@/components/vi
  import StatsTab from '@/components/view/StatsTab'
  import EventsTab from '@/components/view/EventsTab'
  import DetailSettings from '@/components/view/DetailSettings'
+ import CreateVolume from '@/views/storage/CreateVolume'
  import NicsTable from '@/views/network/NicsTable'
 +import InstanceSchedules from '@/views/compute/InstanceSchedules.vue'
  import ListResourceTable from '@/components/view/ListResourceTable'
  import TooltipButton from '@/components/widgets/TooltipButton'
  import ResourceIcon from '@/components/view/ResourceIcon'
@@@ -310,8 -323,8 +329,9 @@@ export default 
      StatsTab,
      EventsTab,
      DetailSettings,
+     CreateVolume,
      NicsTable,
 +    InstanceSchedules,
      ListResourceTable,
      TooltipButton,
      ResourceIcon,
diff --cc ui/src/views/image/TemplateZones.vue
index 8d7a3e24b24,a2f8834be6e..2e46a239b77
--- a/ui/src/views/image/TemplateZones.vue
+++ b/ui/src/views/image/TemplateZones.vue
@@@ -35,35 -35,16 +35,35 @@@
        :pagination="false"
        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: 
onSelectChange}"
        :rowKey="record => record.zoneid">
 -      <template #zonename="{record}">
 -        <span v-if="fetchZoneIcon(record.zoneid)">
 -          <resource-icon :image="zoneIcon" size="2x" style="margin-right: 
5px"/>
 -        </span>
 -        <global-outlined v-else style="margin-right: 5px" />
 -        <span> {{ record.zonename }} </span>
 -      </template>
 -      <template #isready="{ record }">
 -        <span v-if="record.isready">{{ $t('label.yes') }}</span>
 -        <span v-else>{{ $t('label.no') }}</span>
 +      <template #bodyCell="{ column, record }">
 +        <template v-if="column.key === 'zonename'">
 +          <span v-if="fetchZoneIcon(record.zoneid)">
-             <resource-icon :image="zoneIcon" size="1x" style="margin-right: 
5px"/>
++            <resource-icon :image="zoneIcon" size="2x" style="margin-right: 
5px"/>
 +          </span>
 +          <global-outlined v-else style="margin-right: 5px" />
 +          <span> {{ record.zonename }} </span>
 +        </template>
 +        <template v-if="column.key === 'isready'">
 +          <span v-if="record.isready">{{ $t('label.yes') }}</span>
 +          <span v-else>{{ $t('label.no') }}</span>
 +        </template>
 +        <template v-if="column.key === 'actions'">
 +          <tooltip-button
 +            style="margin-right: 5px"
 +            :disabled="!('copyTemplate' in $store.getters.apis && 
record.isready)"
 +            :title="$t('label.action.copy.template')"
 +            icon="copy-outlined"
 +            :loading="copyLoading"
 +            @onClick="showCopyTemplate(record)" />
 +          <tooltip-button
 +            style="margin-right: 5px"
 +            :disabled="!('deleteTemplate' in $store.getters.apis)"
 +            :title="$t('label.action.delete.template')"
 +            type="primary"
 +            :danger="true"
 +            icon="delete-outlined"
 +            @onClick="onShowDeleteModal(record)"/>
 +        </template>
        </template>
        <template #expandedRowRender="{ record }">
          <a-table
@@@ -126,7 -124,7 +126,7 @@@
                <a-select-option v-for="zone in zones" :key="zone.id" 
:label="zone.name">
                  <div>
                    <span v-if="zone.icon && zone.icon.base64image">
--                    <resource-icon :image="zone.icon.base64image" size="1x" 
style="margin-right: 5px"/>
++                    <resource-icon :image="zone.icon.base64image" size="2x" 
style="margin-right: 5px"/>
                    </span>
                    <global-outlined v-else style="margin-right: 5px" />
                    {{ zone.name }}

Reply via email to