| // 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 { getAPI } from '@/api' | |
| import { message, notification, Modal } from 'ant-design-vue' | |
| import eventBus from '@/config/eventBus' | |
| import store from '@/store' | |
| import { sourceToken } from '@/utils/request' | |
| import { toLocalDate, toLocaleDate } from '@/utils/date' | |
| export const pollJobPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$pollJob = function (options) { | |
| /** | |
| * @param {String} jobId | |
| * @param {String} [name=''] | |
| * @param {String} [title=''] | |
| * @param {String} [description=''] | |
| * @param {Boolean} [showSuccessMessage=true] | |
| * @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 = '', | |
| showSuccessMessage = true, | |
| 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', | |
| timestamp: new Date() | |
| }) | |
| 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 | |
| getAPI('queryAsyncJobResult', { jobId }).then(json => { | |
| const result = json.queryasyncjobresultresponse | |
| eventBus.emit('update-job-details', { jobId, resourceId }) | |
| if (result.jobstatus === 1) { | |
| if (showSuccessMessage) { | |
| 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 | |
| }) | |
| } else { | |
| message.destroy(jobId) | |
| } | |
| store.dispatch('AddHeaderNotice', { | |
| key: jobId, | |
| title, | |
| description, | |
| status: 'done', | |
| duration: 2, | |
| timestamp: new Date() | |
| }) | |
| 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, | |
| timestamp: new Date() | |
| }) | |
| 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.response.headers?.['x-description']) { | |
| desc = error.response.headers['x-description'] | |
| } else if (error.response.data) { | |
| const responseKey = _.findKey(error.response.data, 'errortext') | |
| if (responseKey) { | |
| desc = error.response.data[responseKey].errortext | |
| } else if (typeof error.response.data === 'string') { | |
| desc = error.response.data | |
| } | |
| } | |
| if (!desc && error.message) { | |
| desc = error.message | |
| } | |
| } | |
| 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() | |
| } | |
| app.config.globalProperties.$messageConfigSuccess = function (msg, configrecord) { | |
| if (configrecord.isdynamic) { | |
| msg += `. ${this.$t('message.setting.update.delay')}` | |
| } | |
| message.success(msg) | |
| } | |
| } | |
| } | |
| export const toLocaleDatePlugin = { | |
| install (app) { | |
| app.config.globalProperties.$toLocaleDate = function (date) { | |
| const { timezoneoffset, usebrowsertimezone } = this.$store.getters | |
| return toLocaleDate({ date, timezoneoffset, usebrowsertimezone }) | |
| } | |
| app.config.globalProperties.$toLocalDate = function (date) { | |
| const { timezoneoffset, usebrowsertimezone } = this.$store.getters | |
| return toLocalDate({ date, timezoneoffset, usebrowsertimezone }).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', 'zones', 'template', 'iso', 'account', 'accountuser', 'vm', 'domain', 'project', 'vpc', 'guestnetwork', 'guestoscategory'].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 'KubernetesCluster': | |
| return 'kubernetes' | |
| case 'KubernetesSupportedVersion': | |
| return 'kubernetesiso' | |
| case 'ExtensionCustomAction': | |
| return 'customaction' | |
| 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': | |
| case 'AutoScaleVmGroup': | |
| case 'QuotaTariff': | |
| case 'GuestOsCategory': | |
| case 'Extension': | |
| return resourceType.toLowerCase() | |
| } | |
| return '' | |
| } | |
| app.config.globalProperties.$getIconFromResourceType = function (resourceType) { | |
| var routePath = this.$getRouteFromResourceType(resourceType) | |
| if (!routePath) return '' | |
| var route = this.$router.resolve('/' + routePath) | |
| if (routePath === 'kubernetes') { | |
| return route?.meta?.icon[0] | |
| } | |
| 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 KiB = 1024 | |
| const MiB = 1024 * KiB | |
| const GiB = 1024 * MiB | |
| const TiB = 1024 * GiB | |
| export const fileSizeUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$bytesToGiB = function (bytes) { | |
| if (bytes == null || bytes === 0) { | |
| return 0 | |
| } | |
| return (bytes / GiB).toFixed(2) | |
| } | |
| app.config.globalProperties.$bytesToHumanReadableSize = function (bytes) { | |
| if (bytes == null) { | |
| return '' | |
| } | |
| if (bytes < KiB && bytes >= 0) { | |
| return bytes + ' bytes' | |
| } | |
| if (bytes < MiB) { | |
| return (bytes / KiB).toFixed(2) + ' KiB' | |
| } else if (bytes < GiB) { | |
| return (bytes / MiB).toFixed(2) + ' MiB' | |
| } else if (bytes < TiB) { | |
| return (bytes / GiB).toFixed(2) + ' GiB' | |
| } else { | |
| return (bytes / TiB).toFixed(2) + ' TiB' | |
| } | |
| } | |
| } | |
| } | |
| function isBase64 (str) { | |
| try { | |
| const decoded = new TextDecoder().decode(Uint8Array.from(atob(str), c => c.charCodeAt(0))) | |
| return btoa(decoded) === str | |
| } catch (err) { | |
| return false | |
| } | |
| } | |
| 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) | |
| } | |
| app.config.globalProperties.$toBase64AndURIEncoded = function (text) { | |
| if (isBase64(text)) { | |
| return text | |
| } | |
| return encodeURI(btoa(unescape(encodeURIComponent(text)))) | |
| } | |
| } | |
| } | |
| 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 | |
| } | |
| export const dialogUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$resetConfigurationValueConfirm = function (configRecord, callback) { | |
| Modal.confirm({ | |
| title: i18n.global.t('label.reset.config.value'), | |
| content: `${i18n.global.t('message.confirm.reset.configuration.value').replace('%x', configRecord.name)}`, | |
| okText: i18n.global.t('label.yes'), | |
| cancelText: i18n.global.t('label.no'), | |
| okType: 'primary', | |
| onOk: () => callback(configRecord) | |
| }) | |
| } | |
| app.config.globalProperties.$notifyConfigurationValueChange = function (configRecord) { | |
| if (!configRecord || configRecord.isdynamic || store.getters.userInfo?.roletype !== 'Admin') { | |
| return | |
| } | |
| const server = configRecord.group === 'Usage Server' ? 'usage' : 'mgmt' | |
| this.$notification.warning({ | |
| message: this.$t('label.status'), | |
| description: this.$t('message.restart.' + server + '.server') | |
| }) | |
| } | |
| } | |
| } | |
| export const cpuArchitectureUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$fetchCpuArchitectureTypes = function () { | |
| const architectures = [ | |
| { id: 'x86_64', name: 'Intel/AMD 64 bits (x86_64)' }, | |
| { id: 'aarch64', name: 'ARM 64 bits (aarch64)' }, | |
| { id: 's390x', name: 'IBM Z 64 bits (s390x)' } | |
| ] | |
| return architectures.map(item => ({ ...item, description: item.name })) | |
| } | |
| } | |
| } | |
| export const imagesUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$fetchTemplateTypes = function (hypervisor) { | |
| const baseTypes = ['USER'] | |
| if (hypervisor === 'External') { | |
| return baseTypes.map(type => ({ id: type, name: type, description: type })) | |
| } | |
| baseTypes.push('VNF') | |
| const adminTypes = ['SYSTEM', 'BUILTIN', 'ROUTING'] | |
| const types = [...baseTypes] | |
| if (store.getters.userInfo?.roletype === 'Admin') { | |
| types.push(...adminTypes) | |
| } | |
| return types.map(type => ({ id: type, name: type, description: type })) | |
| } | |
| } | |
| } | |
| export const extensionsUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$fetchCustomActionRoleTypes = function () { | |
| const roleTypes = [] | |
| const roleTypesList = ['Admin', 'Resource Admin', 'Domain Admin', 'User'] | |
| roleTypesList.forEach((item) => { | |
| roleTypes.push({ | |
| id: item.replace(' ', ''), | |
| description: item | |
| }) | |
| }) | |
| return roleTypes | |
| } | |
| } | |
| } | |
| export const backupUtilPlugin = { | |
| install (app) { | |
| app.config.globalProperties.$isBackupProviderSupportsQuiesceVm = function (provider) { | |
| if (!provider && typeof provider !== 'string') { | |
| return false | |
| } | |
| return ['nas'].includes(provider.toLowerCase()) | |
| } | |
| } | |
| } |