Commit 31cea033 authored by Eric Eastwood's avatar Eric Eastwood

Merge branch '36629-35958-add-cluster-application-section' into add-ingress-to-cluster-applications

Conflicts:
	app/assets/javascripts/clusters/clusters_bundle.js
	app/assets/javascripts/clusters/components/application_row.vue
	app/assets/javascripts/clusters/services/clusters_service.js
parents 802e6653 f4fb0340
...@@ -29,6 +29,7 @@ export default class Clusters { ...@@ -29,6 +29,7 @@ export default class Clusters {
statusPath, statusPath,
installHelmPath, installHelmPath,
installIngressPath, installIngressPath,
installRunnerPath,
clusterStatus, clusterStatus,
clusterStatusReason, clusterStatusReason,
helpPath, helpPath,
...@@ -42,6 +43,8 @@ export default class Clusters { ...@@ -42,6 +43,8 @@ export default class Clusters {
endpoint: statusPath, endpoint: statusPath,
installHelmEndpoint: installHelmPath, installHelmEndpoint: installHelmPath,
installIngressEndpoint: installIngressPath, installIngressEndpoint: installIngressPath,
installIngresEndpoint: installIngressPath,
installRunnerEndpoint: installRunnerPath,
}); });
this.toggle = this.toggle.bind(this); this.toggle = this.toggle.bind(this);
...@@ -59,7 +62,7 @@ export default class Clusters { ...@@ -59,7 +62,7 @@ export default class Clusters {
this.initApplications(); this.initApplications();
if (this.store.state.status !== 'created') { if (this.store.state.status !== 'created') {
this.updateContainer(this.store.state.status, this.store.state.statusReason); this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
} }
this.addListeners(); this.addListeners();
...@@ -133,13 +136,13 @@ export default class Clusters { ...@@ -133,13 +136,13 @@ export default class Clusters {
} }
handleSuccess(data) { handleSuccess(data) {
const prevApplicationMap = Object.assign({}, this.store.state.applications);
const prevStatus = this.store.state.status; const prevStatus = this.store.state.status;
const prevApplicationMap = Object.assign({}, this.store.state.applications);
this.store.updateStateFromServer(data.data); this.store.updateStateFromServer(data.data);
this.checkForNewInstalls(prevApplicationMap, this.store.state.applications); this.checkForNewInstalls(prevApplicationMap, this.store.state.applications);
if (prevStatus.length == 0 || prevStatus !== this.store.state.status) { this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason);
this.updateContainer(this.store.state.status, this.store.state.statusReason);
}
} }
toggle() { toggle() {
...@@ -170,22 +173,26 @@ export default class Clusters { ...@@ -170,22 +173,26 @@ export default class Clusters {
} }
} }
updateContainer(status, error) { updateContainer(prevStatus, status, error) {
this.hideAll(); this.hideAll();
switch (status) {
case 'created': // We poll all the time but only want the `created` banner to show when newly created
this.successContainer.classList.remove('hidden'); if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) {
break; switch (status) {
case 'errored': case 'created':
this.errorContainer.classList.remove('hidden'); this.successContainer.classList.remove('hidden');
this.errorReasonContainer.textContent = error; break;
break; case 'errored':
case 'scheduled': this.errorContainer.classList.remove('hidden');
case 'creating': this.errorReasonContainer.textContent = error;
this.creatingContainer.classList.remove('hidden'); break;
break; case 'scheduled':
default: case 'creating':
this.hideAll(); this.creatingContainer.classList.remove('hidden');
break;
default:
this.hideAll();
}
} }
} }
......
...@@ -75,7 +75,11 @@ export default { ...@@ -75,7 +75,11 @@ export default {
}, },
installButtonLabel() { installButtonLabel() {
let label; let label;
if (this.status === APPLICATION_INSTALLABLE || this.status === APPLICATION_ERROR || this.status === APPLICATION_NOT_INSTALLABLE) { if (
this.status === APPLICATION_NOT_INSTALLABLE ||
this.status === APPLICATION_INSTALLABLE ||
this.status === APPLICATION_ERROR
) {
label = s__('ClusterIntegration|Install'); label = s__('ClusterIntegration|Install');
} else if (this.status === APPLICATION_SCHEDULED || this.status === APPLICATION_INSTALLING) { } else if (this.status === APPLICATION_SCHEDULED || this.status === APPLICATION_INSTALLING) {
label = s__('ClusterIntegration|Installing'); label = s__('ClusterIntegration|Installing');
......
...@@ -4,7 +4,7 @@ export const APPLICATION_INSTALLABLE = 'installable'; ...@@ -4,7 +4,7 @@ export const APPLICATION_INSTALLABLE = 'installable';
export const APPLICATION_SCHEDULED = 'scheduled'; export const APPLICATION_SCHEDULED = 'scheduled';
export const APPLICATION_INSTALLING = 'installing'; export const APPLICATION_INSTALLING = 'installing';
export const APPLICATION_INSTALLED = 'installed'; export const APPLICATION_INSTALLED = 'installed';
export const APPLICATION_ERROR = 'error'; export const APPLICATION_ERROR = 'errored';
// These are only used client-side // These are only used client-side
export const REQUEST_LOADING = 'request-loading'; export const REQUEST_LOADING = 'request-loading';
......
...@@ -9,6 +9,7 @@ export default class ClusterService { ...@@ -9,6 +9,7 @@ export default class ClusterService {
this.appInstallEndpointMap = { this.appInstallEndpointMap = {
helm: this.options.installHelmEndpoint, helm: this.options.installHelmEndpoint,
ingress: this.options.installIngressEndpoint, ingress: this.options.installIngressEndpoint,
runner: this.options.installRunnerEndpoint,
}; };
} }
......
...@@ -104,7 +104,21 @@ describe('Clusters', () => { ...@@ -104,7 +104,21 @@ describe('Clusters', () => {
describe('updateContainer', () => { describe('updateContainer', () => {
describe('when creating cluster', () => { describe('when creating cluster', () => {
it('should show the creating container', () => { it('should show the creating container', () => {
cluster.updateContainer('creating'); cluster.updateContainer(null, 'creating');
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeFalsy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
});
it('should continue to show `creating` banner with subsequent updates of the same status', () => {
cluster.updateContainer('creating', 'creating');
expect( expect(
cluster.creatingContainer.classList.contains('hidden'), cluster.creatingContainer.classList.contains('hidden'),
...@@ -120,7 +134,7 @@ describe('Clusters', () => { ...@@ -120,7 +134,7 @@ describe('Clusters', () => {
describe('when cluster is created', () => { describe('when cluster is created', () => {
it('should show the success container', () => { it('should show the success container', () => {
cluster.updateContainer('created'); cluster.updateContainer(null, 'created');
expect( expect(
cluster.creatingContainer.classList.contains('hidden'), cluster.creatingContainer.classList.contains('hidden'),
...@@ -132,11 +146,25 @@ describe('Clusters', () => { ...@@ -132,11 +146,25 @@ describe('Clusters', () => {
cluster.errorContainer.classList.contains('hidden'), cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy(); ).toBeTruthy();
}); });
it('should not show a banner when status is already `created`', () => {
cluster.updateContainer('created', 'created');
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
});
}); });
describe('when cluster has error', () => { describe('when cluster has error', () => {
it('should show the error container', () => { it('should show the error container', () => {
cluster.updateContainer('errored', 'this is an error'); cluster.updateContainer(null, 'errored', 'this is an error');
expect( expect(
cluster.creatingContainer.classList.contains('hidden'), cluster.creatingContainer.classList.contains('hidden'),
...@@ -152,6 +180,20 @@ describe('Clusters', () => { ...@@ -152,6 +180,20 @@ describe('Clusters', () => {
cluster.errorReasonContainer.textContent, cluster.errorReasonContainer.textContent,
).toContain('this is an error'); ).toContain('this is an error');
}); });
it('should show `error` banner when previously `creating`', () => {
cluster.updateContainer('creating', 'errored');
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeFalsy();
});
}); });
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import eventHub from '~/clusters/event_hub'; import eventHub from '~/clusters/event_hub';
import { import {
APPLICATION_NOT_INSTALLABLE,
APPLICATION_SCHEDULED,
APPLICATION_INSTALLABLE, APPLICATION_INSTALLABLE,
APPLICATION_INSTALLING, APPLICATION_INSTALLING,
APPLICATION_INSTALLED, APPLICATION_INSTALLED,
...@@ -60,7 +62,18 @@ describe('Application Row', () => { ...@@ -60,7 +62,18 @@ describe('Application Row', () => {
expect(vm.installButtonLabel).toBeUndefined(); expect(vm.installButtonLabel).toBeUndefined();
}); });
it('has enabled "Install" when `status=installable`', () => { it('has disabled "Install" when APPLICATION_NOT_INSTALLABLE', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_NOT_INSTALLABLE,
});
expect(vm.installButtonLabel).toEqual('Install');
expect(vm.installButtonLoading).toEqual(false);
expect(vm.installButtonDisabled).toEqual(true);
});
it('has enabled "Install" when APPLICATION_INSTALLABLE', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLABLE, status: APPLICATION_INSTALLABLE,
...@@ -71,7 +84,18 @@ describe('Application Row', () => { ...@@ -71,7 +84,18 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(false); expect(vm.installButtonDisabled).toEqual(false);
}); });
it('has loading "Installing" when `status=installing`', () => { it('has loading "Installing" when APPLICATION_SCHEDULED', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_SCHEDULED,
});
expect(vm.installButtonLabel).toEqual('Installing');
expect(vm.installButtonLoading).toEqual(true);
expect(vm.installButtonDisabled).toEqual(true);
});
it('has loading "Installing" when APPLICATION_INSTALLING', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLING, status: APPLICATION_INSTALLING,
...@@ -82,7 +106,7 @@ describe('Application Row', () => { ...@@ -82,7 +106,7 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true); expect(vm.installButtonDisabled).toEqual(true);
}); });
it('has disabled "Installed" when `status=installed`', () => { it('has disabled "Installed" when APPLICATION_INSTALLED', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLED, status: APPLICATION_INSTALLED,
...@@ -93,7 +117,7 @@ describe('Application Row', () => { ...@@ -93,7 +117,7 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true); expect(vm.installButtonDisabled).toEqual(true);
}); });
it('has disabled "Install" when `status=error`', () => { it('has disabled "Install" when APPLICATION_ERROR', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_ERROR, status: APPLICATION_ERROR,
...@@ -104,7 +128,7 @@ describe('Application Row', () => { ...@@ -104,7 +128,7 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true); expect(vm.installButtonDisabled).toEqual(true);
}); });
it('has loading "Install" when `requestStatus=loading`', () => { it('has loading "Install" when REQUEST_LOADING', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLABLE, status: APPLICATION_INSTALLABLE,
...@@ -116,7 +140,7 @@ describe('Application Row', () => { ...@@ -116,7 +140,7 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true); expect(vm.installButtonDisabled).toEqual(true);
}); });
it('has disabled "Install" when `requestStatus=success`', () => { it('has disabled "Install" when REQUEST_SUCCESS', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLABLE, status: APPLICATION_INSTALLABLE,
...@@ -128,7 +152,7 @@ describe('Application Row', () => { ...@@ -128,7 +152,7 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true); expect(vm.installButtonDisabled).toEqual(true);
}); });
it('has enabled "Install" when `requestStatus=error` (so you can try installing again)', () => { it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => {
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
status: APPLICATION_INSTALLABLE, status: APPLICATION_INSTALLABLE,
...@@ -181,7 +205,7 @@ describe('Application Row', () => { ...@@ -181,7 +205,7 @@ describe('Application Row', () => {
expect(generalErrorMessage).toBeNull(); expect(generalErrorMessage).toBeNull();
}); });
it('shows status reason when `status=error`', () => { it('shows status reason when APPLICATION_ERROR', () => {
const statusReason = 'We broke it 0.0'; const statusReason = 'We broke it 0.0';
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
...@@ -195,7 +219,7 @@ describe('Application Row', () => { ...@@ -195,7 +219,7 @@ describe('Application Row', () => {
expect(statusErrorMessage.textContent.trim()).toEqual(statusReason); expect(statusErrorMessage.textContent.trim()).toEqual(statusReason);
}); });
it('shows request reason when `requestStatus=error`', () => { it('shows request reason when REQUEST_FAILURE', () => {
const requestReason = 'We broke thre request 0.0'; const requestReason = 'We broke thre request 0.0';
vm = mountComponent(ApplicationRow, { vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE, ...DEFAULT_APPLICATION_STATE,
......
...@@ -62,18 +62,21 @@ describe('Clusters Store', () => { ...@@ -62,18 +62,21 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.status_reason, statusReason: mockResponseData.status_reason,
applications: { applications: {
helm: { helm: {
title: 'Helm Tiller',
status: mockResponseData.applications[0].status, status: mockResponseData.applications[0].status,
statusReason: mockResponseData.applications[0].status_reason, statusReason: mockResponseData.applications[0].status_reason,
requestStatus: null, requestStatus: null,
requestReason: null, requestReason: null,
}, },
ingress: { ingress: {
title: 'Ingress',
status: mockResponseData.applications[1].status, status: mockResponseData.applications[1].status,
statusReason: mockResponseData.applications[1].status_reason, statusReason: mockResponseData.applications[1].status_reason,
requestStatus: null, requestStatus: null,
requestReason: null, requestReason: null,
}, },
runner: { runner: {
title: 'GitLab Runner',
status: mockResponseData.applications[2].status, status: mockResponseData.applications[2].status,
statusReason: mockResponseData.applications[2].status_reason, statusReason: mockResponseData.applications[2].status_reason,
requestStatus: null, requestStatus: null,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment