mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
505 lines
16 KiB
JavaScript
505 lines
16 KiB
JavaScript
// 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.
|
|
|
|
import _ from 'lodash'
|
|
import { i18n } from '@/locales'
|
|
import { api } from '@/api'
|
|
import { message, notification } from 'ant-design-vue'
|
|
import eventBus from '@/config/eventBus'
|
|
import store from '@/store'
|
|
import { sourceToken } from '@/utils/request'
|
|
|
|
export const pollJobPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$pollJob = function (options) {
|
|
/**
|
|
* @param {String} jobId
|
|
* @param {String} [name='']
|
|
* @param {String} [title='']
|
|
* @param {String} [description='']
|
|
* @param {String} [successMessage=Success]
|
|
* @param {Function} [successMethod=() => {}]
|
|
* @param {String} [errorMessage=Error]
|
|
* @param {Function} [errorMethod=() => {}]
|
|
* @param {Object} [showLoading=true]
|
|
* @param {String} [loadingMessage=Loading...]
|
|
* @param {String} [catchMessage=Error caught]
|
|
* @param {Function} [catchMethod=() => {}]
|
|
* @param {Object} [action=null]
|
|
* @param {Object} [bulkAction=false]
|
|
* @param {String} resourceId
|
|
*/
|
|
const {
|
|
jobId,
|
|
name = '',
|
|
title = '',
|
|
description = '',
|
|
successMessage = i18n.global.t('label.success'),
|
|
successMethod = () => {},
|
|
errorMessage = i18n.global.t('label.error'),
|
|
errorMethod = () => {},
|
|
loadingMessage = `${i18n.global.t('label.loading')}...`,
|
|
showLoading = true,
|
|
catchMessage = i18n.global.t('label.error.caught'),
|
|
catchMethod = () => {},
|
|
action = null,
|
|
bulkAction = false,
|
|
resourceId = null
|
|
} = options
|
|
|
|
store.dispatch('AddHeaderNotice', {
|
|
key: jobId,
|
|
title,
|
|
description,
|
|
status: 'progress'
|
|
})
|
|
|
|
eventBus.on('update-job-details', (args) => {
|
|
const { jobId, resourceId } = args
|
|
const fullPath = this.$route.fullPath
|
|
const path = this.$route.path
|
|
var jobs = this.$store.getters.headerNotices.map(job => {
|
|
if (job.key === jobId) {
|
|
if (resourceId && !path.includes(resourceId)) {
|
|
job.path = path + '/' + resourceId
|
|
} else {
|
|
job.path = fullPath
|
|
}
|
|
}
|
|
return job
|
|
})
|
|
this.$store.commit('SET_HEADER_NOTICES', jobs)
|
|
})
|
|
|
|
options.originalPage = options.originalPage || this.$router.currentRoute.value.path
|
|
api('queryAsyncJobResult', { jobId }).then(json => {
|
|
const result = json.queryasyncjobresultresponse
|
|
eventBus.emit('update-job-details', { jobId, resourceId })
|
|
if (result.jobstatus === 1) {
|
|
var content = successMessage
|
|
if (successMessage === 'Success' && action && action.label) {
|
|
content = i18n.global.t(action.label)
|
|
}
|
|
if (name) {
|
|
content = content + ' - ' + name
|
|
}
|
|
message.success({
|
|
content,
|
|
key: jobId,
|
|
duration: 2
|
|
})
|
|
store.dispatch('AddHeaderNotice', {
|
|
key: jobId,
|
|
title,
|
|
description,
|
|
status: 'done',
|
|
duration: 2
|
|
})
|
|
eventBus.emit('update-job-details', { jobId, resourceId })
|
|
// Ensure we refresh on the same / parent page
|
|
const currentPage = this.$router.currentRoute.value.path
|
|
const samePage = options.originalPage === currentPage || options.originalPage.startsWith(currentPage + '/')
|
|
if (samePage && (!action || !('isFetchData' in action) || (action.isFetchData))) {
|
|
eventBus.emit('async-job-complete', action)
|
|
}
|
|
successMethod(result)
|
|
} else if (result.jobstatus === 2) {
|
|
if (!bulkAction) {
|
|
message.error({
|
|
content: errorMessage,
|
|
key: jobId,
|
|
duration: 1
|
|
})
|
|
}
|
|
var errMessage = errorMessage
|
|
if (action && action.label) {
|
|
errMessage = i18n.global.t(action.label)
|
|
}
|
|
var desc = result.jobresult.errortext
|
|
if (name) {
|
|
desc = `(${name}) ${desc}`
|
|
}
|
|
let onClose = () => {}
|
|
if (!bulkAction) {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify++
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
onClose = () => {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify > 0 ? countNotify-- : countNotify = 0
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
}
|
|
}
|
|
notification.error({
|
|
top: '65px',
|
|
message: errMessage,
|
|
description: desc,
|
|
key: jobId,
|
|
duration: 0,
|
|
onClose: onClose
|
|
})
|
|
store.dispatch('AddHeaderNotice', {
|
|
key: jobId,
|
|
title,
|
|
description: desc,
|
|
status: 'failed',
|
|
duration: 2
|
|
})
|
|
eventBus.emit('update-job-details', { jobId, resourceId })
|
|
// Ensure we refresh on the same / parent page
|
|
const currentPage = this.$router.currentRoute.value.path
|
|
const samePage = options.originalPage === currentPage || options.originalPage.startsWith(currentPage + '/')
|
|
if (samePage && (!action || !('isFetchData' in action) || (action.isFetchData))) {
|
|
eventBus.emit('async-job-complete', action)
|
|
}
|
|
errorMethod(result)
|
|
} else if (result.jobstatus === 0) {
|
|
if (showLoading) {
|
|
message.loading({
|
|
content: loadingMessage,
|
|
key: jobId,
|
|
duration: 0
|
|
})
|
|
}
|
|
setTimeout(() => {
|
|
this.$pollJob(options, action)
|
|
}, 3000)
|
|
}
|
|
}).catch(e => {
|
|
console.error(`${catchMessage} - ${e}`)
|
|
if (!sourceToken.isCancel(e)) {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify++
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
notification.error({
|
|
top: '65px',
|
|
message: i18n.global.t('label.error'),
|
|
description: catchMessage,
|
|
duration: 0,
|
|
onClose: () => {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify > 0 ? countNotify-- : countNotify = 0
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
}
|
|
})
|
|
}
|
|
catchMethod && catchMethod()
|
|
})
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
export const notifierPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$notifyError = function (error) {
|
|
console.log(error)
|
|
var msg = i18n.global.t('message.request.failed')
|
|
var desc = ''
|
|
if (error && error.response) {
|
|
if (error.response.status) {
|
|
msg = `${i18n.global.t('message.request.failed')} (${error.response.status})`
|
|
}
|
|
if (error.message) {
|
|
desc = error.message
|
|
}
|
|
if (error.response.headers && 'x-description' in error.response.headers) {
|
|
desc = error.response.headers['x-description']
|
|
}
|
|
if (desc === '' && error.response.data) {
|
|
const responseKey = _.findKey(error.response.data, 'errortext')
|
|
if (responseKey) {
|
|
desc = error.response.data[responseKey].errortext
|
|
}
|
|
}
|
|
}
|
|
let countNotify = store.getters.countNotify
|
|
countNotify++
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
notification.error({
|
|
top: '65px',
|
|
message: msg,
|
|
description: desc,
|
|
duration: 0,
|
|
onClose: () => {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify > 0 ? countNotify-- : countNotify = 0
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
}
|
|
})
|
|
}
|
|
|
|
app.config.globalProperties.$notification = {
|
|
defaultConfig: {
|
|
top: '65px',
|
|
onClose: () => {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify > 0 ? countNotify-- : countNotify = 0
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
}
|
|
},
|
|
setCountNotify: () => {
|
|
let countNotify = store.getters.countNotify
|
|
countNotify++
|
|
store.commit('SET_COUNT_NOTIFY', countNotify)
|
|
},
|
|
info: (config) => {
|
|
app.config.globalProperties.$notification.setCountNotify()
|
|
config = Object.assign({}, app.config.globalProperties.$notification.defaultConfig, config)
|
|
notification.info(config)
|
|
},
|
|
error: (config) => {
|
|
app.config.globalProperties.$notification.setCountNotify()
|
|
config = Object.assign({}, app.config.globalProperties.$notification.defaultConfig, config)
|
|
notification.error(config)
|
|
},
|
|
success: (config) => {
|
|
app.config.globalProperties.$notification.setCountNotify()
|
|
config = Object.assign({}, app.config.globalProperties.$notification.defaultConfig, config)
|
|
notification.success(config)
|
|
},
|
|
warning: (config) => {
|
|
app.config.globalProperties.$notification.setCountNotify()
|
|
config = Object.assign({}, app.config.globalProperties.$notification.defaultConfig, config)
|
|
notification.warning(config)
|
|
},
|
|
warn: (config) => {
|
|
app.config.globalProperties.$notification.setCountNotify()
|
|
config = Object.assign({}, app.config.globalProperties.$notification.defaultConfig, config)
|
|
notification.warn(config)
|
|
},
|
|
close: (key) => notification.close(key),
|
|
destroy: () => notification.destroy()
|
|
}
|
|
}
|
|
}
|
|
|
|
export const toLocaleDatePlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$toLocaleDate = function (date) {
|
|
var timezoneOffset = this.$store.getters.timezoneoffset
|
|
if (this.$store.getters.usebrowsertimezone) {
|
|
// Since GMT+530 is returned as -330 (mins to GMT)
|
|
timezoneOffset = new Date().getTimezoneOffset() / -60
|
|
}
|
|
var milliseconds = Date.parse(date)
|
|
// e.g. "Tue, 08 Jun 2010 19:13:49 GMT", "Tue, 25 May 2010 12:07:01 UTC"
|
|
var dateWithOffset = new Date(milliseconds + (timezoneOffset * 60 * 60 * 1000)).toUTCString()
|
|
// e.g. "08 Jun 2010 19:13:49 GMT", "25 May 2010 12:07:01 UTC"
|
|
dateWithOffset = dateWithOffset.substring(dateWithOffset.indexOf(', ') + 2)
|
|
// e.g. "08 Jun 2010 19:13:49", "25 May 2010 12:10:16"
|
|
dateWithOffset = dateWithOffset.substring(0, dateWithOffset.length - 4)
|
|
return dateWithOffset
|
|
}
|
|
|
|
app.config.globalProperties.$toLocalDate = function (date) {
|
|
var timezoneOffset = this.$store.getters.timezoneoffset
|
|
if (this.$store.getters.usebrowsertimezone) {
|
|
// Since GMT+530 is returned as -330 (mins to GMT)
|
|
timezoneOffset = new Date().getTimezoneOffset() / -60
|
|
}
|
|
var milliseconds = Date.parse(date)
|
|
// e.g. "Tue, 08 Jun 2010 19:13:49 GMT", "Tue, 25 May 2010 12:07:01 UTC"
|
|
var dateWithOffset = new Date(milliseconds + (timezoneOffset * 60 * 60 * 1000))
|
|
return dateWithOffset.toISOString()
|
|
}
|
|
}
|
|
}
|
|
|
|
export const configUtilPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$applyDocHelpMappings = function (docHelp) {
|
|
var docHelpMappings = this.$config.docHelpMappings
|
|
if (docHelp && docHelpMappings &&
|
|
docHelpMappings.constructor === Object && Object.keys(docHelpMappings).length > 0) {
|
|
for (var key in docHelpMappings) {
|
|
if (docHelp.includes(key) && docHelp !== docHelpMappings[key]) {
|
|
docHelp = docHelp.replace(key, docHelpMappings[key])
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return docHelp
|
|
}
|
|
}
|
|
}
|
|
|
|
export const showIconPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$showIcon = function (resource) {
|
|
var resourceType = this.$route.path.split('/')[1]
|
|
if (resource) {
|
|
resourceType = resource
|
|
}
|
|
if (['zone', 'template', 'iso', 'account', 'accountuser', 'vm', 'domain', 'project', 'vpc', 'guestnetwork'].includes(resourceType)) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const resourceTypePlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$getResourceType = function () {
|
|
const type = this.$route.path.split('/')[1]
|
|
if (type === 'vm') {
|
|
return 'UserVM'
|
|
} else if (type === 'accountuser') {
|
|
return 'User'
|
|
} else if (type === 'guestnetwork') {
|
|
return 'Network'
|
|
} else {
|
|
return type
|
|
}
|
|
}
|
|
|
|
app.config.globalProperties.$getRouteFromResourceType = function (resourceType) {
|
|
switch (resourceType) {
|
|
case 'VirtualMachine':
|
|
return 'vm'
|
|
case 'DomainRouter':
|
|
return 'router'
|
|
case 'ConsoleProxy':
|
|
return 'systemvm'
|
|
case 'User':
|
|
return 'accountuser'
|
|
case 'Network':
|
|
return 'guestnetwork'
|
|
case 'ServiceOffering':
|
|
return 'computeoffering'
|
|
case 'IpAddress':
|
|
return 'publicip'
|
|
case 'NetworkAcl':
|
|
return 'acllist'
|
|
case 'SystemVm':
|
|
case 'PhysicalNetwork':
|
|
case 'Backup':
|
|
case 'SecurityGroup':
|
|
case 'StoragePool':
|
|
case 'ImageStore':
|
|
case 'Template':
|
|
case 'Iso':
|
|
case 'Host':
|
|
case 'Volume':
|
|
case 'Account':
|
|
case 'Snapshot':
|
|
case 'Project':
|
|
case 'Domain':
|
|
case 'DiskOffering':
|
|
case 'NetworkOffering':
|
|
case 'VpcOffering':
|
|
case 'BackupOffering':
|
|
case 'Zone':
|
|
case 'Vpc':
|
|
case 'VmSnapshot':
|
|
case 'Pod':
|
|
case 'Cluster':
|
|
case 'Role':
|
|
case 'AffinityGroup':
|
|
case 'VpnCustomerGateway':
|
|
return resourceType.toLowerCase()
|
|
}
|
|
return ''
|
|
}
|
|
|
|
app.config.globalProperties.$getIconFromResourceType = function (resourceType) {
|
|
var routePath = this.$getRouteFromResourceType(resourceType)
|
|
if (!routePath) return ''
|
|
var route = this.$router.resolve('/' + routePath)
|
|
return route?.meta?.icon || ''
|
|
}
|
|
}
|
|
}
|
|
|
|
export const apiMetaUtilPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$getApiParams = function () {
|
|
var apiParams = {}
|
|
for (var argument of arguments) {
|
|
var apiConfig = this.$store.getters.apis[argument] || {}
|
|
if (apiConfig && apiConfig.params) {
|
|
apiConfig.params.forEach(param => {
|
|
apiParams[param.name] = param
|
|
})
|
|
}
|
|
}
|
|
return apiParams
|
|
}
|
|
}
|
|
}
|
|
|
|
export const localesPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$t = i18n.global.t
|
|
}
|
|
}
|
|
|
|
const KB = 1024
|
|
const MB = 1024 * KB
|
|
const GB = 1024 * MB
|
|
const TB = 1024 * GB
|
|
|
|
export const fileSizeUtilPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$bytesToHumanReadableSize = function (bytes) {
|
|
if (bytes == null) {
|
|
return ''
|
|
}
|
|
if (bytes < KB && bytes >= 0) {
|
|
return bytes + ' bytes'
|
|
}
|
|
if (bytes < MB) {
|
|
return (bytes / KB).toFixed(2) + ' KB'
|
|
} else if (bytes < GB) {
|
|
return (bytes / MB).toFixed(2) + ' MB'
|
|
} else if (bytes < TB) {
|
|
return (bytes / GB).toFixed(2) + ' GB'
|
|
} else {
|
|
return (bytes / TB).toFixed(2) + ' TB'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const genericUtilPlugin = {
|
|
install (app) {
|
|
app.config.globalProperties.$isValidUuid = function (uuid) {
|
|
const regexExp = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi
|
|
return regexExp.test(uuid)
|
|
}
|
|
}
|
|
}
|
|
|
|
export function createPathBasedOnVmType (vmtype, virtualmachineid) {
|
|
let path = ''
|
|
switch (vmtype) {
|
|
case 'ConsoleProxy':
|
|
case 'SecondaryStorageVm':
|
|
path = '/systemvm/'
|
|
break
|
|
case 'DomainRouter':
|
|
path = '/router/'
|
|
break
|
|
default:
|
|
path = '/vm/'
|
|
}
|
|
|
|
return path + virtualmachineid
|
|
}
|