diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-19 12:09:13 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-19 12:09:13 +0000 |
commit | cd3e2c7b9355f8990ab294b34b5e4add4f3985fa (patch) | |
tree | 77264b3e569ec95da8476f604d3d5cf4b03e85dc /app | |
parent | c1fc5da123a1fe670e32740669a9d5e59eff38f5 (diff) | |
download | gitlab-ce-cd3e2c7b9355f8990ab294b34b5e4add4f3985fa.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
9 files changed, 162 insertions, 38 deletions
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js index b0de4dc8628..2427e25a17d 100644 --- a/app/assets/javascripts/blob/template_selector.js +++ b/app/assets/javascripts/blob/template_selector.js @@ -92,10 +92,10 @@ export default class TemplateSelector { } startLoadingSpinner() { - this.$dropdownIcon.addClass('fa-spinner fa-spin').removeClass('fa-chevron-down'); + this.$dropdownIcon.addClass('spinner').removeClass('fa-chevron-down'); } stopLoadingSpinner() { - this.$dropdownIcon.addClass('fa-chevron-down').removeClass('fa-spinner fa-spin'); + this.$dropdownIcon.addClass('fa-chevron-down').removeClass('spinner'); } } diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index b764348eb3c..d35dca7b939 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -255,6 +255,7 @@ export default class Clusters { eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data)); eventHub.$on('uninstallApplication', data => this.uninstallApplication(data)); eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data)); + eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data)); // Add event listener to all the banner close buttons this.addBannerCloseHandler(this.unreachableContainer, 'unreachable'); this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure'); @@ -268,6 +269,7 @@ export default class Clusters { eventHub.$off('setKnativeHostname'); eventHub.$off('setCrossplaneProviderStack'); eventHub.$off('uninstallApplication'); + eventHub.$off('setIngressModSecurityEnabled'); } initPolling(method, successCallback, errorCallback) { @@ -513,6 +515,11 @@ export default class Clusters { this.store.updateAppProperty(appId, 'validationError', null); } + setIngressModSecurityEnabled({ id, modSecurityEnabled }) { + this.store.updateAppProperty(id, 'isEditingModSecurityEnabled', true); + this.store.updateAppProperty(id, 'modsecurity_enabled', modSecurityEnabled); + } + destroy() { this.destroyed = true; diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index fe2ad562ad5..9429e10e6ed 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -21,6 +21,7 @@ import KnativeDomainEditor from './knative_domain_editor.vue'; import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants'; import eventHub from '~/clusters/event_hub'; import CrossplaneProviderStack from './crossplane_provider_stack.vue'; +import IngressModsecuritySettings from './ingress_modsecurity_settings.vue'; export default { components: { @@ -29,6 +30,7 @@ export default { GlLoadingIcon, KnativeDomainEditor, CrossplaneProviderStack, + IngressModsecuritySettings, }, props: { type: { @@ -129,18 +131,6 @@ export default { crossplaneInstalled() { return this.applications.crossplane.status === APPLICATION_STATUS.INSTALLED; }, - ingressModSecurityDescription() { - const escapedUrl = _.escape(this.ingressModSecurityHelpPath); - - return sprintf( - s__('ClusterIntegration|Learn more about %{startLink}ModSecurity%{endLink}'), - { - startLink: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`, - endLink: '</a>', - }, - false, - ); - }, ingressDescription() { return sprintf( _.escape( @@ -241,6 +231,9 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity } return null; }, + ingress() { + return this.applications.ingress; + }, }, created() { this.helmInstallIllustration = helmInstallIllustration; @@ -329,6 +322,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity :uninstall-successful="applications.ingress.uninstallSuccessful" :uninstall-failed="applications.ingress.uninstallFailed" :disabled="!helmInstalled" + :updateable="false" title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/" > <div slot="description"> @@ -340,25 +334,10 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity }} </p> - <template> - <div class="form-group"> - <div class="form-check form-check-inline"> - <input - v-model="applications.ingress.modsecurity_enabled" - :disabled="ingressInstalled" - type="checkbox" - autocomplete="off" - class="form-check-input" - /> - <label class="form-check-label label-bold" for="ingress-enable-modsecurity"> - {{ s__('ClusterIntegration|Enable Web Application Firewall') }} - </label> - </div> - <p class="form-text text-muted"> - <strong v-html="ingressModSecurityDescription"></strong> - </p> - </div> - </template> + <ingress-modsecurity-settings + :ingress="ingress" + :ingress-mod-security-help-path="ingressModSecurityHelpPath" + /> <template v-if="ingressInstalled"> <div class="form-group"> diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue new file mode 100644 index 00000000000..c30015f31de --- /dev/null +++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue @@ -0,0 +1,116 @@ +<script> +import _ from 'lodash'; +import { __ } from '../../locale'; +import LoadingButton from '~/vue_shared/components/loading_button.vue'; +import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants'; +import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; +import eventHub from '~/clusters/event_hub'; + +const { UPDATING, UNINSTALLING } = APPLICATION_STATUS; + +export default { + components: { + LoadingButton, + GlAlert, + GlSprintf, + GlLink, + }, + props: { + ingress: { + type: Object, + required: true, + }, + ingressModSecurityHelpPath: { + type: String, + required: false, + default: '', + }, + }, + computed: { + modSecurityEnabled: { + get() { + return this.ingress.modsecurity_enabled; + }, + set(isEnabled) { + eventHub.$emit('setIngressModSecurityEnabled', { + id: INGRESS, + modSecurityEnabled: isEnabled, + }); + }, + }, + ingressModSecurityDescription() { + return _.escape(this.ingressModSecurityHelpPath); + }, + saving() { + return [UPDATING].includes(this.ingress.status); + }, + saveButtonDisabled() { + return [UNINSTALLING, UPDATING].includes(this.ingress.status); + }, + saveButtonLabel() { + return this.saving ? __('Saving') : __('Save changes'); + }, + ingressInstalled() { + return this.ingress.installed; + }, + }, + methods: { + updateApplication() { + eventHub.$emit('updateApplication', { + id: INGRESS, + params: { modsecurity_enabled: this.ingress.modsecurity_enabled }, + }); + }, + }, +}; +</script> + +<template> + <div> + <gl-alert + v-if="ingress.updateFailed" + class="mb-3" + variant="danger" + :dismissible="false" + @dismiss="alert = null" + > + {{ + s__('ClusterIntegration|Something went wrong while updating the Web Application Firewall.') + }} + </gl-alert> + <div class="form-group"> + <div class="form-check form-check-inline"> + <input + v-model="modSecurityEnabled" + type="checkbox" + autocomplete="off" + class="form-check-input" + /> + <label class="form-check-label label-bold" for="ingress-enable-modsecurity"> + {{ s__('ClusterIntegration|Enable Web Application Firewall') }} + </label> + </div> + <p class="form-text text-muted"> + <strong> + <gl-sprintf + :message="s__('ClusterIntegration|Learn more about %{linkStart}ModSecurity%{linkEnd}')" + > + <template #link="{ content }"> + <gl-link :href="ingressModSecurityDescription" target="_blank" + >{{ content }} + </gl-link> + </template> + </gl-sprintf> + </strong> + </p> + <loading-button + v-if="ingressInstalled" + class="btn-success mt-1" + :loading="saving" + :disabled="saveButtonDisabled" + :label="saveButtonLabel" + @click="updateApplication" + /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 939c396e1b9..ffe71455b2d 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -54,6 +54,8 @@ export default class ClusterStore { modsecurity_enabled: false, externalIp: null, externalHostname: null, + isEditingModSecurityEnabled: false, + updateFailed: false, }, cert_manager: { ...applicationInitialState, @@ -208,8 +210,11 @@ export default class ClusterStore { if (appId === INGRESS) { this.state.applications.ingress.externalIp = serverAppEntry.external_ip; this.state.applications.ingress.externalHostname = serverAppEntry.external_hostname; - this.state.applications.ingress.modsecurity_enabled = - serverAppEntry.modsecurity_enabled || this.state.applications.ingress.modsecurity_enabled; + if (!this.state.applications.ingress.isEditingModSecurityEnabled) { + this.state.applications.ingress.modsecurity_enabled = + serverAppEntry.modsecurity_enabled || + this.state.applications.ingress.modsecurity_enabled; + } } else if (appId === CERT_MANAGER) { this.state.applications.cert_manager.email = this.state.applications.cert_manager.email || serverAppEntry.email; diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue index 2bc93c3f1c1..78ae719ba0d 100644 --- a/app/assets/javascripts/repository/components/preview/index.vue +++ b/app/assets/javascripts/repository/components/preview/index.vue @@ -1,4 +1,6 @@ <script> +import $ from 'jquery'; +import '~/behaviors/markdown/render_gfm'; import { GlLink, GlLoadingIcon } from '@gitlab/ui'; import getReadmeQuery from '../../queries/getReadme.query.graphql'; @@ -30,6 +32,15 @@ export default { loading: 0, }; }, + watch: { + readme(newVal) { + if (newVal) { + this.$nextTick(() => { + $(this.$refs.readme).renderGFM(); + }); + } + }, + }, }; </script> @@ -45,7 +56,7 @@ export default { </div> <div class="blob-viewer"> <gl-loading-icon v-if="loading > 0" size="md" color="dark" class="my-4 mx-auto" /> - <div v-else-if="readme" v-html="readme.html"></div> + <div v-else-if="readme" ref="readme" v-html="readme.html"></div> </div> </article> </template> diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 41f3603506f..005e5efbdaf 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -150,6 +150,12 @@ right: 8px; } + .spinner { + position: absolute; + top: 9px; + right: 8px; + } + .ic-chevron-down { position: absolute; top: $gl-padding-8; diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 958dc27984f..80c7a803392 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -97,7 +97,7 @@ class GroupsController < Groups::ApplicationController end def edit - @badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id)) + @badge_api_endpoint = expose_path(api_v4_groups_badges_path(id: @group.id)) end def projects diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 31b86946ca2..045aa38230c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -50,7 +50,7 @@ class ProjectsController < Projects::ApplicationController # rubocop: enable CodeReuse/ActiveRecord def edit - @badge_api_endpoint = expose_url(api_v4_projects_badges_path(id: @project.id)) + @badge_api_endpoint = expose_path(api_v4_projects_badges_path(id: @project.id)) render_edit end |