You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2020/05/08 09:57:04 UTC

[cloudstack-primate] branch master updated: utils: introduce global API error notification (#296)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack-primate.git


The following commit(s) were added to refs/heads/master by this push:
     new e0802bf  utils: introduce global API error notification (#296)
e0802bf is described below

commit e0802bf84f50d0ba9e27ad71225d36c44c9f07a8
Author: Abhishek Kumar <ab...@gmail.com>
AuthorDate: Fri May 8 15:26:54 2020 +0530

    utils: introduce global API error notification (#296)
    
    Fixes #294
    
    Introduce a new global `this.$notifyError(error)` that takes in the `error` in a catch block and displays error notification with duration: 0, refactored to replace error handling codebase-wide.
    
    Signed-off-by: Abhishek Kumar <ab...@gmail.com>
    Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
    Co-authored-by: Rohit Yadav <ro...@shapeblue.com>
---
 src/components/view/DedicateData.vue               | 40 +++----------
 src/components/view/DedicateDomain.vue             | 12 +---
 src/components/view/DedicateModal.vue              | 20 ++-----
 src/components/view/DetailSettings.vue             |  5 +-
 src/components/view/ResourceLimitTab.vue           |  5 +-
 src/components/view/VmwareData.vue                 |  5 +-
 src/main.js                                        |  3 +-
 src/utils/plugins.js                               | 33 ++++++++++
 src/utils/request.js                               |  2 +-
 src/views/AutogenView.vue                          | 11 +---
 src/views/compute/AssignInstance.vue               |  5 +-
 src/views/compute/CreateKubernetesCluster.vue      |  5 +-
 src/views/compute/CreateSSHKeyPair.vue             | 10 +---
 src/views/compute/DeployVM.vue                     |  5 +-
 src/views/compute/InstanceHardware.vue             | 30 ++--------
 src/views/compute/KubernetesServiceTab.vue         | 15 +----
 src/views/compute/ScaleKubernetesCluster.vue       |  5 +-
 src/views/compute/UpgradeKubernetesCluster.vue     |  5 +-
 src/views/compute/backup/BackupSchedule.vue        |  5 +-
 src/views/compute/backup/FormSchedule.vue          |  5 +-
 src/views/iam/AddLdapAccount.vue                   | 15 +----
 src/views/iam/ChangeUserPassword.vue               |  5 +-
 src/views/iam/SSLCertificateTab.vue                | 10 +---
 src/views/image/AddKubernetesSupportedVersion.vue  |  5 +-
 src/views/image/IsoZones.vue                       |  5 +-
 src/views/image/RegisterOrUploadIso.vue            | 12 +---
 src/views/image/RegisterOrUploadTemplate.vue       | 12 +---
 src/views/image/TemplateZones.vue                  |  5 +-
 .../image/UpdateKubernetesSupportedVersion.vue     |  5 +-
 src/views/image/UpdateTemplateIsoPermissions.vue   |  7 +--
 src/views/infra/AddPrimaryStorage.vue              |  5 +-
 src/views/infra/AddSecondaryStorage.vue            |  5 +-
 src/views/infra/ClusterAdd.vue                     | 15 +----
 src/views/infra/HostAdd.vue                        | 20 ++-----
 src/views/infra/HostInfoTab.vue                    |  5 +-
 src/views/infra/PodAdd.vue                         |  5 +-
 src/views/infra/network/DedicatedVLANTab.vue       | 20 ++-----
 src/views/infra/network/IpRangesTabManagement.vue  | 18 +-----
 src/views/infra/network/IpRangesTabPublic.vue      | 30 ++--------
 src/views/infra/network/IpRangesTabStorage.vue     | 24 ++------
 src/views/infra/network/ServiceProvidersTab.vue    |  6 +-
 src/views/infra/network/TrafficTypesTab.vue        | 10 +---
 src/views/infra/zone/PhysicalNetworksTab.vue       |  5 +-
 src/views/infra/zone/SystemVmsTab.vue              |  5 +-
 src/views/infra/zone/ZoneResources.vue             |  5 +-
 src/views/network/AclListRulesTab.vue              | 40 +++----------
 src/views/network/CreateIsolatedNetworkForm.vue    |  5 +-
 src/views/network/CreateL2NetworkForm.vue          |  5 +-
 src/views/network/CreateSharedNetworkForm.vue      |  5 +-
 src/views/network/EgressRulesTab.vue               | 10 +---
 src/views/network/EnableStaticNat.vue              | 26 ++------
 src/views/network/FirewallRules.vue                | 30 ++--------
 src/views/network/IngressEgressRuleConfigure.vue   | 28 ++-------
 src/views/network/InternalLBAssignVmForm.vue       |  5 +-
 src/views/network/LoadBalancing.vue                | 70 +++++-----------------
 src/views/network/PortForwarding.vue               | 40 +++----------
 src/views/network/RoutersTab.vue                   |  6 +-
 src/views/network/StaticRoutesTab.vue              | 30 ++--------
 src/views/network/VpcTab.vue                       | 50 ++++------------
 src/views/network/VpcTiersTab.vue                  | 18 +-----
 src/views/network/VpnDetails.vue                   | 17 +-----
 src/views/offering/AddComputeOffering.vue          |  5 +-
 src/views/offering/AddDiskOffering.vue             |  5 +-
 src/views/offering/AddNetworkOffering.vue          |  5 +-
 src/views/offering/AddVpcOffering.vue              |  5 +-
 src/views/offering/ImportBackupOffering.vue        | 15 +----
 src/views/offering/UpdateOfferingAccess.vue        |  5 +-
 src/views/plugins/CloudianPlugin.vue               |  7 +--
 src/views/project/AccountsTab.vue                  | 15 +----
 src/views/project/InvitationTokenTemplate.vue      |  5 +-
 src/views/project/InvitationsTemplate.vue          | 10 +---
 src/views/storage/CreateVolume.vue                 |  5 +-
 src/views/storage/FormSchedule.vue                 |  5 +-
 src/views/storage/MigrateVolume.vue                | 20 ++-----
 src/views/storage/RestoreAttachBackupVolume.vue    | 10 +---
 src/views/storage/ScheduledSnapshots.vue           |  5 +-
 src/views/storage/TakeSnapshot.vue                 |  5 +-
 77 files changed, 223 insertions(+), 774 deletions(-)

diff --git a/src/components/view/DedicateData.vue b/src/components/view/DedicateData.vue
index 28ff13e..b35d6c9 100644
--- a/src/components/view/DedicateData.vue
+++ b/src/components/view/DedicateData.vue
@@ -121,10 +121,7 @@ export default {
           this.dedicatedAccountId = response.listdedicatedzonesresponse.dedicatedzone[0].accountid
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     fetchDedicatedPods () {
@@ -137,10 +134,7 @@ export default {
           this.dedicatedAccountId = response.listdedicatedpodsresponse.dedicatedpod[0].accountid
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     fetchDedicatedClusters () {
@@ -153,10 +147,7 @@ export default {
           this.dedicatedAccountId = response.listdedicatedclustersresponse.dedicatedcluster[0].accountid
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     fetchDedicatedHosts () {
@@ -169,10 +160,7 @@ export default {
           this.dedicatedAccountId = response.listdedicatedhostsresponse.dedicatedhost[0].accountid
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     releaseDedidcatedZone () {
@@ -202,10 +190,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     releaseDedidcatedPod () {
@@ -235,10 +220,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     releaseDedidcatedCluster () {
@@ -268,10 +250,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     releaseDedidcatedHost () {
@@ -301,10 +280,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     handleRelease () {
diff --git a/src/components/view/DedicateDomain.vue b/src/components/view/DedicateDomain.vue
index eebf6e8..5dcf859 100644
--- a/src/components/view/DedicateDomain.vue
+++ b/src/components/view/DedicateDomain.vue
@@ -80,12 +80,9 @@ export default {
           this.domainId = this.domainsList[0].id
           this.handleChangeDomain(this.domainId)
         }
-        this.domainsLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
+      }).finally(() => {
         this.domainsLoading = false
       })
     },
@@ -98,10 +95,7 @@ export default {
           this.handleChangeAccount(null)
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     handleChangeDomain (e) {
diff --git a/src/components/view/DedicateModal.vue b/src/components/view/DedicateModal.vue
index 6dcbfed..73b0e43 100644
--- a/src/components/view/DedicateModal.vue
+++ b/src/components/view/DedicateModal.vue
@@ -118,10 +118,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.dedicatedDomainModal = false
       })
     },
@@ -165,10 +162,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.dedicatedDomainModal = false
       })
     },
@@ -212,10 +206,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.dedicatedDomainModal = false
       })
     },
@@ -259,10 +250,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.dedicatedDomainModal = false
       })
     },
diff --git a/src/components/view/DetailSettings.vue b/src/components/view/DetailSettings.vue
index 72744e3..3090856 100644
--- a/src/components/view/DetailSettings.vue
+++ b/src/components/view/DetailSettings.vue
@@ -193,10 +193,7 @@ export default {
           return { name: k, value: details[k], edit: false }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: 'Failed to add setting',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(f => {
         this.loading = false
         this.showAddDetail = false
diff --git a/src/components/view/ResourceLimitTab.vue b/src/components/view/ResourceLimitTab.vue
index bb90fe0..b28a58f 100644
--- a/src/components/view/ResourceLimitTab.vue
+++ b/src/components/view/ResourceLimitTab.vue
@@ -135,10 +135,7 @@ export default {
           this.$message.success('Apply Successful')
           this.fetchData()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.formLoading = false
         })
diff --git a/src/components/view/VmwareData.vue b/src/components/view/VmwareData.vue
index d483e99..9e23a9f 100644
--- a/src/components/view/VmwareData.vue
+++ b/src/components/view/VmwareData.vue
@@ -71,10 +71,7 @@ export default {
         }
         this.$set(this.resource, 'vmwaredc', this.vmwaredc)
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     }
   }
diff --git a/src/main.js b/src/main.js
index 1d83fd5..267a0c4 100644
--- a/src/main.js
+++ b/src/main.js
@@ -27,11 +27,12 @@ import './core/use'
 import './core/ext'
 import './permission' // permission control
 import './utils/filter' // global filter
-import { pollJobPlugin } from './utils/plugins'
+import { pollJobPlugin, notifierPlugin } from './utils/plugins'
 
 Vue.config.productionTip = false
 Vue.use(VueAxios, router)
 Vue.use(pollJobPlugin)
+Vue.use(notifierPlugin)
 
 new Vue({
   router,
diff --git a/src/utils/plugins.js b/src/utils/plugins.js
index 6c69cf1..6711751 100644
--- a/src/utils/plugins.js
+++ b/src/utils/plugins.js
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+import _ from 'lodash'
 import { api } from '@/api'
 import { message, notification } from 'ant-design-vue'
 
@@ -77,3 +78,35 @@ export const pollJobPlugin = {
   }
 
 }
+
+export const notifierPlugin = {
+
+  install (Vue) {
+    Vue.prototype.$notifyError = function (error) {
+      var msg = 'Request Failed'
+      var desc = ''
+      if (error && error.response) {
+        if (error.response.status) {
+          msg = `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
+          }
+        }
+      }
+      notification.error({
+        message: msg,
+        description: error && error.response && 'x-description' in error.response.headers ? error.response.headers['x-description'] : error.message,
+        duration: 0
+      })
+    }
+  }
+}
diff --git a/src/utils/request.js b/src/utils/request.js
index 962a2ad..d2abe4f 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -41,7 +41,7 @@ const err = (error) => {
       if (response.config && response.config.params && ['listIdps'].includes(response.config.params.command)) {
         return
       }
-      notification.error({ message: 'Unauthorized', description: 'Authorization verification failed' })
+      notification.error({ message: 'Unauthorized', description: 'Session expired, authorization verification failed' })
       if (token) {
         store.dispatch('Logout').then(() => {
           setTimeout(() => {
diff --git a/src/views/AutogenView.vue b/src/views/AutogenView.vue
index 1db2b17..38fb535 100644
--- a/src/views/AutogenView.vue
+++ b/src/views/AutogenView.vue
@@ -507,11 +507,7 @@ export default {
           this.treeSelected = {}
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
 
         if ([401, 405].includes(error.response.status)) {
           this.$router.push({ path: '/exception/403' })
@@ -771,10 +767,7 @@ export default {
             }
           }).catch(error => {
             console.log(error)
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-            })
+            this.$notifyError(error)
           }).finally(f => {
             this.closeAction()
           })
diff --git a/src/views/compute/AssignInstance.vue b/src/views/compute/AssignInstance.vue
index 3945e90..0798d5f 100644
--- a/src/views/compute/AssignInstance.vue
+++ b/src/views/compute/AssignInstance.vue
@@ -216,10 +216,7 @@ export default {
         this.$parent.$parent.close()
         this.parentFetchData()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Failed to assign instance',
-          description: error.response.data.assignvirtualmachineresponse.errortext && error.response.data.assignvirtualmachineresponse.errortext
-        })
+        this.$notifyError(error)
         this.$parent.$parent.close()
         this.parentFetchData()
       })
diff --git a/src/views/compute/CreateKubernetesCluster.vue b/src/views/compute/CreateKubernetesCluster.vue
index 4dd0c3b..25c1b78 100644
--- a/src/views/compute/CreateKubernetesCluster.vue
+++ b/src/views/compute/CreateKubernetesCluster.vue
@@ -405,10 +405,7 @@ export default {
         api('createKubernetesCluster', params).then(json => {
           this.$message.success('Successfully created Kubernetes cluster: ' + values.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/compute/CreateSSHKeyPair.vue b/src/views/compute/CreateSSHKeyPair.vue
index 7b1dfad..f5a4551 100644
--- a/src/views/compute/CreateSSHKeyPair.vue
+++ b/src/views/compute/CreateSSHKeyPair.vue
@@ -166,10 +166,7 @@ export default {
           api('registerSSHKeyPair', params).then(json => {
             this.$message.success('Successfully registered SSH key pair: ' + values.name)
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.$emit('refresh-data')
             this.loading = false
@@ -186,10 +183,7 @@ export default {
               })
             }
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.$emit('refresh-data')
             this.loading = false
diff --git a/src/views/compute/DeployVM.vue b/src/views/compute/DeployVM.vue
index 5b507b2..4459141 100644
--- a/src/views/compute/DeployVM.vue
+++ b/src/views/compute/DeployVM.vue
@@ -946,10 +946,7 @@ export default {
           }
           this.$router.back()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading.deploy = false
         })
diff --git a/src/views/compute/InstanceHardware.vue b/src/views/compute/InstanceHardware.vue
index 14a37d5..ab4b147 100644
--- a/src/views/compute/InstanceHardware.vue
+++ b/src/views/compute/InstanceHardware.vue
@@ -422,10 +422,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loadingNic = false
       })
     },
@@ -455,10 +452,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loadingNic = false
       })
     },
@@ -493,10 +487,7 @@ export default {
         })
       })
         .catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
           this.loadingNic = false
         })
     },
@@ -528,10 +519,7 @@ export default {
         })
       })
         .catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
           this.loadingNic = false
         })
     },
@@ -568,10 +556,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.addiptovmnicresponse.errortext
-        })
+        this.$notifyError(error)
         this.loadingNic = false
       })
     },
@@ -602,10 +587,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loadingNic = false
         this.fetchSecondaryIPs(this.selectedNicId)
       })
diff --git a/src/views/compute/KubernetesServiceTab.vue b/src/views/compute/KubernetesServiceTab.vue
index 1f6fd4b..4b597eb 100644
--- a/src/views/compute/KubernetesServiceTab.vue
+++ b/src/views/compute/KubernetesServiceTab.vue
@@ -293,10 +293,7 @@ export default {
             this.kubernetesVersion = versionObjs[0]
           }
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.versionLoading = false
           if (!this.isObjectEmpty(this.kubernetesVersion) && this.isValidValueForKey(this.kubernetesVersion, 'semanticversion')) {
@@ -333,10 +330,7 @@ export default {
             this.virtualmachines = this.virtualmachines.concat(listVms)
           }
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.instanceLoading = false
         })
@@ -363,10 +357,7 @@ export default {
           this.publicIpAddress = ips[0]
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.networkLoading = false
       })
diff --git a/src/views/compute/ScaleKubernetesCluster.vue b/src/views/compute/ScaleKubernetesCluster.vue
index 31c9b86..c30b421 100644
--- a/src/views/compute/ScaleKubernetesCluster.vue
+++ b/src/views/compute/ScaleKubernetesCluster.vue
@@ -173,10 +173,7 @@ export default {
         api('scaleKubernetesCluster', params).then(json => {
           this.$message.success('Successfully scaled Kubernetes cluster: ' + this.resource.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/compute/UpgradeKubernetesCluster.vue b/src/views/compute/UpgradeKubernetesCluster.vue
index 9cf5f9f..bd96ae9 100644
--- a/src/views/compute/UpgradeKubernetesCluster.vue
+++ b/src/views/compute/UpgradeKubernetesCluster.vue
@@ -149,10 +149,7 @@ export default {
         api('upgradeKubernetesCluster', params).then(json => {
           this.$message.success('Successfully upgraded Kubernetes cluster: ' + this.resource.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/compute/backup/BackupSchedule.vue b/src/views/compute/backup/BackupSchedule.vue
index a74d89a..9c6bf67 100644
--- a/src/views/compute/backup/BackupSchedule.vue
+++ b/src/views/compute/backup/BackupSchedule.vue
@@ -164,10 +164,7 @@ export default {
         }
         this.refreshSchedule()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.actionLoading = false
       })
diff --git a/src/views/compute/backup/FormSchedule.vue b/src/views/compute/backup/FormSchedule.vue
index bbc2883..981e6a9 100644
--- a/src/views/compute/backup/FormSchedule.vue
+++ b/src/views/compute/backup/FormSchedule.vue
@@ -274,10 +274,7 @@ export default {
           this.refreshSchedule()
           this.resetForm()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.actionLoading = false
         })
diff --git a/src/views/iam/AddLdapAccount.vue b/src/views/iam/AddLdapAccount.vue
index 59dff86..1fdb098 100644
--- a/src/views/iam/AddLdapAccount.vue
+++ b/src/views/iam/AddLdapAccount.vue
@@ -198,10 +198,7 @@ export default {
         this.fetchListDomains(),
         this.fetchListRoles()
       ]).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.listLoading = false
         this.timeZoneLoading = false
@@ -319,10 +316,7 @@ export default {
           this.$emit('refresh-data')
           this.handleClose()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
           this.$emit('refresh-data')
         }).finally(() => {
           this.loading = false
@@ -365,10 +359,7 @@ export default {
         }))
       }
       Promise.all(promises).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       })
     },
     onSelectChange (selectedRowKeys) {
diff --git a/src/views/iam/ChangeUserPassword.vue b/src/views/iam/ChangeUserPassword.vue
index 927312c..d6f7744 100644
--- a/src/views/iam/ChangeUserPassword.vue
+++ b/src/views/iam/ChangeUserPassword.vue
@@ -146,10 +146,7 @@ export default {
             description: 'Successfully changed password for user "' + this.resource.username + '"'
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Error',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/iam/SSLCertificateTab.vue b/src/views/iam/SSLCertificateTab.vue
index a6941f0..0a67e5c 100644
--- a/src/views/iam/SSLCertificateTab.vue
+++ b/src/views/iam/SSLCertificateTab.vue
@@ -164,10 +164,7 @@ export default {
 
         this.dataSource = listSslResponse
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -203,10 +200,7 @@ export default {
         setTimeout(loading)
 
         // show error
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       })
     },
     onShowConfirm (row) {
diff --git a/src/views/image/AddKubernetesSupportedVersion.vue b/src/views/image/AddKubernetesSupportedVersion.vue
index 96a308f..089348f 100644
--- a/src/views/image/AddKubernetesSupportedVersion.vue
+++ b/src/views/image/AddKubernetesSupportedVersion.vue
@@ -206,10 +206,7 @@ export default {
         api('addKubernetesSupportedVersion', params).then(json => {
           this.$message.success('Successfully added Kubernetes version: ' + values.semanticversion)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/image/IsoZones.vue b/src/views/image/IsoZones.vue
index b08bf99..34cbe1b 100644
--- a/src/views/image/IsoZones.vue
+++ b/src/views/image/IsoZones.vue
@@ -127,10 +127,7 @@ export default {
           this.itemCount = count
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/image/RegisterOrUploadIso.vue b/src/views/image/RegisterOrUploadIso.vue
index 6648336..d61142b 100644
--- a/src/views/image/RegisterOrUploadIso.vue
+++ b/src/views/image/RegisterOrUploadIso.vue
@@ -334,11 +334,7 @@ export default {
               description: 'Sucessfully registered ISO ' + params.name
             })
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message,
-              duration: 0
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.loading = false
             this.closeAction()
@@ -359,11 +355,7 @@ export default {
               })
             }
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message,
-              duration: 0
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.loading = false
           })
diff --git a/src/views/image/RegisterOrUploadTemplate.vue b/src/views/image/RegisterOrUploadTemplate.vue
index 00bcacb..abbaf49 100644
--- a/src/views/image/RegisterOrUploadTemplate.vue
+++ b/src/views/image/RegisterOrUploadTemplate.vue
@@ -873,11 +873,7 @@ export default {
               description: 'Successfully registered template ' + params.name
             })
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message,
-              duration: 0
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.loading = false
             this.closeAction()
@@ -895,11 +891,7 @@ export default {
             this.uploadParams = (json.postuploadtemplateresponse && json.postuploadtemplateresponse.getuploadparams) ? json.postuploadtemplateresponse.getuploadparams : ''
             this.handleUpload()
           }).catch(error => {
-            this.$notification.error({
-              message: 'Request Failed',
-              description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message,
-              duration: 0
-            })
+            this.$notifyError(error)
           }).finally(() => {
             this.loading = false
           })
diff --git a/src/views/image/TemplateZones.vue b/src/views/image/TemplateZones.vue
index 46661bb..0583d8f 100644
--- a/src/views/image/TemplateZones.vue
+++ b/src/views/image/TemplateZones.vue
@@ -124,10 +124,7 @@ export default {
           this.itemCount = count
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/image/UpdateKubernetesSupportedVersion.vue b/src/views/image/UpdateKubernetesSupportedVersion.vue
index 7172fa4..a0a2255 100644
--- a/src/views/image/UpdateKubernetesSupportedVersion.vue
+++ b/src/views/image/UpdateKubernetesSupportedVersion.vue
@@ -131,10 +131,7 @@ export default {
         api('updateKubernetesSupportedVersion', params).then(json => {
           this.$message.success('Successfully updated Kubernetes supported version: ' + this.resource.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/image/UpdateTemplateIsoPermissions.vue b/src/views/image/UpdateTemplateIsoPermissions.vue
index 843a14f..ecde71d 100644
--- a/src/views/image/UpdateTemplateIsoPermissions.vue
+++ b/src/views/image/UpdateTemplateIsoPermissions.vue
@@ -254,12 +254,7 @@ export default {
           })
         })
         .catch(error => {
-          this.$notification.error({
-            message: 'Failed to update ' + resourceType + ' permissions',
-            description: this.isImageTypeIso
-              ? error.response.data.updateisopermissions.errortext
-              : error.response.data.updatetemplatepermissions.errortext
-          })
+          this.$notifyError(error)
         })
         .finally(e => {
           this.loading = false
diff --git a/src/views/infra/AddPrimaryStorage.vue b/src/views/infra/AddPrimaryStorage.vue
index 5cb4ded..6de0af6 100644
--- a/src/views/infra/AddPrimaryStorage.vue
+++ b/src/views/infra/AddPrimaryStorage.vue
@@ -534,10 +534,7 @@ export default {
             description: this.$t('label.add.primary.storage')
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.closeModal()
diff --git a/src/views/infra/AddSecondaryStorage.vue b/src/views/infra/AddSecondaryStorage.vue
index 6a97dd6..ddcfec4 100644
--- a/src/views/infra/AddSecondaryStorage.vue
+++ b/src/views/infra/AddSecondaryStorage.vue
@@ -278,10 +278,7 @@ export default {
             description: this.$t('label.add.secondary.storage')
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.closeModal()
diff --git a/src/views/infra/ClusterAdd.vue b/src/views/infra/ClusterAdd.vue
index a84963c..ad142ed 100644
--- a/src/views/infra/ClusterAdd.vue
+++ b/src/views/infra/ClusterAdd.vue
@@ -167,10 +167,7 @@ export default {
         this.zoneId = this.zonesList[0].id || null
         this.fetchPods()
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -181,10 +178,7 @@ export default {
         this.hypervisorsList = response.listhypervisorsresponse.hypervisor || []
         this.hypervisor = this.hypervisorsList[0].name || null
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -197,10 +191,7 @@ export default {
         this.podsList = response.listpodsresponse.pod || []
         this.podId = this.podsList[0].id || null
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
diff --git a/src/views/infra/HostAdd.vue b/src/views/infra/HostAdd.vue
index b77e651..a86c64b 100644
--- a/src/views/infra/HostAdd.vue
+++ b/src/views/infra/HostAdd.vue
@@ -188,10 +188,7 @@ export default {
         this.zoneId = this.zonesList[0].id || null
         this.fetchPods()
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -205,10 +202,7 @@ export default {
         this.podId = this.podsList[0].id || null
         this.fetchClusters()
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.podsList = []
         this.podId = ''
       }).finally(() => {
@@ -226,10 +220,7 @@ export default {
           this.handleChangeCluster()
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listclustersresponse.errortext
-        })
+        this.$notifyError(error)
         this.clustersList = []
         this.clusterId = null
       }).finally(() => {
@@ -241,10 +232,7 @@ export default {
       api('listHostTags').then(response => {
         this.hostTagsList = response.listhosttagsresponse.hosttag || []
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listhosttagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.hostTagsList = []
       }).finally(() => {
         this.loading = false
diff --git a/src/views/infra/HostInfoTab.vue b/src/views/infra/HostInfoTab.vue
index 31e95c7..ad71712 100644
--- a/src/views/infra/HostInfoTab.vue
+++ b/src/views/infra/HostInfoTab.vue
@@ -135,10 +135,7 @@ export default {
       api('listHosts', { id: this.resource.id }).then(json => {
         this.host = json.listhostsresponse.host[0]
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/infra/PodAdd.vue b/src/views/infra/PodAdd.vue
index ae5ec5a..eeab99d 100644
--- a/src/views/infra/PodAdd.vue
+++ b/src/views/infra/PodAdd.vue
@@ -161,10 +161,7 @@ export default {
         this.params = this.$store.getters.apis.createPod.params
         Object.keys(this.placeholder).forEach(item => { this.returnPlaceholder(item) })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
diff --git a/src/views/infra/network/DedicatedVLANTab.vue b/src/views/infra/network/DedicatedVLANTab.vue
index 48d041d..0c0c1cd 100644
--- a/src/views/infra/network/DedicatedVLANTab.vue
+++ b/src/views/infra/network/DedicatedVLANTab.vue
@@ -220,10 +220,7 @@ export default {
         }
         this.formLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.formLoading = false
       })
     },
@@ -247,10 +244,7 @@ export default {
         }
         this.formLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.formLoading = false
       })
     },
@@ -273,10 +267,7 @@ export default {
         }
         this.formLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.formLoading = false
       })
     },
@@ -334,10 +325,7 @@ export default {
           this.modal = false
           this.fetchData()
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.dedicateguestvlanrangeresponse.errortext
-          })
+          this.$notifyError(error)
           this.modal = false
           this.fetchData()
         })
diff --git a/src/views/infra/network/IpRangesTabManagement.vue b/src/views/infra/network/IpRangesTabManagement.vue
index 3fb324a..04cb9c8 100644
--- a/src/views/infra/network/IpRangesTabManagement.vue
+++ b/src/views/infra/network/IpRangesTabManagement.vue
@@ -220,11 +220,7 @@ export default {
         }
       }).catch(error => {
         console.log(error)
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listpodsresponse
-            ? error.response.data.listpodsresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
       })
@@ -271,11 +267,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletemanagementnetworkiprangeresponse
-            ? error.response.data.deletemanagementnetworkiprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.componentLoading = false
         this.fetchData()
       })
@@ -319,11 +311,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createmanagementnetworkiprangeresponse
-              ? error.response.data.createmanagementnetworkiprangeresponse.errortext : error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.componentLoading = false
           this.fetchData()
diff --git a/src/views/infra/network/IpRangesTabPublic.vue b/src/views/infra/network/IpRangesTabPublic.vue
index 7fa4f72..4428528 100644
--- a/src/views/infra/network/IpRangesTabPublic.vue
+++ b/src/views/infra/network/IpRangesTabPublic.vue
@@ -268,11 +268,7 @@ export default {
       }).then(response => {
         this.items = response.listvlaniprangesresponse.vlaniprange ? response.listvlaniprangesresponse.vlaniprange : []
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listvlaniprangesresponse
-            ? error.response.data.listvlaniprangesresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
       })
@@ -289,11 +285,7 @@ export default {
           this.form.setFieldsValue({ domain: this.domains[0].id })
         }
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listdomains
-            ? error.response.data.listdomains.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.domainsLoading = false
       })
@@ -312,11 +304,7 @@ export default {
         domainid: this.addAccount.domain,
         account: this.addAccount.account
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.dedicatepubliciprangeresponse
-            ? error.response.data.dedicatepubliciprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.addAccountModal = false
         this.domainsLoading = false
@@ -326,11 +314,7 @@ export default {
     handleRemoveAccount (id) {
       this.componentLoading = true
       api('releasePublicIpRange', { id }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.releasepubliciprangeresponse
-            ? error.response.data.releasepubliciprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchData()
       })
@@ -364,11 +348,7 @@ export default {
           message: 'Removed IP Range'
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletevlaniprangeresponse
-            ? error.response.data.deletevlaniprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
         this.fetchData()
diff --git a/src/views/infra/network/IpRangesTabStorage.vue b/src/views/infra/network/IpRangesTabStorage.vue
index f506e3f..d179650 100644
--- a/src/views/infra/network/IpRangesTabStorage.vue
+++ b/src/views/infra/network/IpRangesTabStorage.vue
@@ -190,11 +190,7 @@ export default {
       }).then(response => {
         this.items = response.liststoragenetworkiprangeresponse.storagenetworkiprange ? response.liststoragenetworkiprangeresponse.storagenetworkiprange : []
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.liststoragenetworkiprangeresponse
-            ? error.response.data.liststoragenetworkiprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
       })
@@ -206,11 +202,7 @@ export default {
       }).then(response => {
         this.pods = response.listpodsresponse.pod ? response.listpodsresponse.pod : []
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.listpodsresponse
-            ? error.response.data.listpodsresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
       })
@@ -256,11 +248,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletestoragenetworkiprangeresponse
-            ? error.response.data.deletestoragenetworkiprangeresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.componentLoading = false
         this.fetchData()
       })
@@ -304,11 +292,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createstoragenetworkiprangeresponse
-              ? error.response.data.createstoragenetworkiprangeresponse.errortext : error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.componentLoading = false
           this.fetchData()
diff --git a/src/views/infra/network/ServiceProvidersTab.vue b/src/views/infra/network/ServiceProvidersTab.vue
index cb44236..fce0488 100644
--- a/src/views/infra/network/ServiceProvidersTab.vue
+++ b/src/views/infra/network/ServiceProvidersTab.vue
@@ -129,11 +129,7 @@ export default {
           }
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/infra/network/TrafficTypesTab.vue b/src/views/infra/network/TrafficTypesTab.vue
index 60c8b1f..1fb714a 100644
--- a/src/views/infra/network/TrafficTypesTab.vue
+++ b/src/views/infra/network/TrafficTypesTab.vue
@@ -99,10 +99,7 @@ export default {
       api('listTrafficTypes', { physicalnetworkid: this.resource.id }).then(json => {
         this.traffictypes = json.listtraffictypesresponse.traffictype
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -116,10 +113,7 @@ export default {
       }).then(json => {
         this.publicNetwork = json.listnetworksresponse.network[0] || {}
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/infra/zone/PhysicalNetworksTab.vue b/src/views/infra/zone/PhysicalNetworksTab.vue
index 7c0e1e9..b46b6bc 100644
--- a/src/views/infra/zone/PhysicalNetworksTab.vue
+++ b/src/views/infra/zone/PhysicalNetworksTab.vue
@@ -102,10 +102,7 @@ export default {
       api('listPhysicalNetworks', { zoneid: this.resource.id }).then(json => {
         this.networks = json.listphysicalnetworksresponse.physicalnetwork || []
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/infra/zone/SystemVmsTab.vue b/src/views/infra/zone/SystemVmsTab.vue
index d1d8a21..34744fe 100644
--- a/src/views/infra/zone/SystemVmsTab.vue
+++ b/src/views/infra/zone/SystemVmsTab.vue
@@ -110,10 +110,7 @@ export default {
       api('listSystemVms', { zoneid: this.resource.id }).then(json => {
         this.vms = json.listsystemvmsresponse.systemvm || []
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/infra/zone/ZoneResources.vue b/src/views/infra/zone/ZoneResources.vue
index ac20041..0531fea 100644
--- a/src/views/infra/zone/ZoneResources.vue
+++ b/src/views/infra/zone/ZoneResources.vue
@@ -73,10 +73,7 @@ export default {
         this.resourcesList = response.listcapacityresponse.capacity
         this.animatePercentVals()
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/network/AclListRulesTab.vue b/src/views/network/AclListRulesTab.vue
index 70a5294..2a4cc5f 100644
--- a/src/views/network/AclListRulesTab.vue
+++ b/src/views/network/AclListRulesTab.vue
@@ -271,10 +271,7 @@ export default {
           this.acls.sort((a, b) => a.number - b.number)
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -287,10 +284,7 @@ export default {
       }).then(response => {
         this.tags = response.listtagsresponse.tag || []
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     openTagsModal (acl) {
@@ -332,10 +326,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.tagsLoading = false
       })
     },
@@ -380,10 +371,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createtagsresponse.errortext
-          })
+          this.$notifyError(error)
           this.tagsLoading = false
         })
       })
@@ -451,10 +439,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createnetworkaclresponse.errortext
-          })
+          this.$notifyError(error)
           this.fetchLoading = false
         })
       })
@@ -487,10 +472,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletenetworkaclresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchLoading = false
       })
     },
@@ -552,10 +534,7 @@ export default {
             description: 'Successfully added new rule'
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.fetchLoading = false
           this.fetchData()
@@ -602,10 +581,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
         this.fetchLoading = false
       })
     },
diff --git a/src/views/network/CreateIsolatedNetworkForm.vue b/src/views/network/CreateIsolatedNetworkForm.vue
index ca5da48..15ebf19 100644
--- a/src/views/network/CreateIsolatedNetworkForm.vue
+++ b/src/views/network/CreateIsolatedNetworkForm.vue
@@ -409,10 +409,7 @@ export default {
           })
           this.$emit('refresh-data')
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.actionLoading = false
           this.closeAction()
diff --git a/src/views/network/CreateL2NetworkForm.vue b/src/views/network/CreateL2NetworkForm.vue
index 472a0bc..4eff20a 100644
--- a/src/views/network/CreateL2NetworkForm.vue
+++ b/src/views/network/CreateL2NetworkForm.vue
@@ -329,10 +329,7 @@ export default {
             description: 'Successfully created L2 network'
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.actionLoading = false
diff --git a/src/views/network/CreateSharedNetworkForm.vue b/src/views/network/CreateSharedNetworkForm.vue
index 39d9fc2..2303fee 100644
--- a/src/views/network/CreateSharedNetworkForm.vue
+++ b/src/views/network/CreateSharedNetworkForm.vue
@@ -652,10 +652,7 @@ export default {
           })
           this.resetForm()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.actionLoading = false
diff --git a/src/views/network/EgressRulesTab.vue b/src/views/network/EgressRulesTab.vue
index df78788..8830b03 100644
--- a/src/views/network/EgressRulesTab.vue
+++ b/src/views/network/EgressRulesTab.vue
@@ -199,10 +199,7 @@ export default {
           catchMethod: () => this.fetchData()
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
       })
     },
@@ -229,10 +226,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createegressfirewallruleresponse.errortext
-        })
+        this.$notifyError(error)
         this.resetAllRules()
         this.fetchData()
       })
diff --git a/src/views/network/EnableStaticNat.vue b/src/views/network/EnableStaticNat.vue
index 2a4eff1..63eba0a 100644
--- a/src/views/network/EnableStaticNat.vue
+++ b/src/views/network/EnableStaticNat.vue
@@ -174,10 +174,7 @@ export default {
       }).then(response => {
         this.vmsList = response.listvirtualmachinesresponse.virtualmachine
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -196,10 +193,7 @@ export default {
       }).then(response => {
         this.vmsList = response.listvirtualmachinesresponse.virtualmachine || []
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -223,10 +217,7 @@ export default {
 
         this.selectedNic = this.nicsList[0]
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -241,10 +232,7 @@ export default {
       }).then(response => {
         this.networksList = response.listnetworksresponse.network
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -259,11 +247,7 @@ export default {
       }).then(() => {
         this.parentFetchData()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
         this.handleClose()
diff --git a/src/views/network/FirewallRules.vue b/src/views/network/FirewallRules.vue
index 76b815e..bca4ab4 100644
--- a/src/views/network/FirewallRules.vue
+++ b/src/views/network/FirewallRules.vue
@@ -213,10 +213,7 @@ export default {
         this.firewallRules = response.listfirewallrulesresponse.firewallrule || []
         this.totalCount = response.listfirewallrulesresponse.count || 0
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -235,10 +232,7 @@ export default {
           catchMethod: () => this.fetchData()
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
       })
     },
@@ -265,10 +259,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createfirewallruleresponse.errortext
-        })
+        this.$notifyError(error)
         this.resetAllRules()
         this.fetchData()
       })
@@ -301,10 +292,7 @@ export default {
       }).then(response => {
         this.tags = response.listtagsresponse.tag
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -339,10 +327,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createtagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       }).finally(() => {
         this.addTagLoading = false
@@ -378,10 +363,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
diff --git a/src/views/network/IngressEgressRuleConfigure.vue b/src/views/network/IngressEgressRuleConfigure.vue
index 75432e6..f54eec9 100644
--- a/src/views/network/IngressEgressRuleConfigure.vue
+++ b/src/views/network/IngressEgressRuleConfigure.vue
@@ -267,12 +267,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: this.tabType === 'ingress'
-            ? error.response.data.authorizesecuritygroupingressresponse.errortext
-            : error.response.data.authorizesecuritygroupegressresponse.errortext
-        })
+        this.$notifyError(error)
         this.parentToggleLoading()
       })
     },
@@ -304,11 +299,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: this.tabType === 'ingress' ? error.response.data.revokesecuritygroupingressresponse.errortext
-            : error.response.data.revokesecuritygroupegressresponse.errortext
-        })
+        this.$notifyError(error)
         this.parentToggleLoading()
       })
     },
@@ -320,10 +311,7 @@ export default {
       }).then(response => {
         this.tags = response.listtagsresponse.tag
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     handleDeleteTag (tag) {
@@ -361,10 +349,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.parentToggleLoading()
         this.tagsLoading = false
       })
@@ -412,10 +397,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createtagsresponse.errortext
-          })
+          this.$notifyError(error)
           this.parentToggleLoading()
           this.tagsLoading = false
         })
diff --git a/src/views/network/InternalLBAssignVmForm.vue b/src/views/network/InternalLBAssignVmForm.vue
index d9f7cbb..15725d0 100644
--- a/src/views/network/InternalLBAssignVmForm.vue
+++ b/src/views/network/InternalLBAssignVmForm.vue
@@ -175,10 +175,7 @@ export default {
         this.iLb.vmguestip[index] = this.nics[index][0]
         this.addVmModalNicLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}` || 'Error',
-          description: error.response.data.errorresponse.errortext || 'Error'
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
diff --git a/src/views/network/LoadBalancing.vue b/src/views/network/LoadBalancing.vue
index 3a043f5..7a5a1c2 100644
--- a/src/views/network/LoadBalancing.vue
+++ b/src/views/network/LoadBalancing.vue
@@ -466,10 +466,7 @@ export default {
         }
         this.loading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loading = false
       })
     },
@@ -483,10 +480,7 @@ export default {
         }).then(response => {
           this.$set(rule, 'ruleInstances', response.listloadbalancerruleinstancesresponse.lbrulevmidip)
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
         })
@@ -501,10 +495,7 @@ export default {
         }).then(response => {
           this.stickinessPolicies.push(...response.listlbstickinesspoliciesresponse.stickinesspolicies)
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
         })
@@ -543,10 +534,7 @@ export default {
         this.tags = response.listtagsresponse.tag
         this.tagsModalLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -589,10 +577,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createtagsresponse.errortext
-          })
+          this.$notifyError(error)
           this.closeModal()
         })
       })
@@ -628,10 +613,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -692,10 +674,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createLBStickinessPolicy.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -728,10 +707,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -800,10 +776,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
       })
     },
@@ -847,10 +820,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loading = false
         this.closeModal()
       })
@@ -886,10 +856,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.loading = false
         this.closeModal()
       })
@@ -931,10 +898,7 @@ export default {
         })
         this.addVmModalLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -962,10 +926,7 @@ export default {
         this.newRule.vmguestip[index] = this.nics[index][0]
         this.addVmModalNicLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -1042,10 +1003,7 @@ export default {
         this.addVmModalVisible = false
         this.handleAssignToLBRule(response.createloadbalancerruleresponse.id)
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createloadbalancerruleresponse.errortext
-        })
+        this.$notifyError(error)
         this.loading = false
       })
 
diff --git a/src/views/network/PortForwarding.vue b/src/views/network/PortForwarding.vue
index fa55d4b..75646ce 100644
--- a/src/views/network/PortForwarding.vue
+++ b/src/views/network/PortForwarding.vue
@@ -299,10 +299,7 @@ export default {
         this.portForwardRules = response.listportforwardingrulesresponse.portforwardingrule || []
         this.totalCount = response.listportforwardingrulesresponse.count || 0
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -321,10 +318,7 @@ export default {
           catchMethod: () => this.fetchData()
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
       })
     },
@@ -356,10 +350,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createportforwardingruleresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
         this.fetchData()
       })
@@ -403,10 +394,7 @@ export default {
         this.tags = response.listtagsresponse.tag
         this.tagsModalLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -441,10 +429,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createtagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -479,10 +464,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -500,10 +482,7 @@ export default {
         this.vms = response.listvirtualmachinesresponse.virtualmachine
         this.addVmModalLoading = false
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -523,10 +502,7 @@ export default {
         this.addVmModalNicLoading = false
       }).catch(error => {
         console.log(error)
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
diff --git a/src/views/network/RoutersTab.vue b/src/views/network/RoutersTab.vue
index 831ff70..7f7040e 100644
--- a/src/views/network/RoutersTab.vue
+++ b/src/views/network/RoutersTab.vue
@@ -128,11 +128,7 @@ export default {
       api('listRouters', params).then(json => {
         this.routers = json.listroutersresponse.router || []
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
diff --git a/src/views/network/StaticRoutesTab.vue b/src/views/network/StaticRoutesTab.vue
index 9c79684..71c8e39 100644
--- a/src/views/network/StaticRoutesTab.vue
+++ b/src/views/network/StaticRoutesTab.vue
@@ -115,10 +115,7 @@ export default {
       api('listStaticRoutes', { gatewayid: this.resource.id }).then(json => {
         this.routes = json.liststaticroutesresponse.staticroute
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.componentLoading = false
       })
@@ -156,10 +153,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
         this.fetchData()
         this.componentLoading = false
       })
@@ -193,10 +187,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
         this.fetchData()
         this.componentLoading = false
       })
@@ -209,10 +200,7 @@ export default {
       }).then(response => {
         this.tags = response.listtagsresponse.tag
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     handleDeleteTag (tag) {
@@ -243,10 +231,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deletetagsresponse.errortext
-        })
+        this.$notifyError(error)
         this.tagsLoading = false
       })
     },
@@ -286,10 +271,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.createtagsresponse.errortext
-          })
+          this.$notifyError(error)
           this.tagsLoading = false
         })
       })
diff --git a/src/views/network/VpcTab.vue b/src/views/network/VpcTab.vue
index d0d8dbb..15a6e60 100644
--- a/src/views/network/VpcTab.vue
+++ b/src/views/network/VpcTab.vue
@@ -408,10 +408,7 @@ export default {
         this.privateGateways = json.listprivategatewaysresponse.privategateway
         this.itemCounts.privateGateways = json.listprivategatewaysresponse.count
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -424,10 +421,7 @@ export default {
       }).then(json => {
         this.vpnGateways = json.listvpngatewaysresponse.vpngateway ? json.listvpngatewaysresponse.vpngateway : []
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -443,10 +437,7 @@ export default {
         this.vpnConnections = json.listvpnconnectionsresponse.vpnconnection
         this.itemCounts.vpnConnections = json.listvpnconnectionsresponse.count
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -467,10 +458,7 @@ export default {
           })
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
       })
@@ -485,10 +473,7 @@ export default {
           })
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.modals.gatewayLoading = false
       })
@@ -503,10 +488,7 @@ export default {
           })
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.modals.vpnConnectionLoading = false
       })
@@ -576,10 +558,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.modals.gatewayLoading = false
           this.modals.gateway = false
@@ -626,10 +605,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.fetchVpnConnections()
           this.fetchLoading = false
@@ -671,10 +647,7 @@ export default {
             }
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.fetchLoading = false
           this.fetchAclList()
@@ -707,10 +680,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
         this.handleFetchData()
diff --git a/src/views/network/VpcTiersTab.vue b/src/views/network/VpcTiersTab.vue
index 6d15d18..a94e1f2 100644
--- a/src/views/network/VpcTiersTab.vue
+++ b/src/views/network/VpcTiersTab.vue
@@ -366,11 +366,7 @@ export default {
           })
         })
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
         this.modalLoading = false
@@ -392,11 +388,7 @@ export default {
           })
         })
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description'],
-          duration: 0
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.fetchLoading = false
         this.modalLoading = false
@@ -474,11 +466,7 @@ export default {
           })
           this.fetchData()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description'],
-            duration: 0
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.fetchData()
         })
diff --git a/src/views/network/VpnDetails.vue b/src/views/network/VpnDetails.vue
index f630d18..4701584 100644
--- a/src/views/network/VpnDetails.vue
+++ b/src/views/network/VpnDetails.vue
@@ -94,10 +94,7 @@ export default {
           ? response.listremoteaccessvpnsresponse.remoteaccessvpn[0] : null
       }).catch(error => {
         console.log(error)
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
       })
     },
     handleCreateVpn () {
@@ -137,11 +134,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.createremoteaccessvpnresponse
-            ? error.response.data.createremoteaccessvpnresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
         this.parentFetchData()
         this.parentToggleLoading()
@@ -177,11 +170,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.deleteremoteaccessvpnresponse
-            ? error.response.data.deleteremoteaccessvpnresponse.errortext : error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.fetchData()
         this.parentFetchData()
         this.parentToggleLoading()
diff --git a/src/views/offering/AddComputeOffering.vue b/src/views/offering/AddComputeOffering.vue
index 0db7cd6..71848ba 100644
--- a/src/views/offering/AddComputeOffering.vue
+++ b/src/views/offering/AddComputeOffering.vue
@@ -833,10 +833,7 @@ export default {
         api('createServiceOffering', params).then(json => {
           this.$message.success((this.isSystem ? 'Service offering created: ' : 'Compute offering created: ') + values.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.$emit('refresh-data')
diff --git a/src/views/offering/AddDiskOffering.vue b/src/views/offering/AddDiskOffering.vue
index 9c138e2..ba1d1c6 100644
--- a/src/views/offering/AddDiskOffering.vue
+++ b/src/views/offering/AddDiskOffering.vue
@@ -495,10 +495,7 @@ export default {
         api('createDiskOffering', params).then(json => {
           this.$message.success(this.$t('message.disk.offering.created', { name: values.name }))
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.$emit('refresh-data')
diff --git a/src/views/offering/AddNetworkOffering.vue b/src/views/offering/AddNetworkOffering.vue
index c3bd478..5b7a41d 100644
--- a/src/views/offering/AddNetworkOffering.vue
+++ b/src/views/offering/AddNetworkOffering.vue
@@ -838,10 +838,7 @@ export default {
         api('createNetworkOffering', params).then(json => {
           this.$message.success('Network offering created: ' + values.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.$emit('refresh-data')
diff --git a/src/views/offering/AddVpcOffering.vue b/src/views/offering/AddVpcOffering.vue
index b4fcf08..25867c8 100644
--- a/src/views/offering/AddVpcOffering.vue
+++ b/src/views/offering/AddVpcOffering.vue
@@ -368,10 +368,7 @@ export default {
         api('createVPCOffering', params).then(json => {
           this.$message.success('VPC offering created: ' + values.name)
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.$emit('refresh-data')
diff --git a/src/views/offering/ImportBackupOffering.vue b/src/views/offering/ImportBackupOffering.vue
index 0ed963a..f211e72 100644
--- a/src/views/offering/ImportBackupOffering.vue
+++ b/src/views/offering/ImportBackupOffering.vue
@@ -105,10 +105,7 @@ export default {
         this.zones.opts = json.listzonesresponse.zone || []
         this.$forceUpdate()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(f => {
         this.zones.loading = false
       })
@@ -123,10 +120,7 @@ export default {
         this.externals.opts = json.listbackupproviderofferingsresponse.backupoffering || []
         this.$forceUpdate()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(f => {
         this.externals.loading = false
       })
@@ -170,10 +164,7 @@ export default {
             })
           }
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(f => {
           this.loading = false
         })
diff --git a/src/views/offering/UpdateOfferingAccess.vue b/src/views/offering/UpdateOfferingAccess.vue
index ba4da43..6d80a16 100644
--- a/src/views/offering/UpdateOfferingAccess.vue
+++ b/src/views/offering/UpdateOfferingAccess.vue
@@ -285,10 +285,7 @@ export default {
             description: this.$t('label.action.update.offering.access')
           })
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.closeAction()
diff --git a/src/views/plugins/CloudianPlugin.vue b/src/views/plugins/CloudianPlugin.vue
index 28595cc..da6357f 100644
--- a/src/views/plugins/CloudianPlugin.vue
+++ b/src/views/plugins/CloudianPlugin.vue
@@ -44,16 +44,13 @@ export default {
   },
   methods: {
     doSso () {
+      this.showError = false
       api('cloudianSsoLogin').then(json => {
         const url = json.cloudianssologinresponse.cloudianssologin.url
         const cmcWindow = window.open(url, 'CMCWindow')
         cmcWindow.focus()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Single-Sign-On Failed',
-          description: error.response.headers['x-description'] || 'Request Failed',
-          duration: 0
-        })
+        this.$notifyError(error)
         this.showError = true
       })
     }
diff --git a/src/views/project/AccountsTab.vue b/src/views/project/AccountsTab.vue
index a4a554e..5b80cad 100644
--- a/src/views/project/AccountsTab.vue
+++ b/src/views/project/AccountsTab.vue
@@ -144,10 +144,7 @@ export default {
         this.itemCount = itemCount
         this.dataSource = listProjectAccount
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -178,10 +175,7 @@ export default {
         }
       }).catch(error => {
         // show error
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         setTimeout(loading, 1000)
       })
@@ -217,10 +211,7 @@ export default {
         }
       }).catch(error => {
         // show error
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         setTimeout(loading, 1000)
       })
diff --git a/src/views/project/InvitationTokenTemplate.vue b/src/views/project/InvitationTokenTemplate.vue
index 2b9a209..ededf58 100644
--- a/src/views/project/InvitationTokenTemplate.vue
+++ b/src/views/project/InvitationTokenTemplate.vue
@@ -80,10 +80,7 @@ export default {
           this.checkForAddAsyncJob(json, title, description)
           this.$emit('close-action')
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: error.response.headers['x-description']
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.$emit('refresh-data')
           this.loading = false
diff --git a/src/views/project/InvitationsTemplate.vue b/src/views/project/InvitationsTemplate.vue
index ce86af4..0eb6c29 100644
--- a/src/views/project/InvitationsTemplate.vue
+++ b/src/views/project/InvitationsTemplate.vue
@@ -179,10 +179,7 @@ export default {
         this.dataSource = listProjectInvitations
         this.itemCount = itemCount
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.loading = false
       })
@@ -237,10 +234,7 @@ export default {
         }
       }).catch(error => {
         // show error
-        this.$notification.error({
-          message: 'Request Failed',
-          description: error.response.headers['x-description']
-        })
+        this.$notifyError(error)
       }).finally(() => {
         setTimeout(loading, 1000)
       })
diff --git a/src/views/storage/CreateVolume.vue b/src/views/storage/CreateVolume.vue
index 5313612..62a3503 100644
--- a/src/views/storage/CreateVolume.vue
+++ b/src/views/storage/CreateVolume.vue
@@ -144,10 +144,7 @@ export default {
             catchMessage: 'Error encountered while fetching async job result'
           })
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.loading = false
           this.$emit('refresh-data')
diff --git a/src/views/storage/FormSchedule.vue b/src/views/storage/FormSchedule.vue
index 520c3dc..0f2ae8b 100644
--- a/src/views/storage/FormSchedule.vue
+++ b/src/views/storage/FormSchedule.vue
@@ -370,10 +370,7 @@ export default {
           })
           this.resetForm()
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.actionLoading = false
         })
diff --git a/src/views/storage/MigrateVolume.vue b/src/views/storage/MigrateVolume.vue
index b275256..1bd720f 100644
--- a/src/views/storage/MigrateVolume.vue
+++ b/src/views/storage/MigrateVolume.vue
@@ -91,10 +91,7 @@ export default {
           this.storagePools = response.findstoragepoolsformigrationresponse.storagepool || []
           this.selectedStoragePool = this.storagePools[0].id || ''
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
           this.closeModal()
         })
       } else {
@@ -104,10 +101,7 @@ export default {
           this.storagePools = response.liststoragepoolsresponse.storagepool || []
           this.selectedStoragePool = this.storagePools[0].id || ''
         }).catch(error => {
-          this.$notification.error({
-            message: `Error ${error.response.status}`,
-            description: error.response.data.errorresponse.errortext
-          })
+          this.$notifyError(error)
           this.closeModal()
         })
       }
@@ -119,10 +113,7 @@ export default {
         this.diskOfferings = response.listdiskofferingsresponse.diskoffering
         this.selectedDiskOffering = this.diskOfferings[0].id
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     },
@@ -158,10 +149,7 @@ export default {
           }
         })
       }).catch(error => {
-        this.$notification.error({
-          message: `Error ${error.response.status}`,
-          description: error.response.data.errorresponse.errortext
-        })
+        this.$notifyError(error)
         this.closeModal()
       })
     }
diff --git a/src/views/storage/RestoreAttachBackupVolume.vue b/src/views/storage/RestoreAttachBackupVolume.vue
index 5ea8a50..a158f6f 100644
--- a/src/views/storage/RestoreAttachBackupVolume.vue
+++ b/src/views/storage/RestoreAttachBackupVolume.vue
@@ -101,10 +101,7 @@ export default {
         this.virtualMachineOptions.opts = json.listvirtualmachinesresponse.virtualmachine || []
         this.$forceUpdate()
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.virtualMachineOptions.loading = false
       })
@@ -162,10 +159,7 @@ export default {
             })
           }
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         }).finally(() => {
           this.actionLoading = false
         })
diff --git a/src/views/storage/ScheduledSnapshots.vue b/src/views/storage/ScheduledSnapshots.vue
index d2d1f29..82ce4b0 100644
--- a/src/views/storage/ScheduledSnapshots.vue
+++ b/src/views/storage/ScheduledSnapshots.vue
@@ -170,10 +170,7 @@ export default {
           this.$emit('refresh')
         }
       }).catch(error => {
-        this.$notification.error({
-          message: 'Request Failed',
-          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-        })
+        this.$notifyError(error)
       }).finally(() => {
         this.actionLoading = false
       })
diff --git a/src/views/storage/TakeSnapshot.vue b/src/views/storage/TakeSnapshot.vue
index 1acf3d3..e59d26c 100644
--- a/src/views/storage/TakeSnapshot.vue
+++ b/src/views/storage/TakeSnapshot.vue
@@ -183,10 +183,7 @@ export default {
             })
           }
         }).catch(error => {
-          this.$notification.error({
-            message: 'Request Failed',
-            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
-          })
+          this.$notifyError(error)
         })
       })
     },