Hide cluster details until cluster is created

Only display the details of the cluster page when the cluster
exists. If it is in "creating" state, show a message and a spinner
This commit is contained in:
Mike Greiling 2019-08-02 20:08:53 +00:00 committed by Fatih Acet
parent 57e00e191d
commit 9fb1df8f97
8 changed files with 126 additions and 59 deletions

View file

@ -48,6 +48,9 @@ export default class Clusters {
} = document.querySelector('.js-edit-cluster-form').dataset;
this.clusterId = clusterId;
this.clusterNewlyCreatedKey = `cluster_${this.clusterId}_newly_created`;
this.clusterBannerDismissedKey = `cluster_${this.clusterId}_banner_dismissed`;
this.store = new ClustersStore();
this.store.setHelpPaths(helpPath, ingressHelpPath, ingressDnsHelpPath);
this.store.setManagePrometheusPath(managePrometheusPath);
@ -81,18 +84,19 @@ export default class Clusters {
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token');
this.ingressDomainHelpText = document.querySelector('.js-ingress-domain-help-text');
this.ingressDomainSnippet = this.ingressDomainHelpText.querySelector(
'.js-ingress-domain-snippet',
);
this.ingressDomainSnippet =
this.ingressDomainHelpText &&
this.ingressDomainHelpText.querySelector('.js-ingress-domain-snippet');
Clusters.initDismissableCallout();
initSettingsPanels();
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
const toggleButtonsContainer = document.querySelector('.js-cluster-enable-toggle-area');
if (toggleButtonsContainer) {
setupToggleButtons(toggleButtonsContainer);
}
this.initApplications(clusterType);
if (this.store.state.status !== 'created') {
this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
}
this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
this.addListeners();
if (statusPath) {
@ -247,35 +251,56 @@ export default class Clusters {
setBannerDismissedState(status, isDismissed) {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
window.localStorage.setItem(
`cluster_${this.clusterId}_banner_dismissed`,
`${status}_${isDismissed}`,
);
window.localStorage.setItem(this.clusterBannerDismissedKey, `${status}_${isDismissed}`);
}
}
isBannerDismissed(status) {
let bannerState;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
bannerState = window.localStorage.getItem(`cluster_${this.clusterId}_banner_dismissed`);
bannerState = window.localStorage.getItem(this.clusterBannerDismissedKey);
}
return bannerState === `${status}_true`;
}
updateContainer(prevStatus, status, error) {
this.hideAll();
setClusterNewlyCreated(state) {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
window.localStorage.setItem(this.clusterNewlyCreatedKey, Boolean(state));
}
}
if (this.isBannerDismissed(status)) {
isClusterNewlyCreated() {
// once this is true, it will always be true for a given page load
if (!this.isNewlyCreated) {
let newlyCreated;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
newlyCreated = window.localStorage.getItem(this.clusterNewlyCreatedKey);
}
this.isNewlyCreated = newlyCreated === 'true';
}
return this.isNewlyCreated;
}
updateContainer(prevStatus, status, error) {
if (status !== 'created' && this.isBannerDismissed(status)) {
return;
}
this.setBannerDismissedState(status, false);
// We poll all the time but only want the `created` banner to show when newly created
if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) {
if (prevStatus !== status) {
this.hideAll();
switch (status) {
case 'created':
this.successContainer.classList.remove('hidden');
if (this.isClusterNewlyCreated()) {
this.setClusterNewlyCreated(false);
this.successContainer.classList.remove('hidden');
} else if (prevStatus) {
this.setClusterNewlyCreated(true);
window.location.reload();
}
break;
case 'errored':
this.errorContainer.classList.remove('hidden');
@ -292,7 +317,6 @@ export default class Clusters {
this.creatingContainer.classList.remove('hidden');
break;
default:
this.hideAll();
}
}
}

View file

@ -28,8 +28,10 @@ const setState = glManagedCheckbox => {
const initGkeNamespace = () => {
const glManagedCheckbox = document.querySelector('.js-gl-managed');
setState(glManagedCheckbox); // this is needed in order to set the initial state
glManagedCheckbox.addEventListener('change', () => setState(glManagedCheckbox));
if (glManagedCheckbox) {
setState(glManagedCheckbox); // this is needed in order to set the initial state
glManagedCheckbox.addEventListener('change', () => setState(glManagedCheckbox));
}
};
export default initGkeNamespace;

View file

@ -3,7 +3,8 @@
%p.js-error-reason
.hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' }
= s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
%span.spinner.spinner-dark.spinner-sm{ 'aria-label': 'Loading' }
%span.prepend-left-4= s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
.hidden.row.js-cluster-api-unreachable.bs-callout.bs-callout-warning{ role: 'alert' }
.col-11
@ -18,4 +19,4 @@
%button.js-close-banner.close.cluster-application-banner-close.h-100.m-0= "×"
.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine.")

View file

@ -33,26 +33,29 @@
%section#cluster-integration
%h4= @cluster.name
= render 'banner'
= render 'form'
= render_if_exists 'projects/clusters/prometheus_graphs'
- unless @cluster.status_name.in? %i/scheduled creating/
= render 'form'
.cluster-applications-table#js-cluster-applications
- unless @cluster.status_name.in? %i/scheduled creating/
= render_if_exists 'projects/clusters/prometheus_graphs'
%section.settings#js-cluster-details{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Kubernetes cluster details')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
= render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
.cluster-applications-table#js-cluster-applications
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Advanced settings')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
.settings-content#advanced-settings-section
= render 'advanced_settings'
%section.settings#js-cluster-details{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('ClusterIntegration|Kubernetes cluster details')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
= render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4= _('Advanced settings')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
.settings-content#advanced-settings-section
= render 'advanced_settings'

View file

@ -0,0 +1,5 @@
---
title: Update cluster page automatically when cluster is created
merge_request: 27189
author:
type: changed

View file

@ -2647,7 +2647,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster name"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."

View file

@ -22,9 +22,8 @@ describe 'Clusters Applications', :js do
let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) }
it 'user is unable to install applications' do
page.within('.js-cluster-application-row-helm') do
expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Install')
end
expect(page).not_to have_css('.js-cluster-application-row-helm')
expect(page).not_to have_css('.js-cluster-application-install-button')
end
end

View file

@ -147,47 +147,80 @@ describe('Clusters', () => {
});
describe('updateContainer', () => {
const { location } = window;
beforeEach(() => {
delete window.location;
window.location = {
reload: jest.fn(),
hash: location.hash,
};
});
afterEach(() => {
window.location = location;
});
describe('when creating cluster', () => {
it('should show the creating container', () => {
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();
expect(window.location.reload).not.toHaveBeenCalled();
});
it('should continue to show `creating` banner with subsequent updates of the same status', () => {
cluster.updateContainer(null, 'creating');
cluster.updateContainer('creating', 'creating');
expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy();
expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
expect(window.location.reload).not.toHaveBeenCalled();
});
});
describe('when cluster is created', () => {
it('should show the success container and fresh the page', () => {
cluster.updateContainer(null, 'created');
it('should hide the "creating" banner and refresh the page', () => {
jest.spyOn(cluster, 'setClusterNewlyCreated');
cluster.updateContainer(null, 'creating');
cluster.updateContainer('creating', 'created');
expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy();
expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
expect(window.location.reload).toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(true);
});
it('should not show a banner when status is already `created`', () => {
it('when the page is refreshed, it should show the "success" banner', () => {
jest.spyOn(cluster, 'setClusterNewlyCreated');
jest.spyOn(cluster, 'isClusterNewlyCreated').mockReturnValue(true);
cluster.updateContainer(null, 'created');
cluster.updateContainer('created', 'created');
expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy();
expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
expect(window.location.reload).not.toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(false);
});
it('should not show a banner when status is already `created`', () => {
jest.spyOn(cluster, 'setClusterNewlyCreated');
jest.spyOn(cluster, 'isClusterNewlyCreated').mockReturnValue(false);
cluster.updateContainer(null, '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();
expect(window.location.reload).not.toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).not.toHaveBeenCalled();
});
});