diff options
Diffstat (limited to 'app/assets/javascripts/clusters_list')
5 files changed, 144 insertions, 21 deletions
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue index 7b53020fc49..f8fb58cdca2 100644 --- a/app/assets/javascripts/clusters_list/components/clusters.vue +++ b/app/assets/javascripts/clusters_list/components/clusters.vue @@ -10,6 +10,7 @@ import { GlTable, } from '@gitlab/ui'; import AncestorNotice from './ancestor_notice.vue'; +import NodeErrorHelpText from './node_error_help_text.vue'; import tooltip from '~/vue_shared/directives/tooltip'; import { CLUSTER_TYPES, STATUSES } from '../constants'; import { __, sprintf } from '~/locale'; @@ -26,6 +27,7 @@ export default { GlSkeletonLoading, GlSprintf, GlTable, + NodeErrorHelpText, }, directives: { tooltip, @@ -199,7 +201,13 @@ export default { <section v-else> <ancestor-notice /> - <gl-table :items="clusters" :fields="fields" stacked="md" class="qa-clusters-table"> + <gl-table + :items="clusters" + :fields="fields" + stacked="md" + class="qa-clusters-table" + data-testid="cluster_list_table" + > <template #cell(name)="{ item }"> <div :class="[contentAlignClasses, 'js-status']"> <img @@ -231,9 +239,12 @@ export default { <gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" /> - <small v-else class="gl-font-sm gl-font-style-italic gl-text-gray-200">{{ - __('Unknown') - }}</small> + <NodeErrorHelpText + v-else-if="item.kubernetes_errors" + :class="contentAlignClasses" + :error-type="item.kubernetes_errors.connection_error" + :popover-id="`nodeSizeError${item.id}`" + /> </template> <template #cell(total_cpu)="{ item }"> @@ -250,6 +261,13 @@ export default { </span> <gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" /> + + <NodeErrorHelpText + v-else-if="item.kubernetes_errors" + :class="contentAlignClasses" + :error-type="item.kubernetes_errors.node_connection_error" + :popover-id="`nodeCpuError${item.id}`" + /> </template> <template #cell(total_memory)="{ item }"> @@ -266,6 +284,13 @@ export default { </span> <gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" /> + + <NodeErrorHelpText + v-else-if="item.kubernetes_errors" + :class="contentAlignClasses" + :error-type="item.kubernetes_errors.metrics_connection_error" + :popover-id="`nodeMemoryError${item.id}`" + /> </template> <template #cell(cluster_type)="{value}"> diff --git a/app/assets/javascripts/clusters_list/components/node_error_help_text.vue b/app/assets/javascripts/clusters_list/components/node_error_help_text.vue new file mode 100644 index 00000000000..1a396694bc8 --- /dev/null +++ b/app/assets/javascripts/clusters_list/components/node_error_help_text.vue @@ -0,0 +1,53 @@ +<script> +import { GlIcon, GlPopover } from '@gitlab/ui'; +import { CLUSTER_ERRORS } from '../constants'; + +export default { + components: { + GlIcon, + GlPopover, + }, + props: { + errorType: { + type: String, + required: false, + default: '', + }, + popoverId: { + type: String, + required: true, + }, + }, + computed: { + errorContent() { + return CLUSTER_ERRORS[this.errorType] || CLUSTER_ERRORS.default; + }, + }, +}; +</script> + +<template> + <div :id="popoverId"> + <span class="gl-font-style-italic"> + {{ errorContent.tableText }} + </span> + + <gl-icon name="status_warning" :size="24" class="gl-p-2" /> + + <gl-popover :container="popoverId" :target="popoverId" placement="top" triggers="hover focus"> + <template #title> + <span class="gl-display-block gl-text-left">{{ errorContent.title }}</span> + </template> + + <p class="gl-text-left">{{ errorContent.description }}</p> + + <p class="gl-text-left">{{ s__('ClusterIntegration|Troubleshooting tips:') }}</p> + + <ul class="gl-text-left"> + <li v-for="tip in errorContent.troubleshootingTips" :key="tip"> + {{ tip }} + </li> + </ul> + </gl-popover> + </div> +</template> diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js index 3e8ef3151a6..f39678b73dc 100644 --- a/app/assets/javascripts/clusters_list/constants.js +++ b/app/assets/javascripts/clusters_list/constants.js @@ -1,4 +1,45 @@ -import { __ } from '~/locale'; +import { __, s__ } from '~/locale'; + +export const CLUSTER_ERRORS = { + default: { + tableText: s__('ClusterIntegration|Unknown Error'), + title: s__('ClusterIntegration|Unknown Error'), + description: s__( + 'ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes.', + ), + troubleshootingTips: [ + s__('ClusterIntegration|Check your cluster status'), + s__('ClusterIntegration|Make sure your API endpoint is correct'), + s__( + 'ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed', + ), + ], + }, + authentication_error: { + tableText: s__('ClusterIntegration|Unable to Authenticate'), + title: s__('ClusterIntegration|Authentication Error'), + description: s__('ClusterIntegration|GitLab failed to authenticate.'), + troubleshootingTips: [ + s__('ClusterIntegration|Check your token'), + s__('ClusterIntegration|Check your CA certificate'), + ], + }, + connection_error: { + tableText: s__('ClusterIntegration|Unable to Connect'), + title: s__('ClusterIntegration|Connection Error'), + description: s__('ClusterIntegration|GitLab failed to connect to the cluster.'), + troubleshootingTips: [ + s__('ClusterIntegration|Check your cluster status'), + s__('ClusterIntegration|Make sure your API endpoint is correct'), + ], + }, + http_error: { + tableText: s__('ClusterIntegration|Unable to Connect'), + title: s__('ClusterIntegration|HTTP Error'), + description: s__('ClusterIntegration|There was an HTTP error when connecting to your cluster.'), + troubleshootingTips: [s__('ClusterIntegration|Check your cluster status')], + }, +}; export const CLUSTER_TYPES = { project_type: __('Project'), diff --git a/app/assets/javascripts/clusters_list/index.js b/app/assets/javascripts/clusters_list/index.js index 51ad8769250..daa82892773 100644 --- a/app/assets/javascripts/clusters_list/index.js +++ b/app/assets/javascripts/clusters_list/index.js @@ -1,20 +1,6 @@ import Vue from 'vue'; -import Clusters from './components/clusters.vue'; -import { createStore } from './store'; +import loadClusters from './load_clusters'; export default () => { - const entryPoint = document.querySelector('#js-clusters-list-app'); - - if (!entryPoint) { - return; - } - - // eslint-disable-next-line no-new - new Vue({ - el: '#js-clusters-list-app', - store: createStore(entryPoint.dataset), - render(createElement) { - return createElement(Clusters); - }, - }); + loadClusters(Vue); }; diff --git a/app/assets/javascripts/clusters_list/load_clusters.js b/app/assets/javascripts/clusters_list/load_clusters.js new file mode 100644 index 00000000000..98bc5880898 --- /dev/null +++ b/app/assets/javascripts/clusters_list/load_clusters.js @@ -0,0 +1,18 @@ +import Clusters from './components/clusters.vue'; +import { createStore } from './store'; + +export default Vue => { + const el = document.querySelector('#js-clusters-list-app'); + + if (!el) { + return null; + } + + return new Vue({ + el, + store: createStore(el.dataset), + render(createElement) { + return createElement(Clusters); + }, + }); +}; |