cloudstack/ui/src/components/header/HeaderNotice.vue
Abhishek Kumar 8ad1009ad2
ui: fix notification list reordering intermittently (#7609)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2023-08-24 11:29:25 +02:00

143 lines
4.6 KiB
Vue

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<a-popover
v-model="visible"
trigger="click"
placement="bottom"
:autoAdjustOverflow="true"
:arrowPointAtCenter="true"
overlayClassName="header-notice-popover">
<template #content>
<a-spin :spinning="loading">
<a-list style="min-width: 200px; max-width: 300px">
<a-list-item>
<a-list-item-meta :title="$t('label.notifications')">
<template #avatar>
<a-avatar :style="{ backgroundColor: '#6887d0', verticalAlign: 'middle' }">
<template #icon><notification-outlined /></template>
</a-avatar>
</template>
<template #description><a-button size="small" @click="clearJobs">{{ $t('label.clear.list') }}</a-button></template>
</a-list-item-meta>
</a-list-item>
<a-list-item v-for="(notice, index) in notices" :key="index">
<template #title>{{ notice.path }} </template>
<a-list-item-meta :title="notice.title">
<template #avatar>
<a-avatar :style="notificationAvatar[notice.status].style">
<template #icon>
<render-icon :icon="notificationAvatar[notice.status].icon" />
</template>
</a-avatar>
</template>
<template #description>
<span v-if="getResourceName(notice.description, 'name') && notice.path">
<router-link :to="{ path: notice.path}"> {{ getResourceName(notice.description, "name") + ' - ' }}</router-link>
</span>
<span v-if="getResourceName(notice.description, 'name') && notice.path"> {{ getResourceName(notice.description, "msg") }}</span>
<span v-else>{{ notice.description }}</span>
</template>
</a-list-item-meta>
</a-list-item>
</a-list>
</a-spin>
</template>
<span @click="showNotifications" class="header-notice-opener">
<a-badge :count="notices.length">
<bell-outlined class="header-notice-icon" />
</a-badge>
</span>
</a-popover>
</template>
<script>
import store from '@/store'
export default {
name: 'HeaderNotice',
data () {
return {
loading: false,
visible: false,
notices: [],
poller: null,
notificationAvatar: {
done: { icon: 'check-circle-outlined', style: { backgroundColor: '#87d068' } },
progress: { icon: 'loading-outlined', style: { backgroundColor: '#ffbf00' } },
failed: { icon: 'close-circle-outlined', style: { backgroundColor: '#f56a00' } }
}
}
},
methods: {
showNotifications () {
this.visible = !this.visible
},
clearJobs () {
this.notices = this.notices.filter(x => x.status === 'progress')
this.$store.commit('SET_HEADER_NOTICES', this.notices)
},
getResourceName (description, data) {
if (description) {
if (data === 'name') {
const name = description.match(/\(([^)]+)\)/)
return name ? name[1] : null
}
const msg = description.substring(description.indexOf(')') + 1)
return msg
}
}
},
mounted () {
this.notices = (store.getters.headerNotices || []).reverse()
this.$store.watch(
(state, getters) => getters.headerNotices,
(newValue, oldValue) => {
if (oldValue !== newValue && newValue !== undefined) {
this.notices = newValue
}
}
)
}
}
</script>
<style lang="less" scoped>
.header-notice {
display: inline-block;
transition: all 0.3s;
&-popover {
top: 50px !important;
width: 300px;
top: 50px;
}
&-opener {
display: inline-block;
transition: all 0.3s;
vertical-align: initial;
}
&-icon {
font-size: 18px;
padding: 4px;
}
}
</style>