UI - Fixes UI bugs (#6162)

* fixes

* remove console

* fix hidden clear notification button

* fixes

* fixes

* fixes navigation to ssh from comments
This commit is contained in:
Hoang Nguyen 2022-03-30 17:05:36 +07:00 committed by GitHub
parent 1c238e101d
commit 1a304ccf68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 172 additions and 141 deletions

View File

@ -68,11 +68,9 @@
<script>
import store from '@/store'
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'HeaderNotice',
components: { RenderIcon },
data () {
return {
loading: false,

View File

@ -61,11 +61,9 @@
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'SMenu',
components: { RenderIcon },
props: {
menu: {
type: Array,

View File

@ -209,6 +209,11 @@ export default {
}, 16)
})
}
const countNotify = this.$store.getters.countNotify
this.showClear = false
if (countNotify && countNotify > 0) {
this.showClear = true
}
},
beforeUnmount () {
document.body.classList.remove('dark')

View File

@ -51,13 +51,9 @@
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'PageHeader',
components: {
RenderIcon
},
props: {
title: {
type: String,

View File

@ -54,14 +54,11 @@
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
import PageHeader from './PageHeader'
export default {
name: 'LayoutContent',
components: {
RenderIcon,
PageHeader
},
// ['desc', 'logo', 'title', 'avatar', 'linkList', 'extraImage']

View File

@ -80,13 +80,11 @@
<script>
import { api } from '@/api'
import RenderIcon from '@/utils/renderIcon'
import Console from '@/components/widgets/Console'
export default {
name: 'ActionButton',
components: {
RenderIcon,
Console
},
data () {
@ -94,7 +92,7 @@ export default {
actionBadge: {}
}
},
mounted () {
created () {
this.handleShowBadge()
},
props: {

View File

@ -697,7 +697,6 @@
<script>
import { api } from '@/api'
import RenderIcon from '@/utils/renderIcon'
import Console from '@/components/widgets/Console'
import OsLogo from '@/components/widgets/OsLogo'
import Status from '@/components/widgets/Status'
@ -714,8 +713,7 @@ export default {
Status,
TooltipButton,
UploadResourceIcon,
ResourceIcon,
RenderIcon
ResourceIcon
},
props: {
resource: {

View File

@ -98,7 +98,7 @@
</span>
<span v-if="record.hasannotations">
<span v-if="record.id">
<span v-if="record.id && $route.path !== '/ssh'">
<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>
@ -398,7 +398,6 @@ import Status from '@/components/widgets/Status'
import QuickView from '@/components/view/QuickView'
import TooltipButton from '@/components/widgets/TooltipButton'
import ResourceIcon from '@/components/view/ResourceIcon'
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'ListView',
@ -407,8 +406,7 @@ export default {
Status,
QuickView,
TooltipButton,
ResourceIcon,
RenderIcon
ResourceIcon
},
props: {
columns: {
@ -682,6 +680,9 @@ export default {
return record.nic.filter(e => { return e.ip6address }).map(e => { return e.ip6address }).join(', ') || text
},
generateCommentsPath (record) {
if (this.entityTypeToPath(record.entitytype) === 'ssh') {
return '/' + this.entityTypeToPath(record.entitytype) + '/' + record.entityname
}
return '/' + this.entityTypeToPath(record.entitytype) + '/' + record.entityid
},
generateHumanReadableEntityType (record) {

View File

@ -61,11 +61,9 @@
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'Breadcrumb',
components: { RenderIcon },
props: {
resource: {
type: Object,

View File

@ -20,47 +20,46 @@
<template #title v-if="tooltip">
{{ tooltip }}
</template>
<a-button
style="margin-left: -5px"
v-if="copyResource"
shape="circle"
:size="size"
:type="type"
:danger="danger"
:disabled="disabled"
:class="buttonClass"
:loading="loading"
@click="handleClicked()"
v-clipboard:copy="copyResource" >
<template #icon v-if="icon"><render-icon :icon="icon" /></template>
<template v-if="iconType && iconTwoToneColor">
<render-icon :icon="iconType" :props="{ theme: 'twoTone', twoToneColor: iconTwoToneColor }" />
</template>
</a-button>
<a-button
v-else
shape="circle"
:size="size"
:type="type"
:danger="danger"
:disabled="disabled"
:class="buttonClass"
:loading="loading"
@click="handleClicked()" >
<template #icon v-if="icon"><render-icon :icon="icon" /></template>
<template v-if="iconType && iconTwoToneColor">
<render-icon :icon="iconType" :props="{ theme: 'twoTone', twoToneColor: iconTwoToneColor }" />
</template>
</a-button>
<span style="margin-right: 5px">
<a-button
v-if="copyResource"
shape="circle"
:size="size"
:type="type"
:danger="danger"
:disabled="disabled"
:class="buttonClass"
:loading="loading"
@click="handleClicked()"
v-clipboard:copy="copyResource" >
<template #icon v-if="icon"><render-icon :icon="icon" /></template>
<template v-if="iconType && iconTwoToneColor">
<render-icon :icon="iconType" :props="{ theme: 'twoTone', twoToneColor: iconTwoToneColor }" />
</template>
</a-button>
<a-button
v-else
shape="circle"
:size="size"
:type="type"
:danger="danger"
:disabled="disabled"
:class="buttonClass"
:loading="loading"
@click="handleClicked()" >
<template #icon v-if="icon"><render-icon :icon="icon" /></template>
<template v-if="iconType && iconTwoToneColor">
<render-icon :icon="iconType" :props="{ theme: 'twoTone', twoToneColor: iconTwoToneColor }" />
</template>
</a-button>
</span>
</a-tooltip>
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'TooltipButton',
components: { RenderIcon },
props: {
tooltip: {
type: String,

View File

@ -152,6 +152,7 @@ import {
UploadOutlined,
WifiOutlined
} from '@ant-design/icons-vue'
import renderIcon from '@/utils/renderIcon'
export default {
install: (app) => {
@ -290,5 +291,6 @@ export default {
app.component('UserOutlined', UserOutlined)
app.component('UploadOutlined', UploadOutlined)
app.component('WifiOutlined', WifiOutlined)
app.component('renderIcon', renderIcon)
}
}

View File

@ -78,6 +78,11 @@ export default {
if (layoutMode === 'dark') {
document.body.classList.add('dark-mode')
}
const countNotify = this.$store.getters.countNotify
this.showClear = false
if (countNotify && countNotify > 0) {
this.showClear = true
}
},
beforeUnmount () {
document.body.classList.remove('userLayout')

View File

@ -47,7 +47,7 @@
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15);
@loading-color: @primary-color;
.ant-layout.ant-layout-has-sider>.ant-layout,
// .ant-layout.ant-layout-has-sider>.ant-layout,
.ant-layout.ant-layout-has-sider>.ant-layout-content {
width: auto;
}
@ -171,6 +171,18 @@ a {
fill: @navigation-text-color;
}
.ant-menu-dark .ant-menu-item {
.anticon .custom-icon {
fill: @project-nav-text-color;
}
&.ant-menu-item-selected {
.anticon .custom-icon {
fill: #fff;
}
}
}
.ant-menu-item a {
.anticon .custom-icon {
transition: fill 0.3s ease-out;
@ -180,6 +192,10 @@ a {
}
}
.ant-menu-dark .ant-menu-item:hover .anticon .custom-icon {
fill: #fff;
}
.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,

View File

@ -1190,6 +1190,9 @@ export default {
})
}
}
if ('successMethod' in action) {
action.successMethod(this, result)
}
resolve(true)
},
errorMethod: () => {

View File

@ -282,6 +282,8 @@ export default {
})
},
loginSuccess (res) {
this.$notification.destroy()
this.$store.commit('SET_COUNT_NOTIFY', 0)
this.$router.push({ path: '/dashboard' }).catch(() => {})
},
requestFailed (err) {

View File

@ -1648,7 +1648,6 @@ export default {
handleSubmitAndStay (e) {
this.form.stayonpage = true
this.handleSubmit(e.domEvent)
this.form.stayonpage = false
},
handleSubmit (e) {
console.log('wizard submit')
@ -1884,6 +1883,9 @@ export default {
}).catch(error => {
this.$notifyError(error)
this.loading.deploy = false
}).finally(() => {
this.form.stayonpage = false
this.loading.deploy = false
})
}).catch(err => {
this.formRef.value.scrollToField(err.errorFields[0].name)

View File

@ -83,43 +83,45 @@
</div>
<div v-if="selectedRowKeys.length > 0" class="row-keys">
<a-divider />
<a-table
v-if="selectedRowKeys.length > 0"
size="middle"
:columns="chosenColumns"
:dataSource="selectedItems"
:rowKey="(record, idx) => record.id || record.name || record.usageType || idx + '-' + Math.random()"
:pagination="true"
style="overflow-y: auto"
>
<template
#expandedRowRender="record"
style="margin: 0">
<a-form-item :label="$t('label.delete.volumes')" v-if="listVolumes[record.id].opts.length > 0">
<a-select
mode="multiple"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="listVolumes[record.id].loading"
:placeholder="$t('label.delete.volumes')"
@change="(value) => onChangeVolume(record.id, value)">
<a-select-option v-for="item in listVolumes[record.id].opts" :key="item.id">
{{ item.name || item.description }}
</a-select-option>
</a-select>
</a-form-item>
<span v-else v-html="$t('label.volume.empty')" />
</template>
</a-table>
<a-form-item v-if="$store.getters.userInfo.roletype === 'Admin' || $store.getters.features.allowuserexpungerecovervm">
<template #label>
<tooltip-label :title="$t('label.expunge')" :tooltip="apiParams.expunge.description"/>
</template>
<a-switch v-model:checked="expunge" v-focus="true" />
</a-form-item>
<a-form layout="vertical">
<a-table
v-if="selectedRowKeys.length > 0"
size="middle"
:columns="chosenColumns"
:dataSource="selectedItems"
:rowKey="(record, idx) => record.id || record.name || record.usageType || idx + '-' + Math.random()"
:pagination="true"
style="overflow-y: auto"
>
<template
#expandedRowRender="{ record } "
style="margin: 0">
<a-form-item :label="$t('label.delete.volumes')" v-if="listVolumes[record.id].opts.length > 0">
<a-select
mode="multiple"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="listVolumes[record.id].loading"
:placeholder="$t('label.delete.volumes')"
@change="(value) => onChangeVolume(record.id, value)">
<a-select-option v-for="item in listVolumes[record.id].opts" :key="item.id">
{{ item.name || item.description }}
</a-select-option>
</a-select>
</a-form-item>
<span v-else v-html="$t('label.volume.empty')" />
</template>
</a-table>
<a-form-item v-if="$store.getters.userInfo.roletype === 'Admin' || $store.getters.features.allowuserexpungerecovervm">
<template #label>
<tooltip-label :title="$t('label.expunge')" :tooltip="apiParams.expunge.description"/>
</template>
<a-switch v-model:checked="expunge" v-focus="true" />
</a-form-item>
</a-form>
</div>
<div :span="24" class="action-button">
@ -214,7 +216,6 @@ export default {
this.listVolumes[item.id].loading = false
this.listVolumes[item.id].opts = item.volumes || []
})
this.$forceUpdate()
})
}
},

View File

@ -52,7 +52,7 @@
:bordered="false"
:loading="loading"
:style="stat.bgcolor ? { 'background': stat.bgcolor } : {}">
<router-link :to="{ path: stat.path, query: stat.query }">
<router-link v-if="stat.path" :to="{ path: stat.path, query: stat.query }">
<div
class="usage-dashboard-chart-card-inner">
<h3>{{ stat.name }}</h3>
@ -68,8 +68,7 @@
</a-card>
</a-row>
</a-col>
<a-col
:xl="8">
<a-col :xl="8">
<chart-card :loading="loading" >
<div class="usage-dashboard-chart-card-inner">
<a-button>
@ -100,7 +99,6 @@
<script>
import { api } from '@/api'
import store from '@/store'
import RenderIcon from '@/utils/renderIcon'
import ChartCard from '@/components/widgets/ChartCard'
import UsageDashboardChart from '@/views/dashboard/UsageDashboardChart'
@ -109,8 +107,7 @@ export default {
name: 'UsageDashboard',
components: {
ChartCard,
UsageDashboardChart,
RenderIcon
UsageDashboardChart
},
props: {
resource: {
@ -142,6 +139,8 @@ export default {
(newValue, oldValue) => {
if (newValue && newValue.id && (!oldValue || newValue.id !== oldValue.id)) {
this.fetchData()
} else if (store.getters.userInfo.roletype !== 'Admin') {
this.fetchData()
}
}
)
@ -273,4 +272,10 @@ export default {
white-space: normal;
}
}
@media (max-width: 1200px) {
.ant-col-xl-8 {
width: 100%;
}
}
</style>

View File

@ -44,11 +44,9 @@
</template>
<script>
import RenderIcon from '@/utils/renderIcon'
export default {
name: 'UsageDashboardChart',
components: { RenderIcon },
props: {
stats: {
type: Array,

View File

@ -169,7 +169,6 @@
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import router from '@/router'
import RenderIcon from '@/utils/renderIcon'
import Breadcrumb from '@/components/widgets/Breadcrumb'
import ChartCard from '@/components/widgets/ChartCard'
@ -180,8 +179,7 @@ export default {
components: {
Breadcrumb,
ChartCard,
TooltipLabel,
RenderIcon
TooltipLabel
},
data () {
return {

View File

@ -35,32 +35,32 @@
<template #action="{ record }">
<div v-if="record.projectroleid">
<span v-if="imProjectAdmin && dataSource.length > 1" class="account-button-action">
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.make.user.project.owner') : $t('label.make.project.owner')"
v-if="record.role !== owner"
type="default"
icon="arrow-up-outlined"
size="small"
@onClick="promoteAccount(record)" />
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.demote.project.owner.user') : $t('label.demote.project.owner')"
v-if="updateProjectApi.params.filter(x => x.name === 'swapowner').length > 0 && record.role === owner"
type="default"
icon="arrow-down-outlined"
size="small"
@onClick="demoteAccount(record)" />
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.remove.project.user') : $t('label.remove.project.account')"
type="primary"
:danger="true"
icon="delete-outlined"
size="small"
:disabled="!('deleteAccountFromProject' in $store.getters.apis)"
@onClick="onShowConfirmDelete(record)" />
</span>
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.make.user.project.owner') : $t('label.make.project.owner')"
v-if="record.role !== owner"
type="default"
icon="arrow-up-outlined"
size="small"
@onClick="promoteAccount(record)" />
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.demote.project.owner.user') : $t('label.demote.project.owner')"
v-if="updateProjectApi.params.filter(x => x.name === 'swapowner').length > 0 && record.role === owner"
type="default"
icon="arrow-down-outlined"
size="small"
@onClick="demoteAccount(record)" />
<tooltip-button
tooltipPlacement="top"
:tooltip="record.userid ? $t('label.remove.project.user') : $t('label.remove.project.account')"
type="primary"
:danger="true"
icon="delete-outlined"
size="small"
:disabled="!('deleteAccountFromProject' in $store.getters.apis)"
@onClick="onShowConfirmDelete(record)" />
</span>
</div>
</template>
</a-table>

View File

@ -44,7 +44,6 @@
<tooltip-button
tooltipPlacement="top"
:tooltip="$t('label.accept.project.invitation')"
type="success"
icon="check-outlined"
size="small"
@onClick="onShowConfirmAcceptInvitation(record)"/>
@ -247,12 +246,24 @@ export default {
params.accept = state
api('updateProjectInvitation', params).then(json => {
const hasJobId = this.checkForAddAsyncJob(json, title, record.project)
if (hasJobId) {
this.fetchData()
this.$emit('refresh-data')
}
this.$pollJob({
jobId: json.updateprojectinvitationresponse.jobid,
title,
description: record.project,
successMethod: () => {
this.fetchData()
this.$emit('refresh-data')
},
errorMethod: () => {
this.fetchData()
this.$emit('refresh-data')
},
catchMessage: this.$t('error.fetching.async.job.result'),
catchMethod: () => {
this.fetchData()
this.$emit('refresh-data')
}
})
}).catch(error => {
// show error
this.$notifyError(error)