summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 09:08:11 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-25 09:08:11 +0000
commit5064bf8c5647d4c4430cbb4d097cf1592416de29 (patch)
treed051bf2abe2cc7061b3a7facb6669a56ccb9cf54 /app/assets/javascripts
parent9c83aadd2604e7e6cb1f84683f951e6b12872618 (diff)
downloadgitlab-ce-5064bf8c5647d4c4430cbb4d097cf1592416de29.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue19
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js11
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue66
-rw-r--r--app/assets/javascripts/environments/components/environment_delete.vue70
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue16
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue3
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue7
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue3
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js86
-rw-r--r--app/assets/javascripts/environments/mount_show.js32
-rw-r--r--app/assets/javascripts/environments/services/environments_service.js5
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js8
-rw-r--r--app/assets/javascripts/pages/projects/environments/show/index.js3
13 files changed, 298 insertions, 31 deletions
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
index 7f0c232eea8..7418ca9edfc 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
@@ -1,7 +1,6 @@
<script>
import { GlPopover, GlSprintf, GlButton, GlIcon } from '@gitlab/ui';
-import Cookies from 'js-cookie';
-import { parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
+import { parseBoolean, scrollToElement, setCookie, getCookie } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { glEmojiTag } from '~/emoji';
import Tracking from '~/tracking';
@@ -51,7 +50,7 @@ export default {
},
data() {
return {
- popoverDismissed: parseBoolean(Cookies.get(this.dismissKey)),
+ popoverDismissed: parseBoolean(getCookie(`${this.trackLabel}_${this.dismissKey}`)),
tracking: {
label: this.trackLabel,
property: this.humanAccess,
@@ -68,17 +67,27 @@ export default {
emoji() {
return popoverStates[this.trackLabel].emoji || '';
},
+ dismissCookieName() {
+ return `${this.trackLabel}_${this.dismissKey}`;
+ },
+ commitCookieName() {
+ return `suggest_gitlab_ci_yml_commit_${this.dismissKey}`;
+ },
},
mounted() {
- if (this.trackLabel === 'suggest_commit_first_project_gitlab_ci_yml' && !this.popoverDismissed)
+ if (
+ this.trackLabel === 'suggest_commit_first_project_gitlab_ci_yml' &&
+ !this.popoverDismissed
+ ) {
scrollToElement(document.querySelector(this.target));
+ }
this.trackOnShow();
},
methods: {
onDismiss() {
this.popoverDismissed = true;
- Cookies.set(this.dismissKey, this.popoverDismissed, { expires: 365 });
+ setCookie(this.dismissCookieName, this.popoverDismissed);
},
trackOnShow() {
if (!this.popoverDismissed) this.track();
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index f4ce98037c8..5a77896f5ef 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -5,6 +5,7 @@ import NewCommitForm from '../new_commit_form';
import EditBlob from './edit_blob';
import BlobFileDropzone from '../blob/blob_file_dropzone';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
+import { setCookie } from '~/lib/utils/common_utils';
export default () => {
const editBlobForm = $('.js-edit-blob-form');
@@ -60,6 +61,16 @@ export default () => {
}
if (suggestEl) {
+ const commitButton = document.querySelector('#commit-changes');
+
initPopover(suggestEl);
+
+ if (commitButton) {
+ const commitCookieName = `suggest_gitlab_ci_yml_commit_${suggestEl.dataset.dismissKey}`;
+
+ commitButton.addEventListener('click', () => {
+ setCookie(commitCookieName, true);
+ });
+ }
}
};
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
new file mode 100644
index 00000000000..f731dc49a5b
--- /dev/null
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import GlModal from '~/vue_shared/components/gl_modal.vue';
+import { s__, sprintf } from '~/locale';
+import eventHub from '../event_hub';
+
+export default {
+ id: 'delete-environment-modal',
+ name: 'DeleteEnvironmentModal',
+
+ components: {
+ GlModal,
+ },
+
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+
+ props: {
+ environment: {
+ type: Object,
+ required: true,
+ },
+ },
+
+ computed: {
+ confirmDeleteMessage() {
+ return sprintf(
+ s__(
+ `Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?`,
+ ),
+ {
+ environmentName: this.environment.name,
+ },
+ false,
+ );
+ },
+ },
+
+ methods: {
+ onSubmit() {
+ eventHub.$emit('deleteEnvironment', this.environment);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :id="$options.id"
+ :footer-primary-button-text="s__('Environments|Delete environment')"
+ footer-primary-button-variant="danger"
+ @submit="onSubmit"
+ >
+ <template slot="header">
+ <h4 class="modal-title d-flex mw-100">
+ {{ __('Delete') }}
+ <span v-gl-tooltip :title="environment.name" class="text-truncate mx-1 flex-fill">
+ {{ environment.name }}?
+ </span>
+ </h4>
+ </template>
+
+ <p>{{ confirmDeleteMessage }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/environments/components/environment_delete.vue b/app/assets/javascripts/environments/components/environment_delete.vue
new file mode 100644
index 00000000000..b53c5fa6583
--- /dev/null
+++ b/app/assets/javascripts/environments/components/environment_delete.vue
@@ -0,0 +1,70 @@
+<script>
+/**
+ * Renders the delete button that allows deleting a stopped environment.
+ * Used in the environments table and the environment detail view.
+ */
+
+import $ from 'jquery';
+import { GlTooltipDirective } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { s__ } from '~/locale';
+import eventHub from '../event_hub';
+import LoadingButton from '../../vue_shared/components/loading_button.vue';
+
+export default {
+ components: {
+ Icon,
+ LoadingButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ environment: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ };
+ },
+ computed: {
+ title() {
+ return s__('Environments|Delete environment');
+ },
+ },
+ mounted() {
+ eventHub.$on('deleteEnvironment', this.onDeleteEnvironment);
+ },
+ beforeDestroy() {
+ eventHub.$off('deleteEnvironment', this.onDeleteEnvironment);
+ },
+ methods: {
+ onClick() {
+ $(this.$el).tooltip('dispose');
+ eventHub.$emit('requestDeleteEnvironment', this.environment);
+ },
+ onDeleteEnvironment(environment) {
+ if (this.environment.id === environment.id) {
+ this.isLoading = true;
+ }
+ },
+ },
+};
+</script>
+<template>
+ <loading-button
+ v-gl-tooltip
+ :loading="isLoading"
+ :title="title"
+ :aria-label="title"
+ container-class="btn btn-danger d-none d-sm-none d-md-block"
+ data-toggle="modal"
+ data-target="#delete-environment-modal"
+ @click="onClick"
+ >
+ <icon name="remove" />
+ </loading-button>
+</template>
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index dc489c804e9..ec5b1092c14 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -15,8 +15,9 @@ import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import MonitoringButtonComponent from './environment_monitoring.vue';
import PinComponent from './environment_pin.vue';
-import RollbackComponent from './environment_rollback.vue';
+import DeleteComponent from './environment_delete.vue';
import StopComponent from './environment_stop.vue';
+import RollbackComponent from './environment_rollback.vue';
import TerminalButtonComponent from './environment_terminal_button.vue';
/**
@@ -33,6 +34,7 @@ export default {
Icon,
MonitoringButtonComponent,
PinComponent,
+ DeleteComponent,
RollbackComponent,
StopComponent,
TerminalButtonComponent,
@@ -113,6 +115,15 @@ export default {
},
/**
+ * Returns whether the environment can be deleted.
+ *
+ * @returns {Boolean}
+ */
+ canDeleteEnvironment() {
+ return Boolean(this.model && this.model.can_delete && this.model.delete_path);
+ },
+
+ /**
* Verifies if the `deployable` key is present in `last_deployment` key.
* Used to verify whether we should or not render the rollback partial.
*
@@ -485,6 +496,7 @@ export default {
this.externalURL ||
this.monitoringUrl ||
this.canStopEnvironment ||
+ this.canDeleteEnvironment ||
this.canRetry
);
},
@@ -680,6 +692,8 @@ export default {
/>
<stop-component v-if="canStopEnvironment" :environment="model" />
+
+ <delete-component v-if="canDeleteEnvironment" :environment="model" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index 07b8d20fde0..cc1d86d06ed 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -9,6 +9,7 @@ import environmentsMixin from '../mixins/environments_mixin';
import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
import EnableReviewAppButton from './enable_review_app_button.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
+import DeleteEnvironmentModal from './delete_environment_modal.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
export default {
@@ -18,6 +19,7 @@ export default {
EnableReviewAppButton,
GlButton,
StopEnvironmentModal,
+ DeleteEnvironmentModal,
},
mixins: [CIPaginationMixin, environmentsMixin, envrionmentsAppMixin],
@@ -95,6 +97,7 @@ export default {
<template>
<div>
<stop-environment-modal :environment="environmentInStopModal" />
+ <delete-environment-modal :environment="environmentInDeleteModal" />
<confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="top-area">
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 3caf723442e..d3e8fb7ff08 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -63,10 +63,9 @@ export default {
<template slot="header">
<h4 class="modal-title d-flex mw-100">
Stopping
- <span v-gl-tooltip :title="environment.name" class="text-truncate ml-1 mr-1 flex-fill">{{
- environment.name
- }}</span>
- ?
+ <span v-gl-tooltip :title="environment.name" class="text-truncate ml-1 mr-1 flex-fill">
+ {{ environment.name }}?
+ </span>
</h4>
</template>
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index d60c2efd618..30b02585692 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -3,10 +3,12 @@ import folderMixin from 'ee_else_ce/environments/mixins/environments_folder_view
import environmentsMixin from '../mixins/environments_mixin';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
import StopEnvironmentModal from '../components/stop_environment_modal.vue';
+import DeleteEnvironmentModal from '../components/delete_environment_modal.vue';
export default {
components: {
StopEnvironmentModal,
+ DeleteEnvironmentModal,
},
mixins: [environmentsMixin, CIPaginationMixin, folderMixin],
@@ -39,6 +41,7 @@ export default {
<template>
<div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" />
+ <delete-environment-modal :environment="environmentInDeleteModal" />
<h4 class="js-folder-name environments-folder-name">
{{ s__('Environments|Environments') }} /
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 1c5884b541c..4fadecdd3e9 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -27,6 +27,10 @@ export default {
data() {
const store = new EnvironmentsStore();
+ const isDetailView = document.body.contains(
+ document.getElementById('environments-detail-view'),
+ );
+
return {
store,
state: store.state,
@@ -36,7 +40,9 @@ export default {
page: getParameterByName('page') || '1',
requestData: {},
environmentInStopModal: {},
+ environmentInDeleteModal: {},
environmentInRollbackModal: {},
+ isDetailView,
};
},
@@ -121,6 +127,10 @@ export default {
this.environmentInStopModal = environment;
},
+ updateDeleteModal(environment) {
+ this.environmentInDeleteModal = environment;
+ },
+
updateRollbackModal(environment) {
this.environmentInRollbackModal = environment;
},
@@ -133,6 +143,30 @@ export default {
this.postAction({ endpoint, errorMessage });
},
+ deleteEnvironment(environment) {
+ const endpoint = environment.delete_path;
+ const mountedToShow = environment.mounted_to_show;
+ const errorMessage = s__(
+ 'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
+ );
+
+ this.service
+ .deleteAction(endpoint)
+ .then(() => {
+ if (!mountedToShow) {
+ // Reload as a first solution to bust the ETag cache
+ window.location.reload();
+ return;
+ }
+ const url = window.location.href.split('/');
+ url.pop();
+ window.location.href = url.join('/');
+ })
+ .catch(() => {
+ Flash(errorMessage);
+ });
+ },
+
rollbackEnvironment(environment) {
const { retryUrl, isLastDeployment } = environment;
const errorMessage = isLastDeployment
@@ -178,36 +212,42 @@ export default {
this.service = new EnvironmentsService(this.endpoint);
this.requestData = { page: this.page, scope: this.scope, nested: true };
- this.poll = new Poll({
- resource: this.service,
- method: 'fetchEnvironments',
- data: this.requestData,
- successCallback: this.successCallback,
- errorCallback: this.errorCallback,
- notificationCallback: isMakingRequest => {
- this.isMakingRequest = isMakingRequest;
- },
- });
-
- if (!Visibility.hidden()) {
- this.isLoading = true;
- this.poll.makeRequest();
- } else {
- this.fetchEnvironments();
- }
+ if (!this.isDetailView) {
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'fetchEnvironments',
+ data: this.requestData,
+ successCallback: this.successCallback,
+ errorCallback: this.errorCallback,
+ notificationCallback: isMakingRequest => {
+ this.isMakingRequest = isMakingRequest;
+ },
+ });
- Visibility.change(() => {
if (!Visibility.hidden()) {
- this.poll.restart();
+ this.isLoading = true;
+ this.poll.makeRequest();
} else {
- this.poll.stop();
+ this.fetchEnvironments();
}
- });
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.poll.restart();
+ } else {
+ this.poll.stop();
+ }
+ });
+ }
eventHub.$on('postAction', this.postAction);
+
eventHub.$on('requestStopEnvironment', this.updateStopModal);
eventHub.$on('stopEnvironment', this.stopEnvironment);
+ eventHub.$on('requestDeleteEnvironment', this.updateDeleteModal);
+ eventHub.$on('deleteEnvironment', this.deleteEnvironment);
+
eventHub.$on('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$on('rollbackEnvironment', this.rollbackEnvironment);
@@ -216,9 +256,13 @@ export default {
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
+
eventHub.$off('requestStopEnvironment', this.updateStopModal);
eventHub.$off('stopEnvironment', this.stopEnvironment);
+ eventHub.$off('requestDeleteEnvironment', this.updateDeleteModal);
+ eventHub.$off('deleteEnvironment', this.deleteEnvironment);
+
eventHub.$off('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$off('rollbackEnvironment', this.rollbackEnvironment);
diff --git a/app/assets/javascripts/environments/mount_show.js b/app/assets/javascripts/environments/mount_show.js
new file mode 100644
index 00000000000..1929ed080a1
--- /dev/null
+++ b/app/assets/javascripts/environments/mount_show.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import DeleteEnvironmentModal from './components/delete_environment_modal.vue';
+import environmentsMixin from './mixins/environments_mixin';
+
+export default () => {
+ const el = document.getElementById('delete-environment-modal');
+ const container = document.getElementById('environments-detail-view');
+
+ return new Vue({
+ el,
+ components: {
+ DeleteEnvironmentModal,
+ },
+ mixins: [environmentsMixin],
+ data() {
+ const environment = JSON.parse(JSON.stringify(container.dataset));
+ environment.delete_path = environment.deletePath;
+ environment.mounted_to_show = true;
+
+ return {
+ environment,
+ };
+ },
+ render(createElement) {
+ return createElement('delete-environment-modal', {
+ props: {
+ environment: this.environment,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/environments/services/environments_service.js b/app/assets/javascripts/environments/services/environments_service.js
index cb4ff6856db..122c8f84a2c 100644
--- a/app/assets/javascripts/environments/services/environments_service.js
+++ b/app/assets/javascripts/environments/services/environments_service.js
@@ -16,6 +16,11 @@ export default class EnvironmentsService {
return axios.post(endpoint, {});
}
+ // eslint-disable-next-line class-methods-use-this
+ deleteAction(endpoint) {
+ return axios.delete(endpoint, {});
+ }
+
getFolderContent(folderUrl) {
return axios.get(`${folderUrl}.json?per_page=${this.folderResults}`);
}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index abecfba5718..9b0ee40a30a 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -9,6 +9,7 @@ import { getLocationHash } from './url_utility';
import { convertToCamelCase, convertToSnakeCase } from './text_utility';
import { isObject } from './type_utility';
import { isFunction } from 'lodash';
+import Cookies from 'js-cookie';
export const getPagePath = (index = 0) => {
const page = $('body').attr('data-page') || '';
@@ -902,3 +903,10 @@ window.gl.utils = {
spriteIcon,
imagePath,
};
+
+// Methods to set and get Cookie
+export const setCookie = (name, value) => Cookies.set(name, value, { expires: 365 });
+
+export const getCookie = name => Cookies.get(name);
+
+export const removeCookie = name => Cookies.remove(name);
diff --git a/app/assets/javascripts/pages/projects/environments/show/index.js b/app/assets/javascripts/pages/projects/environments/show/index.js
new file mode 100644
index 00000000000..10e3e28f024
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/environments/show/index.js
@@ -0,0 +1,3 @@
+import initShowEnvironment from '~/environments/mount_show';
+
+document.addEventListener('DOMContentLoaded', () => initShowEnvironment());