summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/environments
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/environments')
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue3
-rw-r--r--app/assets/javascripts/environments/components/deployment.vue25
-rw-r--r--app/assets/javascripts/environments/components/deployment_status_badge.vue60
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue25
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue11
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue27
-rw-r--r--app/assets/javascripts/environments/components/new_environment_folder.vue26
-rw-r--r--app/assets/javascripts/environments/components/new_environment_item.vue265
-rw-r--r--app/assets/javascripts/environments/components/new_environments_app.vue39
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue15
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/action.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/set_environment_to_stop.mutation.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_to_stop.query.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/queries/is_environment_stopping.query.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/queries/is_last_deployment.query.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers.js18
-rw-r--r--app/assets/javascripts/environments/graphql/typedefs.graphql6
17 files changed, 510 insertions, 27 deletions
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index 0e556f093e2..ce919f73858 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -99,8 +99,7 @@ export default {
};
},
isLastDeployment() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return this.environment?.isLastDeployment || this.environment?.lastDeployment?.['last?'];
+ return this.environment?.isLastDeployment || this.environment?.lastDeployment?.isLast;
},
},
methods: {
diff --git a/app/assets/javascripts/environments/components/deployment.vue b/app/assets/javascripts/environments/components/deployment.vue
new file mode 100644
index 00000000000..ef43ca6bc33
--- /dev/null
+++ b/app/assets/javascripts/environments/components/deployment.vue
@@ -0,0 +1,25 @@
+<script>
+import DeploymentStatusBadge from './deployment_status_badge.vue';
+
+export default {
+ components: {
+ DeploymentStatusBadge,
+ },
+ props: {
+ deployment: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ status() {
+ return this.deployment?.status;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <deployment-status-badge v-if="status" :status="status" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/deployment_status_badge.vue b/app/assets/javascripts/environments/components/deployment_status_badge.vue
new file mode 100644
index 00000000000..5a026911766
--- /dev/null
+++ b/app/assets/javascripts/environments/components/deployment_status_badge.vue
@@ -0,0 +1,60 @@
+<script>
+import { GlBadge } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+const STATUS_TEXT = {
+ created: s__('Deployment|Created'),
+ running: s__('Deployment|Running'),
+ success: s__('Deployment|Success'),
+ failed: s__('Deployment|Failed'),
+ canceled: s__('Deployment|Cancelled'),
+ skipped: s__('Deployment|Skipped'),
+ blocked: s__('Deployment|Waiting'),
+};
+
+const STATUS_VARIANT = {
+ success: 'success',
+ running: 'info',
+ failed: 'danger',
+ created: 'neutral',
+ canceled: 'neutral',
+ skipped: 'neutral',
+ blocked: 'neutral',
+};
+
+const STATUS_ICON = {
+ success: 'status_success',
+ running: 'status_running',
+ failed: 'status_failed',
+ created: 'status_created',
+ canceled: 'status_canceled',
+ skipped: 'status_skipped',
+ blocked: 'status_manual',
+};
+
+export default {
+ components: {
+ GlBadge,
+ },
+ props: {
+ status: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ icon() {
+ return STATUS_ICON[this.status];
+ },
+ text() {
+ return STATUS_TEXT[this.status];
+ },
+ variant() {
+ return STATUS_VARIANT[this.status];
+ },
+ },
+};
+</script>
+<template>
+ <gl-badge v-if="status" :icon="icon" :variant="variant">{{ text }}</gl-badge>
+</template>
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index 2d98f00433a..98c95507168 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -1,8 +1,9 @@
<script>
-import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { formatTime } from '~/lib/utils/datetime_utility';
import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
+import actionMutation from '../graphql/mutations/action.mutation.graphql';
export default {
directives: {
@@ -12,7 +13,6 @@ export default {
GlDropdown,
GlDropdownItem,
GlIcon,
- GlLoadingIcon,
},
props: {
actions: {
@@ -20,6 +20,11 @@ export default {
required: false,
default: () => [],
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -49,7 +54,11 @@ export default {
this.isLoading = true;
- eventHub.$emit('postAction', { endpoint: action.playPath });
+ if (this.graphql) {
+ this.$apollo.mutate({ mutation: actionMutation, variables: { action } });
+ } else {
+ eventHub.$emit('postAction', { endpoint: action.playPath });
+ }
},
isActionDisabled(action) {
@@ -70,18 +79,16 @@ export default {
<template>
<gl-dropdown
v-gl-tooltip
+ :text="title"
:title="title"
+ :loading="isLoading"
:aria-label="title"
- :disabled="isLoading"
+ icon="play"
+ text-sr-only
right
data-container="body"
data-testid="environment-actions-button"
>
- <template #button-content>
- <gl-icon name="play" />
- <gl-icon name="chevron-down" />
- <gl-loading-icon v-if="isLoading" size="sm" />
- </template>
<gl-dropdown-item
v-for="(action, i) in actions"
:key="i"
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index be9bfb50de5..cfe35d26b94 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlDropdown, GlTooltipDirective, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlTooltipDirective, GlIcon, GlLink, GlSprintf, GlBadge } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { __, s__, sprintf } from '~/locale';
@@ -30,6 +30,7 @@ export default {
CommitComponent,
ExternalUrlComponent,
GlDropdown,
+ GlBadge,
GlIcon,
GlLink,
GlSprintf,
@@ -621,9 +622,9 @@ export default {
<span v-if="model.size === 1">{{ model.name }}</span>
<span v-else>{{ model.name_without_type }}</span>
</a>
- <span v-if="isProtected" class="badge badge-success">
- {{ s__('Environments|protected') }}
- </span>
+ <gl-badge v-if="isProtected" variant="success">{{
+ s__('Environments|protected')
+ }}</gl-badge>
</span>
<span
v-else
@@ -639,7 +640,7 @@ export default {
<span> {{ model.folderName }} </span>
- <span class="badge badge-pill"> {{ model.size }} </span>
+ <gl-badge>{{ model.size }}</gl-badge>
</span>
</div>
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index 0d4a1e76eb8..17a70fd0c34 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -8,6 +8,8 @@ import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
+import setEnvironmentToStopMutation from '../graphql/mutations/set_environment_to_stop.mutation.graphql';
+import isEnvironmentStoppingQuery from '../graphql/queries/is_environment_stopping.query.graphql';
export default {
components: {
@@ -22,6 +24,19 @@ export default {
type: Object,
required: true,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ apollo: {
+ isEnvironmentStopping: {
+ query: isEnvironmentStoppingQuery,
+ variables() {
+ return { environment: this.environment };
+ },
+ },
},
i18n: {
title: s__('Environments|Stop environment'),
@@ -30,6 +45,7 @@ export default {
data() {
return {
isLoading: false,
+ isEnvironmentStopping: false,
};
},
mounted() {
@@ -41,7 +57,14 @@ export default {
methods: {
onClick() {
this.$root.$emit(BV_HIDE_TOOLTIP, this.$options.stopEnvironmentTooltipId);
- eventHub.$emit('requestStopEnvironment', this.environment);
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: setEnvironmentToStopMutation,
+ variables: { environment: this.environment },
+ });
+ } else {
+ eventHub.$emit('requestStopEnvironment', this.environment);
+ }
},
onStopEnvironment(environment) {
if (this.environment.id === environment.id) {
@@ -56,7 +79,7 @@ export default {
<gl-button
v-gl-tooltip="{ id: $options.stopEnvironmentTooltipId }"
v-gl-modal-directive="'stop-environment-modal'"
- :loading="isLoading"
+ :loading="isLoading || isEnvironmentStopping"
:title="$options.i18n.title"
:aria-label="$options.i18n.title"
icon="stop"
diff --git a/app/assets/javascripts/environments/components/new_environment_folder.vue b/app/assets/javascripts/environments/components/new_environment_folder.vue
index fe3d6f1e8ca..0d3867a4d74 100644
--- a/app/assets/javascripts/environments/components/new_environment_folder.vue
+++ b/app/assets/javascripts/environments/components/new_environment_folder.vue
@@ -2,9 +2,11 @@
import { GlButton, GlCollapse, GlIcon, GlBadge, GlLink } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import folderQuery from '../graphql/queries/folder.query.graphql';
+import EnvironmentItem from './new_environment_item.vue';
export default {
components: {
+ EnvironmentItem,
GlButton,
GlCollapse,
GlIcon,
@@ -51,17 +53,26 @@ export default {
folderPath() {
return this.nestedEnvironment.latest.folderPath;
},
+ environments() {
+ return this.folder?.environments;
+ },
},
methods: {
toggleCollapse() {
this.visible = !this.visible;
},
+ isFirstEnvironment(index) {
+ return index === 0;
+ },
},
};
</script>
<template>
- <div class="gl-border-b-solid gl-border-gray-100 gl-border-1 gl-px-3 gl-pt-3 gl-pb-5">
- <div class="gl-w-full gl-display-flex gl-align-items-center">
+ <div
+ :class="{ 'gl-pb-5': !visible }"
+ class="gl-border-b-solid gl-border-gray-100 gl-border-1 gl-pt-3"
+ >
+ <div class="gl-w-full gl-display-flex gl-align-items-center gl-px-3">
<gl-button
class="gl-mr-4 gl-fill-current-color gl-text-gray-500"
:aria-label="label"
@@ -77,6 +88,15 @@ export default {
<gl-badge size="sm" class="gl-mr-auto">{{ count }}</gl-badge>
<gl-link v-if="visible" :href="folderPath">{{ $options.i18n.link }}</gl-link>
</div>
- <gl-collapse :visible="visible" />
+ <gl-collapse :visible="visible">
+ <environment-item
+ v-for="(environment, index) in environments"
+ :key="environment.name"
+ :environment="environment"
+ :class="{ 'gl-mt-5': isFirstEnvironment(index) }"
+ class="gl-border-gray-100 gl-border-t-solid gl-border-1 gl-pt-3"
+ in-folder
+ />
+ </gl-collapse>
</div>
</template>
diff --git a/app/assets/javascripts/environments/components/new_environment_item.vue b/app/assets/javascripts/environments/components/new_environment_item.vue
new file mode 100644
index 00000000000..d3624103c13
--- /dev/null
+++ b/app/assets/javascripts/environments/components/new_environment_item.vue
@@ -0,0 +1,265 @@
+<script>
+import {
+ GlCollapse,
+ GlDropdown,
+ GlButton,
+ GlLink,
+ GlTooltipDirective as GlTooltip,
+} from '@gitlab/ui';
+import { __ } from '~/locale';
+import { truncate } from '~/lib/utils/text_utility';
+import isLastDeployment from '../graphql/queries/is_last_deployment.query.graphql';
+import ExternalUrl from './environment_external_url.vue';
+import Actions from './environment_actions.vue';
+import StopComponent from './environment_stop.vue';
+import Rollback from './environment_rollback.vue';
+import Pin from './environment_pin.vue';
+import Monitoring from './environment_monitoring.vue';
+import Terminal from './environment_terminal_button.vue';
+import Delete from './environment_delete.vue';
+import Deployment from './deployment.vue';
+
+export default {
+ components: {
+ GlCollapse,
+ GlDropdown,
+ GlButton,
+ GlLink,
+ Actions,
+ Deployment,
+ ExternalUrl,
+ StopComponent,
+ Rollback,
+ Monitoring,
+ Pin,
+ Terminal,
+ Delete,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ environment: {
+ required: true,
+ type: Object,
+ },
+ inFolder: {
+ required: false,
+ default: false,
+ type: Boolean,
+ },
+ },
+ apollo: {
+ isLastDeployment: {
+ query: isLastDeployment,
+ variables() {
+ return { environment: this.environment };
+ },
+ },
+ },
+ i18n: {
+ collapse: __('Collapse'),
+ expand: __('Expand'),
+ },
+ data() {
+ return { visible: false };
+ },
+ computed: {
+ icon() {
+ return this.visible ? 'angle-down' : 'angle-right';
+ },
+ externalUrl() {
+ return this.environment.externalUrl;
+ },
+ name() {
+ return this.inFolder ? this.environment.nameWithoutType : this.environment.name;
+ },
+ label() {
+ return this.visible ? this.$options.i18n.collapse : this.$options.i18n.expand;
+ },
+ lastDeployment() {
+ return this.environment?.lastDeployment;
+ },
+ upcomingDeployment() {
+ return this.environment?.upcomingDeployment;
+ },
+ actions() {
+ if (!this.lastDeployment) {
+ return [];
+ }
+ const { manualActions = [], scheduledActions = [] } = this.lastDeployment;
+ const combinedActions = [...manualActions, ...scheduledActions];
+ return combinedActions.map((action) => ({
+ ...action,
+ }));
+ },
+ canStop() {
+ return this.environment?.canStop;
+ },
+ retryPath() {
+ return this.lastDeployment?.deployable?.retryPath;
+ },
+ hasExtraActions() {
+ return Boolean(
+ this.retryPath ||
+ this.canShowAutoStopDate ||
+ this.metricsPath ||
+ this.terminalPath ||
+ this.canDeleteEnvironment,
+ );
+ },
+ canShowAutoStopDate() {
+ if (!this.environment?.autoStopAt) {
+ return false;
+ }
+
+ const autoStopDate = new Date(this.environment?.autoStopAt);
+ const now = new Date();
+
+ return now < autoStopDate;
+ },
+ autoStopPath() {
+ return this.environment?.cancelAutoStopPath ?? '';
+ },
+ metricsPath() {
+ return this.environment?.metricsPath ?? '';
+ },
+ terminalPath() {
+ return this.environment?.terminalPath ?? '';
+ },
+ canDeleteEnvironment() {
+ return Boolean(this.environment?.canDelete && this.environment?.deletePath);
+ },
+ displayName() {
+ return truncate(this.name, 80);
+ },
+ },
+ methods: {
+ toggleCollapse() {
+ this.visible = !this.visible;
+ },
+ },
+ deploymentClasses: [
+ 'gl-border-gray-100',
+ 'gl-border-t-solid',
+ 'gl-border-1',
+ 'gl-py-5',
+ 'gl-pl-7',
+ 'gl-bg-gray-10',
+ ],
+};
+</script>
+<template>
+ <div>
+ <div
+ class="gl-px-3 gl-pt-3 gl-pb-5 gl-display-flex gl-justify-content-space-between gl-align-items-center"
+ >
+ <div
+ :class="{ 'gl-ml-7': inFolder }"
+ class="gl-min-w-0 gl-mr-4 gl-display-flex gl-align-items-center"
+ >
+ <gl-button
+ class="gl-mr-4 gl-min-w-fit-content"
+ :icon="icon"
+ :aria-label="label"
+ size="small"
+ category="tertiary"
+ @click="toggleCollapse"
+ />
+ <gl-link
+ v-gl-tooltip
+ :href="environment.environmentPath"
+ class="gl-text-blue-500 gl-text-truncate"
+ :class="{ 'gl-font-weight-bold': visible }"
+ :title="name"
+ >
+ {{ displayName }}
+ </gl-link>
+ </div>
+ <div>
+ <div class="btn-group table-action-buttons" role="group">
+ <external-url
+ v-if="externalUrl"
+ :external-url="externalUrl"
+ data-track-action="click_button"
+ data-track-label="environment_url"
+ />
+
+ <actions
+ v-if="actions.length > 0"
+ :actions="actions"
+ data-track-action="click_dropdown"
+ data-track-label="environment_actions"
+ graphql
+ />
+
+ <stop-component
+ v-if="canStop"
+ :environment="environment"
+ class="gl-z-index-2"
+ data-track-action="click_button"
+ data-track-label="environment_stop"
+ graphql
+ />
+
+ <gl-dropdown
+ v-if="hasExtraActions"
+ icon="ellipsis_v"
+ text-sr-only
+ :text="__('More actions')"
+ category="secondary"
+ no-caret
+ right
+ >
+ <rollback
+ v-if="retryPath"
+ :environment="environment"
+ :is-last-deployment="isLastDeployment"
+ :retry-url="retryPath"
+ graphql
+ data-track-action="click_button"
+ data-track-label="environment_rollback"
+ />
+
+ <pin
+ v-if="canShowAutoStopDate"
+ :auto-stop-url="autoStopPath"
+ data-track-action="click_button"
+ data-track-label="environment_pin"
+ />
+
+ <monitoring
+ v-if="metricsPath"
+ :monitoring-url="metricsPath"
+ data-track-action="click_button"
+ data-track-label="environment_monitoring"
+ />
+
+ <terminal
+ v-if="terminalPath"
+ :terminal-path="terminalPath"
+ data-track-action="click_button"
+ data-track-label="environment_terminal"
+ />
+
+ <delete
+ v-if="canDeleteEnvironment"
+ :environment="environment"
+ data-track-action="click_button"
+ data-track-label="environment_delete"
+ graphql
+ />
+ </gl-dropdown>
+ </div>
+ </div>
+ </div>
+ <gl-collapse :visible="visible">
+ <div v-if="lastDeployment" :class="$options.deploymentClasses">
+ <deployment :deployment="lastDeployment" :class="{ 'gl-ml-7': inFolder }" />
+ </div>
+ <div v-if="upcomingDeployment" :class="$options.deploymentClasses">
+ <deployment :deployment="upcomingDeployment" :class="{ 'gl-ml-7': inFolder }" />
+ </div>
+ </gl-collapse>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/new_environments_app.vue b/app/assets/javascripts/environments/components/new_environments_app.vue
index 8d94e7021ca..cb36e226d0e 100644
--- a/app/assets/javascripts/environments/components/new_environments_app.vue
+++ b/app/assets/javascripts/environments/components/new_environments_app.vue
@@ -5,13 +5,24 @@ import { updateHistory, setUrlParams, queryToObject } from '~/lib/utils/url_util
import environmentAppQuery from '../graphql/queries/environment_app.query.graphql';
import pollIntervalQuery from '../graphql/queries/poll_interval.query.graphql';
import pageInfoQuery from '../graphql/queries/page_info.query.graphql';
+import environmentToDeleteQuery from '../graphql/queries/environment_to_delete.query.graphql';
+import environmentToRollbackQuery from '../graphql/queries/environment_to_rollback.query.graphql';
+import environmentToStopQuery from '../graphql/queries/environment_to_stop.query.graphql';
import EnvironmentFolder from './new_environment_folder.vue';
import EnableReviewAppModal from './enable_review_app_modal.vue';
+import StopEnvironmentModal from './stop_environment_modal.vue';
+import EnvironmentItem from './new_environment_item.vue';
+import ConfirmRollbackModal from './confirm_rollback_modal.vue';
+import DeleteEnvironmentModal from './delete_environment_modal.vue';
export default {
components: {
+ DeleteEnvironmentModal,
+ ConfirmRollbackModal,
EnvironmentFolder,
EnableReviewAppModal,
+ EnvironmentItem,
+ StopEnvironmentModal,
GlBadge,
GlPagination,
GlTab,
@@ -36,6 +47,15 @@ export default {
pageInfo: {
query: pageInfoQuery,
},
+ environmentToDelete: {
+ query: environmentToDeleteQuery,
+ },
+ environmentToRollback: {
+ query: environmentToRollbackQuery,
+ },
+ environmentToStop: {
+ query: environmentToStopQuery,
+ },
},
inject: ['newEnvironmentPath', 'canCreateEnvironment'],
i18n: {
@@ -57,6 +77,9 @@ export default {
isReviewAppModalVisible: false,
page: parseInt(page, 10),
scope,
+ environmentToDelete: {},
+ environmentToRollback: {},
+ environmentToStop: {},
};
},
computed: {
@@ -64,7 +87,10 @@ export default {
return this.environmentApp?.reviewApp?.canSetupReviewApp;
},
folders() {
- return this.environmentApp?.environments.filter((e) => e.size > 1) ?? [];
+ return this.environmentApp?.environments?.filter((e) => e.size > 1) ?? [];
+ },
+ environments() {
+ return this.environmentApp?.environments?.filter((e) => e.size === 1) ?? [];
},
availableCount() {
return this.environmentApp?.availableCount;
@@ -119,7 +145,7 @@ export default {
},
setScope(scope) {
this.scope = scope;
- this.resetPolling();
+ this.moveToPage(1);
},
movePage(direction) {
this.moveToPage(this.pageInfo[`${direction}Page`]);
@@ -157,6 +183,9 @@ export default {
:modal-id="$options.modalId"
data-testid="enable-review-app-modal"
/>
+ <delete-environment-modal :environment="environmentToDelete" graphql />
+ <stop-environment-modal :environment="environmentToStop" graphql />
+ <confirm-rollback-modal :environment="environmentToRollback" graphql />
<gl-tabs
:action-secondary="addEnvironment"
:action-primary="openReviewAppModal"
@@ -187,6 +216,12 @@ export default {
class="gl-mb-3"
:nested-environment="folder"
/>
+ <environment-item
+ v-for="environment in environments"
+ :key="environment.name"
+ class="gl-mb-3 gl-border-gray-100 gl-border-1 gl-border-b-solid"
+ :environment="environment.latest"
+ />
<gl-pagination
align="center"
:total-items="totalItems"
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 7a9233048a9..162ad598c8c 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -2,6 +2,7 @@
import { GlSprintf, GlTooltipDirective, GlModal } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
+import stopEnvironmentMutation from '../graphql/mutations/stop_environment.mutation.graphql';
export default {
id: 'stop-environment-modal',
@@ -21,6 +22,11 @@ export default {
type: Object,
required: true,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
@@ -39,7 +45,14 @@ export default {
methods: {
onSubmit() {
- eventHub.$emit('stopEnvironment', this.environment);
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: stopEnvironmentMutation,
+ variables: { environment: this.environment },
+ });
+ } else {
+ eventHub.$emit('stopEnvironment', this.environment);
+ }
},
},
};
diff --git a/app/assets/javascripts/environments/graphql/mutations/action.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/action.mutation.graphql
new file mode 100644
index 00000000000..bc2c9b33367
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/action.mutation.graphql
@@ -0,0 +1,5 @@
+mutation action($action: LocalAction) {
+ action(action: $action) @client {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/set_environment_to_stop.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_stop.mutation.graphql
new file mode 100644
index 00000000000..2891f4c5101
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_stop.mutation.graphql
@@ -0,0 +1,3 @@
+mutation SetEnvironmentToStop($environment: LocalEnvironmentInput) {
+ setEnvironmentToStop(environment: $environment) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_to_stop.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_to_stop.query.graphql
new file mode 100644
index 00000000000..128846145e8
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environment_to_stop.query.graphql
@@ -0,0 +1,3 @@
+query environmentToStop {
+ environmentToStop @client
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/is_environment_stopping.query.graphql b/app/assets/javascripts/environments/graphql/queries/is_environment_stopping.query.graphql
new file mode 100644
index 00000000000..ad05e252e6f
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/is_environment_stopping.query.graphql
@@ -0,0 +1,3 @@
+query isEnvironmentStopping($environment: LocalEnvironment) {
+ isEnvironmentStopping(environment: $environment) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/is_last_deployment.query.graphql b/app/assets/javascripts/environments/graphql/queries/is_last_deployment.query.graphql
new file mode 100644
index 00000000000..5eda2f18567
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/is_last_deployment.query.graphql
@@ -0,0 +1,3 @@
+query isLastDeployment($environment: LocalEnvironment) {
+ isLastDeployment(environment: $environment) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/resolvers.js b/app/assets/javascripts/environments/graphql/resolvers.js
index 9ebbc0ad1f8..812fa0c81f0 100644
--- a/app/assets/javascripts/environments/graphql/resolvers.js
+++ b/app/assets/javascripts/environments/graphql/resolvers.js
@@ -8,6 +8,7 @@ import {
import pollIntervalQuery from './queries/poll_interval.query.graphql';
import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
+import environmentToStopQuery from './queries/environment_to_stop.query.graphql';
import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
import pageInfoQuery from './queries/page_info.query.graphql';
@@ -65,8 +66,7 @@ export const resolvers = (endpoint) => ({
}));
},
isLastDeployment(_, { environment }) {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return environment?.lastDeployment?.['last?'];
+ return environment?.lastDeployment?.isLast;
},
},
Mutation: {
@@ -108,6 +108,20 @@ export const resolvers = (endpoint) => ({
]);
});
},
+ setEnvironmentToStop(_, { environment }, { client }) {
+ client.writeQuery({
+ query: environmentToStopQuery,
+ data: { environmentToStop: environment },
+ });
+ },
+ action(_, { action: { playPath } }) {
+ return axios
+ .post(playPath)
+ .then(() => buildErrors())
+ .catch(() =>
+ buildErrors([s__('Environments|An error occurred while making the request.')]),
+ );
+ },
setEnvironmentToDelete(_, { environment }, { client }) {
client.writeQuery({
query: environmentToDeleteQuery,
diff --git a/app/assets/javascripts/environments/graphql/typedefs.graphql b/app/assets/javascripts/environments/graphql/typedefs.graphql
index 4a3abb0e89f..c02f6b2838a 100644
--- a/app/assets/javascripts/environments/graphql/typedefs.graphql
+++ b/app/assets/javascripts/environments/graphql/typedefs.graphql
@@ -68,7 +68,9 @@ extend type Query {
environmentToDelete: LocalEnvironment
pageInfo: LocalPageInfo
environmentToRollback: LocalEnvironment
- isLastDeployment: Boolean
+ environmentToStop: LocalEnvironment
+ isEnvironmentStopping(environment: LocalEnvironmentInput): Boolean
+ isLastDeployment(environment: LocalEnvironmentInput): Boolean
}
extend type Mutation {
@@ -78,4 +80,6 @@ extend type Mutation {
cancelAutoStop(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors
+ setEnvironmentToStop(environment: LocalEnvironmentInput): LocalErrors
+ action(environment: LocalEnvironmentInput): LocalErrors
}