From 83badd07f783880079ecfb4f47705fe62760b8da Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 7 Aug 2018 19:05:43 +0000 Subject: Fix UI error whereby prometheus application status is updated --- app/assets/javascripts/clusters/clusters_bundle.js | 6 +-- .../clusters/components/application_row.vue | 45 ++++++++++---------- .../clusters/components/applications.vue | 6 +-- app/assets/javascripts/clusters/constants.js | 15 ++++--- .../unreleased/fix-prometheus-updated-status.yml | 5 +++ spec/javascripts/clusters/clusters_bundle_spec.js | 18 ++++---- .../clusters/components/application_row_spec.js | 49 ++++++++++------------ spec/javascripts/clusters/services/mock_data.js | 27 +++++------- .../clusters/stores/clusters_store_spec.js | 4 +- 9 files changed, 87 insertions(+), 88 deletions(-) create mode 100644 changelogs/unreleased/fix-prometheus-updated-status.yml diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index e565af800d0..0fdf0c7a389 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -6,7 +6,7 @@ import Poll from '../lib/utils/poll'; import initSettingsPanels from '../settings_panels'; import eventHub from './event_hub'; import { - APPLICATION_INSTALLED, + APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE, @@ -177,8 +177,8 @@ export default class Clusters { checkForNewInstalls(prevApplicationMap, newApplicationMap) { const appTitles = Object.keys(newApplicationMap) - .filter(appId => newApplicationMap[appId].status === APPLICATION_INSTALLED && - prevApplicationMap[appId].status !== APPLICATION_INSTALLED && + .filter(appId => newApplicationMap[appId].status === APPLICATION_STATUS.INSTALLED && + prevApplicationMap[appId].status !== APPLICATION_STATUS.INSTALLED && prevApplicationMap[appId].status !== null) .map(appId => newApplicationMap[appId].title); diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index ec52fdfdf32..651f3b50236 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -4,12 +4,7 @@ import eventHub from '../event_hub'; import loadingButton from '../../vue_shared/components/loading_button.vue'; import { - APPLICATION_NOT_INSTALLABLE, - APPLICATION_SCHEDULED, - APPLICATION_INSTALLABLE, - APPLICATION_INSTALLING, - APPLICATION_INSTALLED, - APPLICATION_ERROR, + APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE, @@ -59,49 +54,57 @@ }, }, computed: { + isUnknownStatus() { + return !this.isKnownStatus && this.status !== null; + }, + isKnownStatus() { + return Object.values(APPLICATION_STATUS).includes(this.status); + }, rowJsClass() { return `js-cluster-application-row-${this.id}`; }, installButtonLoading() { return !this.status || - this.status === APPLICATION_SCHEDULED || - this.status === APPLICATION_INSTALLING || + this.status === APPLICATION_STATUS.SCHEDULED || + this.status === APPLICATION_STATUS.INSTALLING || this.requestStatus === REQUEST_LOADING; }, installButtonDisabled() { - // Avoid the potential for the real-time data to say APPLICATION_INSTALLABLE but + // Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but // we already made a request to install and are just waiting for the real-time // to sync up. - return (this.status !== APPLICATION_INSTALLABLE - && this.status !== APPLICATION_ERROR) || + return ((this.status !== APPLICATION_STATUS.INSTALLABLE + && this.status !== APPLICATION_STATUS.ERROR) || this.requestStatus === REQUEST_LOADING || - this.requestStatus === REQUEST_SUCCESS; + this.requestStatus === REQUEST_SUCCESS) && this.isKnownStatus; }, installButtonLabel() { let label; if ( - this.status === APPLICATION_NOT_INSTALLABLE || - this.status === APPLICATION_INSTALLABLE || - this.status === APPLICATION_ERROR + this.status === APPLICATION_STATUS.NOT_INSTALLABLE || + this.status === APPLICATION_STATUS.INSTALLABLE || + this.status === APPLICATION_STATUS.ERROR || + this.isUnknownStatus ) { label = s__('ClusterIntegration|Install'); - } else if (this.status === APPLICATION_SCHEDULED || - this.status === APPLICATION_INSTALLING) { + } else if (this.status === APPLICATION_STATUS.SCHEDULED || + this.status === APPLICATION_STATUS.INSTALLING) { label = s__('ClusterIntegration|Installing'); - } else if (this.status === APPLICATION_INSTALLED) { + } else if (this.status === APPLICATION_STATUS.INSTALLED || + this.status === APPLICATION_STATUS.UPDATED) { label = s__('ClusterIntegration|Installed'); } return label; }, showManageButton() { - return this.manageLink && this.status === APPLICATION_INSTALLED; + return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED; }, manageButtonLabel() { return s__('ClusterIntegration|Manage'); }, hasError() { - return this.status === APPLICATION_ERROR || + return this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE; }, generalErrorDescription() { @@ -182,7 +185,7 @@
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 8ee7279e544..d708a9e595a 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -3,7 +3,7 @@ import _ from 'underscore'; import { s__, sprintf } from '../../locale'; import applicationRow from './application_row.vue'; import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; -import { APPLICATION_INSTALLED, INGRESS } from '../constants'; +import { APPLICATION_STATUS, INGRESS } from '../constants'; export default { components: { @@ -58,7 +58,7 @@ export default { return INGRESS; }, ingressInstalled() { - return this.applications.ingress.status === APPLICATION_INSTALLED; + return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED; }, ingressExternalIp() { return this.applications.ingress.externalIp; @@ -122,7 +122,7 @@ export default { ); }, jupyterInstalled() { - return this.applications.jupyter.status === APPLICATION_INSTALLED; + return this.applications.jupyter.status === APPLICATION_STATUS.INSTALLED; }, jupyterHostname() { return this.applications.jupyter.hostname; diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index 371f71fde44..72fc9355d82 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -1,10 +1,13 @@ // These need to match what is returned from the server -export const APPLICATION_NOT_INSTALLABLE = 'not_installable'; -export const APPLICATION_INSTALLABLE = 'installable'; -export const APPLICATION_SCHEDULED = 'scheduled'; -export const APPLICATION_INSTALLING = 'installing'; -export const APPLICATION_INSTALLED = 'installed'; -export const APPLICATION_ERROR = 'errored'; +export const APPLICATION_STATUS = { + NOT_INSTALLABLE: 'not_installable', + INSTALLABLE: 'installable', + SCHEDULED: 'scheduled', + INSTALLING: 'installing', + INSTALLED: 'installed', + UPDATED: 'updated', + ERROR: 'errored', +}; // These are only used client-side export const REQUEST_LOADING = 'request-loading'; diff --git a/changelogs/unreleased/fix-prometheus-updated-status.yml b/changelogs/unreleased/fix-prometheus-updated-status.yml new file mode 100644 index 00000000000..7261c3429c8 --- /dev/null +++ b/changelogs/unreleased/fix-prometheus-updated-status.yml @@ -0,0 +1,5 @@ +--- +title: Fix UI error whereby prometheus application status is updated +merge_request: 21029 +author: +type: fixed diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js index 839b8a06b48..d0e0b214509 100644 --- a/spec/javascripts/clusters/clusters_bundle_spec.js +++ b/spec/javascripts/clusters/clusters_bundle_spec.js @@ -1,11 +1,9 @@ import Clusters from '~/clusters/clusters_bundle'; import { - APPLICATION_INSTALLABLE, - APPLICATION_INSTALLING, - APPLICATION_INSTALLED, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE, + APPLICATION_STATUS, } from '~/clusters/constants'; import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper'; @@ -84,7 +82,7 @@ describe('Clusters', () => { it('does not show alert when things transition from initial null state to something', () => { cluster.checkForNewInstalls(INITIAL_APP_MAP, { ...INITIAL_APP_MAP, - helm: { status: APPLICATION_INSTALLABLE, title: 'Helm Tiller' }, + helm: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Helm Tiller' }, }); const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text'); @@ -94,10 +92,10 @@ describe('Clusters', () => { it('shows an alert when something gets newly installed', () => { cluster.checkForNewInstalls({ ...INITIAL_APP_MAP, - helm: { status: APPLICATION_INSTALLING, title: 'Helm Tiller' }, + helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' }, }, { ...INITIAL_APP_MAP, - helm: { status: APPLICATION_INSTALLED, title: 'Helm Tiller' }, + helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' }, }); const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text'); @@ -108,12 +106,12 @@ describe('Clusters', () => { it('shows an alert when multiple things gets newly installed', () => { cluster.checkForNewInstalls({ ...INITIAL_APP_MAP, - helm: { status: APPLICATION_INSTALLING, title: 'Helm Tiller' }, - ingress: { status: APPLICATION_INSTALLABLE, title: 'Ingress' }, + helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' }, + ingress: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Ingress' }, }, { ...INITIAL_APP_MAP, - helm: { status: APPLICATION_INSTALLED, title: 'Helm Tiller' }, - ingress: { status: APPLICATION_INSTALLED, title: 'Ingress' }, + helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' }, + ingress: { status: APPLICATION_STATUS.INSTALLED, title: 'Ingress' }, }); const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text'); diff --git a/spec/javascripts/clusters/components/application_row_spec.js b/spec/javascripts/clusters/components/application_row_spec.js index c83cbe90a57..9da5c248371 100644 --- a/spec/javascripts/clusters/components/application_row_spec.js +++ b/spec/javascripts/clusters/components/application_row_spec.js @@ -1,12 +1,7 @@ import Vue from 'vue'; import eventHub from '~/clusters/event_hub'; import { - APPLICATION_NOT_INSTALLABLE, - APPLICATION_SCHEDULED, - APPLICATION_INSTALLABLE, - APPLICATION_INSTALLING, - APPLICATION_INSTALLED, - APPLICATION_ERROR, + APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE, @@ -62,10 +57,10 @@ describe('Application Row', () => { expect(vm.installButtonLabel).toBeUndefined(); }); - it('has disabled "Install" when APPLICATION_NOT_INSTALLABLE', () => { + it('has disabled "Install" when APPLICATION_STATUS.NOT_INSTALLABLE', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_NOT_INSTALLABLE, + status: APPLICATION_STATUS.NOT_INSTALLABLE, }); expect(vm.installButtonLabel).toEqual('Install'); @@ -73,10 +68,10 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has enabled "Install" when APPLICATION_INSTALLABLE', () => { + it('has enabled "Install" when APPLICATION_STATUS.INSTALLABLE', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, }); expect(vm.installButtonLabel).toEqual('Install'); @@ -84,10 +79,10 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(false); }); - it('has loading "Installing" when APPLICATION_SCHEDULED', () => { + it('has loading "Installing" when APPLICATION_STATUS.SCHEDULED', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_SCHEDULED, + status: APPLICATION_STATUS.SCHEDULED, }); expect(vm.installButtonLabel).toEqual('Installing'); @@ -95,10 +90,10 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has loading "Installing" when APPLICATION_INSTALLING', () => { + it('has loading "Installing" when APPLICATION_STATUS.INSTALLING', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLING, + status: APPLICATION_STATUS.INSTALLING, }); expect(vm.installButtonLabel).toEqual('Installing'); @@ -106,10 +101,10 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Installed" when APPLICATION_INSTALLED', () => { + it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLED, + status: APPLICATION_STATUS.INSTALLED, }); expect(vm.installButtonLabel).toEqual('Installed'); @@ -117,10 +112,10 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has enabled "Install" when APPLICATION_ERROR', () => { + it('has enabled "Install" when APPLICATION_STATUS.ERROR', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_ERROR, + status: APPLICATION_STATUS.ERROR, }); expect(vm.installButtonLabel).toEqual('Install'); @@ -131,7 +126,7 @@ describe('Application Row', () => { it('has loading "Install" when REQUEST_LOADING', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, requestStatus: REQUEST_LOADING, }); @@ -143,7 +138,7 @@ describe('Application Row', () => { it('has disabled "Install" when REQUEST_SUCCESS', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, requestStatus: REQUEST_SUCCESS, }); @@ -155,7 +150,7 @@ describe('Application Row', () => { it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, requestStatus: REQUEST_FAILURE, }); @@ -168,7 +163,7 @@ describe('Application Row', () => { spyOn(eventHub, '$emit'); vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, }); const installButton = vm.$el.querySelector('.js-cluster-application-install-button'); @@ -184,7 +179,7 @@ describe('Application Row', () => { spyOn(eventHub, '$emit'); vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, installApplicationRequestParams: { hostname: 'jupyter' }, }); const installButton = vm.$el.querySelector('.js-cluster-application-install-button'); @@ -201,7 +196,7 @@ describe('Application Row', () => { spyOn(eventHub, '$emit'); vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLING, + status: APPLICATION_STATUS.INSTALLING, }); const installButton = vm.$el.querySelector('.js-cluster-application-install-button'); @@ -225,11 +220,11 @@ describe('Application Row', () => { expect(generalErrorMessage).toBeNull(); }); - it('shows status reason when APPLICATION_ERROR', () => { + it('shows status reason when APPLICATION_STATUS.ERROR', () => { const statusReason = 'We broke it 0.0'; vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_ERROR, + status: APPLICATION_STATUS.ERROR, statusReason, }); const generalErrorMessage = vm.$el.querySelector('.js-cluster-application-general-error-message'); @@ -243,7 +238,7 @@ describe('Application Row', () => { const requestReason = 'We broke thre request 0.0'; vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, requestStatus: REQUEST_FAILURE, requestReason, }); diff --git a/spec/javascripts/clusters/services/mock_data.js b/spec/javascripts/clusters/services/mock_data.js index b2b0ebf840b..c7c1412e1c6 100644 --- a/spec/javascripts/clusters/services/mock_data.js +++ b/spec/javascripts/clusters/services/mock_data.js @@ -1,9 +1,4 @@ -import { - APPLICATION_INSTALLED, - APPLICATION_INSTALLABLE, - APPLICATION_INSTALLING, - APPLICATION_ERROR, -} from '~/clusters/constants'; +import { APPLICATION_STATUS } from '~/clusters/constants'; const CLUSTERS_MOCK_DATA = { GET: { @@ -13,25 +8,25 @@ const CLUSTERS_MOCK_DATA = { status_reason: 'Failed to request to CloudPlatform.', applications: [{ name: 'helm', - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, status_reason: null, }, { name: 'ingress', - status: APPLICATION_ERROR, + status: APPLICATION_STATUS.ERROR, status_reason: 'Cannot connect', external_ip: null, }, { name: 'runner', - status: APPLICATION_INSTALLING, + status: APPLICATION_STATUS.INSTALLING, status_reason: null, }, { name: 'prometheus', - status: APPLICATION_ERROR, + status: APPLICATION_STATUS.ERROR, status_reason: 'Cannot connect', }, { name: 'jupyter', - status: APPLICATION_INSTALLING, + status: APPLICATION_STATUS.INSTALLING, status_reason: 'Cannot connect', }], }, @@ -42,25 +37,25 @@ const CLUSTERS_MOCK_DATA = { status_reason: 'Failed to request to CloudPlatform.', applications: [{ name: 'helm', - status: APPLICATION_INSTALLED, + status: APPLICATION_STATUS.INSTALLED, status_reason: null, }, { name: 'ingress', - status: APPLICATION_INSTALLED, + status: APPLICATION_STATUS.INSTALLED, status_reason: 'Cannot connect', external_ip: '1.1.1.1', }, { name: 'runner', - status: APPLICATION_INSTALLING, + status: APPLICATION_STATUS.INSTALLING, status_reason: null, }, { name: 'prometheus', - status: APPLICATION_ERROR, + status: APPLICATION_STATUS.ERROR, status_reason: 'Cannot connect', }, { name: 'jupyter', - status: APPLICATION_INSTALLABLE, + status: APPLICATION_STATUS.INSTALLABLE, status_reason: 'Cannot connect', }], }, diff --git a/spec/javascripts/clusters/stores/clusters_store_spec.js b/spec/javascripts/clusters/stores/clusters_store_spec.js index 9e43552f740..104a064bdd3 100644 --- a/spec/javascripts/clusters/stores/clusters_store_spec.js +++ b/spec/javascripts/clusters/stores/clusters_store_spec.js @@ -1,5 +1,5 @@ import ClustersStore from '~/clusters/stores/clusters_store'; -import { APPLICATION_INSTALLING } from '~/clusters/constants'; +import { APPLICATION_STATUS } from '~/clusters/constants'; import { CLUSTERS_MOCK_DATA } from '../services/mock_data'; describe('Clusters Store', () => { @@ -35,7 +35,7 @@ describe('Clusters Store', () => { it('should store new request status', () => { expect(store.state.applications.helm.requestStatus).toEqual(null); - const newStatus = APPLICATION_INSTALLING; + const newStatus = APPLICATION_STATUS.INSTALLING; store.updateAppProperty('helm', 'requestStatus', newStatus); expect(store.state.applications.helm.requestStatus).toEqual(newStatus); -- cgit v1.2.1