Commit 27bb0bed authored by Mike Greiling's avatar Mike Greiling

Merge branch 'gitlab-integration-form-toggle' into 'master'

Gitlab integration form toggle

Closes #219612

See merge request gitlab-org/gitlab!35453
parents b6d32b0c 73d4dc46
...@@ -20,7 +20,6 @@ import ClustersService from './services/clusters_service'; ...@@ -20,7 +20,6 @@ import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store'; import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue'; import Applications from './components/applications.vue';
import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue'; import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
import setupToggleButtons from '../toggle_buttons';
import initProjectSelectDropdown from '~/project_select'; import initProjectSelectDropdown from '~/project_select';
import initServerlessSurveyBanner from '~/serverless/survey_banner'; import initServerlessSurveyBanner from '~/serverless/survey_banner';
...@@ -128,10 +127,6 @@ export default class Clusters { ...@@ -128,10 +127,6 @@ export default class Clusters {
Clusters.initDismissableCallout(); Clusters.initDismissableCallout();
initSettingsPanels(); initSettingsPanels();
const toggleButtonsContainer = document.querySelector('.js-cluster-enable-toggle-area');
if (toggleButtonsContainer) {
setupToggleButtons(toggleButtonsContainer);
}
this.initApplications(clusterType); this.initApplications(clusterType);
this.initEnvironments(); this.initEnvironments();
......
...@@ -118,7 +118,7 @@ export default { ...@@ -118,7 +118,7 @@ export default {
</script> </script>
<template> <template>
<div> <div class="gl-display-flex gl-justify-content-end">
<split-button <split-button
v-if="canCleanupResources" v-if="canCleanupResources"
:action-items="$options.splitButtonActionItems" :action-items="$options.splitButtonActionItems"
......
<script>
import { GlFormGroup, GlToggle, GlTooltipDirective } from '@gitlab/ui';
import { mapState } from 'vuex';
export default {
components: {
GlFormGroup,
GlToggle,
},
directives: {
GlTooltip: GlTooltipDirective,
},
data() {
return {
toggleEnabled: true,
};
},
computed: {
...mapState(['enabled', 'editable']),
},
mounted() {
this.toggleEnabled = this.enabled;
},
};
</script>
<template>
<div class="d-flex align-items-center">
<gl-form-group>
<div class="gl-display-flex gl-align-items-center">
<h4 class="gl-pr-3 gl-m-0 ">{{ s__('ClusterIntegration|GitLab Integration') }}</h4>
<input
id="cluster_enabled"
class="js-project-feature-toggle-input"
type="hidden"
:value="toggleEnabled"
name="cluster[enabled]"
/>
<div id="tooltipcontainer" class="js-cluster-enable-toggle-area">
<gl-toggle
v-model="toggleEnabled"
v-gl-tooltip:tooltipcontainer
class="gl-mb-0 js-project-feature-toggle"
data-qa-selector="integration_status_toggle"
:aria-describedby="__('Toggle Kubernetes cluster')"
:disabled="!editable"
:is_checked="toggleEnabled"
:title="
s__(
'ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.',
)
"
/>
</div>
</div>
</gl-form-group>
</div>
</template>
import Vue from 'vue';
import IntegrationForm from '../components/integration_form.vue';
import { createStore } from '../stores';
export default () => {
const entryPoint = document.querySelector('#js-cluster-integration-form');
if (!entryPoint) {
return;
}
// eslint-disable-next-line no-new
new Vue({
el: entryPoint,
store: createStore(entryPoint.dataset),
render(createElement) {
return createElement(IntegrationForm);
},
});
};
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
Vue.use(Vuex);
export const createStore = initialState =>
new Vuex.Store({
state: state(initialState),
});
export default createStore;
import { parseBoolean } from '../../../lib/utils/common_utils';
export default (initialState = {}) => {
return {
enabled: parseBoolean(initialState.enabled),
editable: parseBoolean(initialState.editable),
};
};
import ClustersBundle from '~/clusters/clusters_bundle'; import ClustersBundle from '~/clusters/clusters_bundle';
import initClusterHealth from '~/pages/projects/clusters/show/cluster_health'; import initClusterHealth from '~/pages/projects/clusters/show/cluster_health';
import initIntegrationForm from '~/clusters/forms/show';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new new ClustersBundle(); // eslint-disable-line no-new
initClusterHealth(); initClusterHealth();
initIntegrationForm();
}); });
import initCreateCluster from '~/create_cluster/init_create_cluster'; import initCreateCluster from '~/create_cluster/init_create_cluster';
import initIntegrationForm from '~/clusters/forms/show/index';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initCreateCluster(document, gon); initCreateCluster(document, gon);
initIntegrationForm();
}); });
import ClustersBundle from '~/clusters/clusters_bundle'; import ClustersBundle from '~/clusters/clusters_bundle';
import initGkeNamespace from '~/create_cluster/gke_cluster_namespace'; import initGkeNamespace from '~/create_cluster/gke_cluster_namespace';
import initClusterHealth from './cluster_health'; import initClusterHealth from './cluster_health';
import initIntegrationForm from '~/clusters/forms/show';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new new ClustersBundle(); // eslint-disable-line no-new
initGkeNamespace(); initGkeNamespace();
initClusterHealth(); initClusterHealth();
initIntegrationForm();
}); });
# frozen_string_literal: true # frozen_string_literal: true
module ClustersHelper module ClustersHelper
def has_multiple_clusters?
true
end
def create_new_cluster_label(provider: nil) def create_new_cluster_label(provider: nil)
case provider case provider
when 'aws' when 'aws'
...@@ -24,6 +28,13 @@ module ClustersHelper ...@@ -24,6 +28,13 @@ module ClustersHelper
} }
end end
def js_cluster_form_data(cluster, can_edit)
{
enabled: cluster.enabled?.to_s,
editable: can_edit.to_s
}
end
# This method is depreciated and will be removed when associated HAML files are moved to JavaScript # This method is depreciated and will be removed when associated HAML files are moved to JavaScript
def provider_icon(provider = nil) def provider_icon(provider = nil)
img_data = js_clusters_list_data.dig(:img_tags, provider&.to_sym) || img_data = js_clusters_list_data.dig(:img_tags, provider&.to_sym) ||
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
.text-muted .text-muted
= s_('ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes <code>cluster-admin</code> privileges.').html_safe = s_('ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes <code>cluster-admin</code> privileges.').html_safe
= link_to _('More information'), help_page_path('user/clusters/management_project.md'), target: '_blank' = link_to _('More information'), help_page_path('user/clusters/management_project.md'), target: '_blank'
= field.submit _('Save changes'), class: 'btn btn-success' .gl-display-flex.gl-justify-content-end
= field.submit _('Save changes'), class: 'btn btn-success'
- if @cluster.managed? - if @cluster.managed?
.sub-section.form-group .sub-section.form-group
...@@ -32,7 +33,8 @@ ...@@ -32,7 +33,8 @@
= s_('ClusterIntegration|Clear cluster cache') = s_('ClusterIntegration|Clear cluster cache')
%p %p
= s_("ClusterIntegration|Clear the local cache of namespace and service accounts. This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts.") = s_("ClusterIntegration|Clear the local cache of namespace and service accounts. This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts.")
= link_to(s_('ClusterIntegration|Clear cluster cache'), clusterable.clear_cluster_cache_path(@cluster), method: :delete, class: 'btn btn-primary') .gl-display-flex.gl-justify-content-end
= link_to(s_('ClusterIntegration|Clear cluster cache'), clusterable.clear_cluster_cache_path(@cluster), method: :delete, class: 'btn btn-primary')
.sub-section.form-group .sub-section.form-group
%h4.text-danger %h4.text-danger
......
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-integration-form' } do |field| = form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-integration-form' } do |field|
= form_errors(@cluster) = form_errors(@cluster)
.form-group #js-cluster-integration-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }
.d-flex.align-items-center
%h4.pr-2.m-0
= s_('ClusterIntegration|GitLab Integration')
%label.gl-mb-0.js-cluster-enable-toggle-area{ title: s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.'), data: { toggle: 'tooltip', container: 'body' } }
= render "shared/buttons/project_feature_toggle", is_checked: @cluster.enabled?, label: s_("ClusterIntegration|Toggle Kubernetes cluster"), disabled: !can?(current_user, :update_cluster, @cluster), data: { qa_selector: 'integration_status_toggle' } do
= field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
.form-group .form-group
%h5= s_('ClusterIntegration|Environment scope') %h5= s_('ClusterIntegration|Environment scope')
= field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope') = field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope')
...@@ -32,5 +25,5 @@ ...@@ -32,5 +25,5 @@
= s_('ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}.').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: '</a>'.html_safe } = s_('ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}.').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: '</a>'.html_safe }
- if can?(current_user, :update_cluster, @cluster) - if can?(current_user, :update_cluster, @cluster)
.form-group .form-group.gl-display-flex.gl-justify-content-end
= field.submit _('Save changes'), class: 'btn btn-success', data: { qa_selector: 'save_changes_button' } = field.submit _('Save changes'), class: 'btn btn-success', data: { qa_selector: 'save_changes_button'}
...@@ -48,5 +48,5 @@ ...@@ -48,5 +48,5 @@
- if cluster.allow_user_defined_namespace? - if cluster.allow_user_defined_namespace?
= render('clusters/clusters/namespace', platform_field: platform_field) = render('clusters/clusters/namespace', platform_field: platform_field)
.form-group .form-group.gl-display-flex.gl-justify-content-end
= field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success' = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
---
title: Rewrite integration form in Vue
merge_request: 35453
author:
type: changed
...@@ -5790,9 +5790,6 @@ msgstr "" ...@@ -5790,9 +5790,6 @@ msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:" msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr "" msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Uninstall %{appTitle}" msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "" msgstr ""
...@@ -24948,6 +24945,9 @@ msgstr "" ...@@ -24948,6 +24945,9 @@ msgstr ""
msgid "Today" msgid "Today"
msgstr "" msgstr ""
msgid "Toggle Kubernetes cluster"
msgstr ""
msgid "Toggle Markdown preview" msgid "Toggle Markdown preview"
msgstr "" msgstr ""
......
...@@ -10,8 +10,11 @@ module QA ...@@ -10,8 +10,11 @@ module QA
element :ingress_ip_address, 'id="ingress-endpoint"' # rubocop:disable QA/ElementWithPattern element :ingress_ip_address, 'id="ingress-endpoint"' # rubocop:disable QA/ElementWithPattern
end end
view 'app/views/clusters/clusters/_gitlab_integration_form.html.haml' do view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do
element :integration_status_toggle, required: true element :integration_status_toggle, required: true
end
view 'app/views/clusters/clusters/_gitlab_integration_form.html.haml' do
element :base_domain_field, required: true element :base_domain_field, required: true
element :save_changes_button, required: true element :save_changes_button, required: true
end end
......
...@@ -73,6 +73,7 @@ RSpec.describe 'User Cluster', :js do ...@@ -73,6 +73,7 @@ RSpec.describe 'User Cluster', :js do
end end
it 'user sees a cluster details page' do it 'user sees a cluster details page' do
expect(page).to have_content('GitLab Integration')
expect(page).to have_button('Save changes') expect(page).to have_button('Save changes')
end end
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { loadHTMLFixture } from 'helpers/fixtures'; import { loadHTMLFixture } from 'helpers/fixtures';
import { setTestTimeout } from 'helpers/timeout'; import { setTestTimeout } from 'helpers/timeout';
import Clusters from '~/clusters/clusters_bundle'; import Clusters from '~/clusters/clusters_bundle';
...@@ -63,25 +62,6 @@ describe('Clusters', () => { ...@@ -63,25 +62,6 @@ describe('Clusters', () => {
}); });
}); });
describe('toggle', () => {
it('should update the button and the input field on click', done => {
const toggleButton = document.querySelector(
'.js-cluster-enable-toggle-area .js-project-feature-toggle',
);
const toggleInput = document.querySelector(
'.js-cluster-enable-toggle-area .js-project-feature-toggle-input',
);
$(toggleInput).one('trigger-change', () => {
expect(toggleButton.classList).not.toContain('is-checked');
expect(toggleInput.getAttribute('value')).toEqual('false');
done();
});
toggleButton.click();
});
});
describe('checkForNewInstalls', () => { describe('checkForNewInstalls', () => {
const INITIAL_APP_MAP = { const INITIAL_APP_MAP = {
helm: { status: null, title: 'Helm Tiller' }, helm: { status: null, title: 'Helm Tiller' },
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = ` exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = `
<div> <div
class="gl-display-flex gl-justify-content-end"
>
<div <div
class="dropdown b-dropdown gl-dropdown btn-group" class="dropdown b-dropdown gl-dropdown btn-group"
> >
......
import IntegrationForm from '~/clusters/forms/components/integration_form.vue';
import { createStore } from '~/clusters/forms/stores/index';
import { mount } from '@vue/test-utils';
import { GlToggle } from '@gitlab/ui';
describe('ClusterIntegrationForm', () => {
let wrapper;
let store;
const glToggle = () => wrapper.find(GlToggle);
const toggleButton = () => glToggle().find('button');
const toggleInput = () => wrapper.find('input');
const createWrapper = () => {
store = createStore({
enabled: 'true',
editable: 'true',
});
wrapper = mount(IntegrationForm, { store });
return wrapper.vm.$nextTick();
};
beforeEach(() => {
return createWrapper();
});
afterEach(() => {
wrapper.destroy();
});
it('creates the toggle and label', () => {
expect(wrapper.text()).toContain('GitLab Integration');
expect(wrapper.contains(GlToggle)).toBe(true);
});
it('initializes toggle with store value', () => {
expect(toggleButton().classes()).toContain('is-checked');
expect(toggleInput().attributes('value')).toBe('true');
});
it('switches the toggle value on click', () => {
toggleButton().trigger('click');
wrapper.vm.$nextTick(() => {
expect(toggleButton().classes()).not.toContain('is-checked');
expect(toggleInput().attributes('value')).toBe('false');
});
});
});
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