From fd6776214abb2603ce2fb5dfb078229f0a0195e5 Mon Sep 17 00:00:00 2001
From: Filipa Lacerda <filipa@gitlab.com>
Date: Mon, 2 Oct 2017 20:49:04 +0100
Subject: [PATCH] Adds toggle button Adds polling function

---
 app/assets/javascripts/clusters.js         | 136 +++++++++++++++++++++
 app/assets/javascripts/dispatcher.js       |   5 +
 app/views/projects/clusters/edit.html.haml |  45 ++++---
 3 files changed, 168 insertions(+), 18 deletions(-)

diff --git a/app/assets/javascripts/clusters.js b/app/assets/javascripts/clusters.js
index e69de29bb2d..63ff676486b 100644
--- a/app/assets/javascripts/clusters.js
+++ b/app/assets/javascripts/clusters.js
@@ -0,0 +1,136 @@
+/* globals Flash */
+import Visibility from 'visibilityjs';
+import axios from 'axios';
+import Poll from './lib/utils/poll';
+import { s__ } from './locale';
+import './flash';
+
+class ClusterService {
+  constructor(options = {}) {
+    this.options = options;
+  }
+
+  fetchData() {
+    return axios.get(this.options.endpoints.checkStatus);
+  }
+
+  updateData(value) {
+    return axios.put(this.options.endpoints.editPath,
+      {
+        cluster: {
+          enabled: value,
+        },
+      },
+    );
+  }
+}
+/**
+ * Handles visibily toggle
+ * Polls the state
+ */
+export default class ClusterEdit {
+  constructor() {
+    const dataset = document.querySelector('.js-edit-cluster-form').dataset;
+
+    this.state = {
+      endpoints: {
+        checkStatus: dataset.checkStatus,
+        editPath: dataset.editPath,
+      },
+      canUpdate: dataset.canUpdate,
+      clusterStatus: dataset.clusterStatus,
+    };
+
+    this.service = new ClusterService({ endpoints: this.state.endpoints });
+    this.toggleButton = document.querySelector('.js-toggle-cluster');
+    this.errorContainer = document.querySelector('.js-cluster-error');
+    this.successContainer = document.querySelector('.js-cluster-success');
+    this.creatingContainer = document.querySelector('.js-cluster-creating');
+    this.bindEvents();
+  }
+
+  bindEvents() {
+    if (!this.canUpdate) {
+      this.disableToggle();
+    }
+
+    if (this.clusterStatus) {
+      // update to enable or disabled!
+    }
+
+    this.toggleButton.addEventListener('click', this.toggle.bind(this));
+
+    document.querySelector('.js-edit-cluster-button').addEventListener('click', this.updateData.bind(this));
+
+    this.initPoling();
+  }
+
+  toggle() {
+    this.toggleButton.classList.toggle('checked');
+    this.toggleStatus = this.toggleButton.classList.contains('checked').toString();
+  }
+
+  updateData() {
+    this.service.updateData(this.state.toggleStatus);
+  }
+
+  disableToggle(disable = true) {
+    this.toggleButton.classList.toggle('disabled', disable);
+    this.toggleButton.setAttribute('disabled', disable);
+  }
+
+  initPoling() {
+    if (this.state.clusterStatus === 'created') return;
+
+    this.poll = new Poll({
+      resource: this.service,
+      method: 'fetchData',
+      successCallback: (data) => {
+        const { status } = data.data;
+        this.updateContainer(status);
+      },
+      errorCallback: () => {
+        this.updateContainer('error');
+        Flash(s__('ClusterIntegration|Something went wrong on our end.'));
+      },
+    });
+
+    if (!Visibility.hidden()) {
+      this.poll.makeRequest();
+    } else {
+      this.service.fetchData();
+    }
+
+    Visibility.change(() => {
+      if (!Visibility.hidden()) {
+        this.poll.restart();
+      } else {
+        this.poll.stop();
+      }
+    });
+  }
+
+  hideAll() {
+    this.errorContainer.classList.add('hidden');
+    this.successContainer.classList.add('hidden');
+    this.creatingContainer.classList.add('hidden');
+  }
+
+  updateContainer(status) {
+    this.hideAll();
+    switch (status) {
+      case 'created':
+        this.successContainer.classList.remove('hidden');
+        break;
+      case 'error':
+        this.errorContainer.classList.remove('hidden');
+        break;
+      case 'creating':
+        this.creatingContainer.classList.add('hidden');
+        break;
+      default:
+        this.hideAll();
+    }
+  }
+
+}
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 31214818496..7131889a0a0 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -524,6 +524,11 @@ import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils';
         case 'admin:impersonation_tokens:index':
           new gl.DueDateSelectors();
           break;
+        case 'projects:clusters:edit':
+          import(/* webpackChunkName: "clusters" */ './clusters')
+            .then(cluster => new cluster.default()) // eslint-disable-line new-cap
+            .catch(() => {});
+          break;
       }
       switch (path[0]) {
         case 'sessions':
diff --git a/app/views/projects/clusters/edit.html.haml b/app/views/projects/clusters/edit.html.haml
index 16d864423f5..0f6be36e56a 100644
--- a/app/views/projects/clusters/edit.html.haml
+++ b/app/views/projects/clusters/edit.html.haml
@@ -1,4 +1,7 @@
-.row.prepend-top-default.edit-cluster-form.js-edit-cluster-form{ data: { check_status: status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id), edit_path: namespace_project_cluster_path(@project.namespace, @project, @cluster.id)}}
+.row.prepend-top-default.edit-cluster-form.js-edit-cluster-form{ data: { check_status: status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id, format: :json),
+  edit_path: namespace_project_cluster_path(@project.namespace, @project, @cluster.id, format: :json),
+  can_update: 'true',
+  cluster_status: '' }}
   = render 'sidebar'
   .col-lg-8
     %h4.prepend-top-0
@@ -16,21 +19,37 @@
       = s_('ClusterIntegration|Cluster integration is disabled for this project.')
 
     %label.toggle-wrapper
-      %button{ type: 'button', class: 'js-toggle-cluster project-feature-toggle', aria: { label: 'Toggle' }, data: { 'enabled-text': 'Enable', 'disabled-text': 'disabled' } }
+      %button{ type: 'button', class: 'js-toggle-cluster project-feature-toggle', 'aria-label': 'Toggle', data: { 'enabled-text': 'Enabled', 'disabled-text': 'Disabled' } }
 
+    -# if can?(current_user, :update_cluster, @cluster)
     .form-group
+      %button{ type: 'button', class: 'js-edit-cluster-button btn btn-success'}
+        = s_('ClusterIntegration|Save changes')
 
 
-    -# render errors TODO
-      #= form_errors(@cluster)
-
     -# if can?(current_user, :update_cluster, @cluster)
     .form_group
       %label
         = s_('ClusterIntegration|Google container engine')
-      %p
+
         - link_gke = link_to(s_('ClusterIntegration|Manage your cluster on GKE'), '', target: '_blank', rel: 'noopener noreferrer')
-        = s_('ClusterIntegration|This cluster was not set up on Google Container Engine. %{link_gke}').html_safe % { link_gke: link_gke }
+      .hidden.js-cluster-error
+        %p
+          = s_('ClusterIntegration|This cluster was set up on Google Container Engine. %{link_gke}').html_safe % { link_gke: link_gke }
+        .alert.alert-info{ role: 'alert' }
+          = s_('ClusterIntegration|Something went wrong while creating your cluster on Google Container Engine.')
+
+      .hidden.js-cluster-success
+        %p
+          = s_('ClusterIntegration|This cluster was set up on Google Container Engine. %{link_gke}').html_safe % { link_gke: link_gke }
+        .alert.alert-info{ role: 'alert' }
+          = s_('ClusterIntegration|Cluster was successfully created on Google Container Engine.')
+
+      .hidden.js-cluster-creating
+        %p
+          = s_('ClusterIntegration|This cluster was set up on Google Container Engine. %{link_gke}').html_safe % { link_gke: link_gke }
+        .alert.alert-info{ role: 'alert' }
+        = s_('ClusterIntegration|Cluster is being created on Google Container Engine...')
 
     .form_group
       %label
@@ -50,18 +69,8 @@
       = link_to(s_('ClusterIntegration|Remove integration'), namespace_project_cluster_path(@project.namespace, @project, @cluster.id), method: :delete, class: 'btn btn-danger')
 
 
+
 %br
 = link_to "Enable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id), method: :put
 %br
 = link_to "Disable", namespace_project_cluster_path(@project.namespace, @project, @cluster.id, cluster: {enabled: 'false'}), method: :put
-
-%br
--# status GET
--# status: The current status of the operation.
--# status_reason: If an error has occurred, a textual description of the error.
-= link_to 'Check status', status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id), :remote => true
-%br
--# simply rendering error, if it happened
-status_reason
-%p= @cluster.status_reason
--# Even if we got an error during the creation process, we don't delete cluster objects automatically, because we don't have a method to delete the cluster on gke. So users move to edit page from new page **regardless of validation errors**, and they have to delete the record manually. This is for giving users headsup that a new cluster might remain in gke. /cc @ayufan
-- 
2.30.9