diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-11 03:13:53 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-11 03:13:53 +0300 |
commit | d9c0b200e192c340f50fa165a66e4b6ff805f9fc (patch) | |
tree | 570199824b4576359360bf1fb4bc18e53e87415f /app/assets/javascripts/environments | |
parent | fbb529e46cfd031fae6f6f650d81bef331ef8fcd (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/environments')
9 files changed, 326 insertions, 18 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/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/new_environment_folder.vue b/app/assets/javascripts/environments/components/new_environment_folder.vue index fe3d6f1e8ca..0d8651b1d09 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,16 +53,25 @@ 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-pb-5': !visible }" + class="gl-border-b-solid gl-border-gray-100 gl-border-1 gl-px-3 gl-pt-3" + > <div class="gl-w-full gl-display-flex gl-align-items-center"> <gl-button class="gl-mr-4 gl-fill-current-color gl-text-gray-500" @@ -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-pl-7 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..883e887c1ae --- /dev/null +++ b/app/assets/javascripts/environments/components/new_environment_item.vue @@ -0,0 +1,239 @@ +<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'; + +export default { + components: { + GlCollapse, + GlDropdown, + GlButton, + GlLink, + Actions, + 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; + }, + actions() { + if (!this.environment?.lastDeployment) { + return []; + } + const { manualActions = [], scheduledActions = [] } = this.environment.lastDeployment; + const combinedActions = [...manualActions, ...scheduledActions]; + return combinedActions.map((action) => ({ + ...action, + })); + }, + canStop() { + return this.environment?.canStop; + }, + retryPath() { + return this.environment?.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; + }, + }, +}; +</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-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> +</template> diff --git a/app/assets/javascripts/environments/components/new_environments_app.vue b/app/assets/javascripts/environments/components/new_environments_app.vue index 02ccdb53456..c93caa4b4ab 100644 --- a/app/assets/javascripts/environments/components/new_environments_app.vue +++ b/app/assets/javascripts/environments/components/new_environments_app.vue @@ -5,20 +5,28 @@ 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, GlTabs, - StopEnvironmentModal, }, apollo: { environmentApp: { @@ -39,6 +47,12 @@ export default { pageInfo: { query: pageInfoQuery, }, + environmentToDelete: { + query: environmentToDeleteQuery, + }, + environmentToRollback: { + query: environmentToRollbackQuery, + }, environmentToStop: { query: environmentToStopQuery, }, @@ -63,6 +77,8 @@ export default { isReviewAppModalVisible: false, page: parseInt(page, 10), scope, + environmentToDelete: {}, + environmentToRollback: {}, environmentToStop: {}, }; }, @@ -71,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; @@ -164,7 +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" @@ -195,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/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/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 a2b3bda05fa..812fa0c81f0 100644 --- a/app/assets/javascripts/environments/graphql/resolvers.js +++ b/app/assets/javascripts/environments/graphql/resolvers.js @@ -66,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: { @@ -115,6 +114,14 @@ export const resolvers = (endpoint) => ({ 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 64cab480c98..c02f6b2838a 100644 --- a/app/assets/javascripts/environments/graphql/typedefs.graphql +++ b/app/assets/javascripts/environments/graphql/typedefs.graphql @@ -70,7 +70,7 @@ extend type Query { environmentToRollback: LocalEnvironment environmentToStop: LocalEnvironment isEnvironmentStopping(environment: LocalEnvironmentInput): Boolean - isLastDeployment: Boolean + isLastDeployment(environment: LocalEnvironmentInput): Boolean } extend type Mutation { @@ -81,4 +81,5 @@ extend type Mutation { setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors setEnvironmentToStop(environment: LocalEnvironmentInput): LocalErrors + action(environment: LocalEnvironmentInput): LocalErrors } |