diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-03 09:07:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-03 09:07:33 +0000 |
commit | c0d8f9f3f962df6bfcc70440432da55d67307189 (patch) | |
tree | 457666705fbbd4f517d201680113406163829fcc /app/assets/javascripts/environments | |
parent | 2cfa1fc75dd4bd6d1f70d5fee1a824410694f297 (diff) | |
download | gitlab-ce-c0d8f9f3f962df6bfcc70440432da55d67307189.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/environments')
4 files changed, 206 insertions, 62 deletions
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index 428dfe5fcf7..3096ccad0aa 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -1,22 +1,23 @@ <script> /* eslint-disable @gitlab/vue-i18n/no-bare-strings */ -import { format } from 'timeago.js'; import _ from 'underscore'; import { GlTooltipDirective } from '@gitlab/ui'; -import environmentItemMixin from 'ee_else_ce/environments/mixins/environment_item_mixin'; +import { __, sprintf } from '~/locale'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import CommitComponent from '~/vue_shared/components/commit.vue'; import Icon from '~/vue_shared/components/icon.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; -import { __, sprintf } from '~/locale'; +import environmentItemMixin from 'ee_else_ce/environments/mixins/environment_item_mixin'; +import eventHub from '../event_hub'; import ActionsComponent from './environment_actions.vue'; import ExternalUrlComponent from './environment_external_url.vue'; -import StopComponent from './environment_stop.vue'; +import MonitoringButtonComponent from './environment_monitoring.vue'; +import PinComponent from './environment_pin.vue'; import RollbackComponent from './environment_rollback.vue'; +import StopComponent from './environment_stop.vue'; import TerminalButtonComponent from './environment_terminal_button.vue'; -import MonitoringButtonComponent from './environment_monitoring.vue'; -import CommitComponent from '../../vue_shared/components/commit.vue'; -import eventHub from '../event_hub'; -import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; /** * Environment Item Component @@ -26,21 +27,22 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; export default { components: { - CommitComponent, - Icon, ActionsComponent, + CommitComponent, ExternalUrlComponent, - StopComponent, + Icon, + MonitoringButtonComponent, + PinComponent, RollbackComponent, + StopComponent, TerminalButtonComponent, - MonitoringButtonComponent, TooltipOnTruncate, UserAvatarLink, }, directives: { GlTooltip: GlTooltipDirective, }, - mixins: [environmentItemMixin], + mixins: [environmentItemMixin, timeagoMixin], props: { canReadEnvironment: { @@ -52,7 +54,12 @@ export default { model: { type: Object, required: true, - default: () => ({}), + }, + + shouldShowAutoStopDate: { + type: Boolean, + required: false, + default: false, }, tableData: { @@ -77,6 +84,16 @@ export default { }, /** + * Checkes whether the row displayed is a folder. + * + * @returns {Boolean} + */ + + isFolder() { + return this.model.isFolder; + }, + + /** * Checkes whether the environment is protected. * (`is_protected` currently only set in EE) * @@ -112,24 +129,64 @@ export default { }, /** - * Verifies if the date to be shown is present. + * Verifies if the autostop date is present. + * + * @returns {Boolean} + */ + canShowAutoStopDate() { + if (!this.model.auto_stop_at) { + return false; + } + + const autoStopDate = new Date(this.model.auto_stop_at); + const now = new Date(); + + return now < autoStopDate; + }, + + /** + * Human readable deployment date. + * + * @returns {String} + */ + autoStopDate() { + if (this.canShowAutoStopDate) { + return { + formatted: this.timeFormatted(this.model.auto_stop_at), + tooltip: this.tooltipTitle(this.model.auto_stop_at), + }; + } + return { + formatted: '', + tooltip: '', + }; + }, + + /** + * Verifies if the deployment date is present. * * @returns {Boolean|Undefined} */ - canShowDate() { + canShowDeploymentDate() { return this.model && this.model.last_deployment && this.model.last_deployment.deployed_at; }, /** - * Human readable date. + * Human readable deployment date. * * @returns {String} */ deployedDate() { - if (this.canShowDate) { - return format(this.model.last_deployment.deployed_at); + if (this.canShowDeploymentDate) { + return { + formatted: this.timeFormatted(this.model.last_deployment.deployed_at), + tooltip: this.tooltipTitle(this.model.last_deployment.deployed_at), + }; } - return ''; + return { + formatted: '', + tooltip: '', + }; }, actions() { @@ -345,6 +402,15 @@ export default { }, /** + * Checkes whether to display no deployment text. + * + * @returns {Boolean} + */ + showNoDeployments() { + return !this.hasLastDeploymentKey && !this.isFolder; + }, + + /** * Verifies if the build name column should be rendered by verifing * if all the information needed is present * and if the environment is not a folder. @@ -353,7 +419,7 @@ export default { */ shouldRenderBuildName() { return ( - !this.model.isFolder && + !this.isFolder && !_.isEmpty(this.model.last_deployment) && !_.isEmpty(this.model.last_deployment.deployable) ); @@ -383,11 +449,7 @@ export default { * @return {String} */ externalURL() { - if (this.model && this.model.external_url) { - return this.model.external_url; - } - - return ''; + return this.model.external_url || ''; }, /** @@ -399,26 +461,22 @@ export default { */ shouldRenderDeploymentID() { return ( - !this.model.isFolder && + !this.isFolder && !_.isEmpty(this.model.last_deployment) && this.model.last_deployment.iid !== undefined ); }, environmentPath() { - if (this.model && this.model.environment_path) { - return this.model.environment_path; - } - - return ''; + return this.model.environment_path || ''; }, monitoringUrl() { - if (this.model && this.model.metrics_path) { - return this.model.metrics_path; - } + return this.model.metrics_path || ''; + }, - return ''; + autoStopUrl() { + return this.model.cancel_auto_stop_path || ''; }, displayEnvironmentActions() { @@ -447,7 +505,7 @@ export default { <div :class="{ 'js-child-row environment-child-row': model.isChildren, - 'folder-row': model.isFolder, + 'folder-row': isFolder, }" class="gl-responsive-table-row" role="row" @@ -457,7 +515,7 @@ export default { :class="tableData.name.spacing" role="gridcell" > - <div v-if="!model.isFolder" class="table-mobile-header" role="rowheader"> + <div v-if="!isFolder" class="table-mobile-header" role="rowheader"> {{ tableData.name.title }} </div> @@ -466,7 +524,7 @@ export default { </span> <span - v-if="!model.isFolder" + v-if="!isFolder" v-gl-tooltip :title="model.name" class="environment-name table-mobile-content" @@ -506,7 +564,7 @@ export default { {{ deploymentInternalId }} </span> - <span v-if="!model.isFolder && deploymentHasUser" class="text-break-word"> + <span v-if="!isFolder && deploymentHasUser" class="text-break-word"> by <user-avatar-link :link-href="deploymentUser.web_url" @@ -516,6 +574,10 @@ export default { class="js-deploy-user-container float-none" /> </span> + + <div v-if="showNoDeployments" class="commit-title table-mobile-content"> + {{ s__('Environments|No deployments yet') }} + </div> </div> <div @@ -536,14 +598,8 @@ export default { </a> </div> - <div - v-if="!model.isFolder" - class="table-section" - :class="tableData.commit.spacing" - role="gridcell" - > + <div v-if="!isFolder" class="table-section" :class="tableData.commit.spacing" role="gridcell"> <div role="rowheader" class="table-mobile-header">{{ tableData.commit.title }}</div> - <div v-if="hasLastDeploymentKey" class="js-commit-component table-mobile-content"> <commit-component :tag="commitTag" @@ -554,31 +610,51 @@ export default { :author="commitAuthor" /> </div> - <div v-if="!hasLastDeploymentKey" class="commit-title table-mobile-content"> - {{ s__('Environments|No deployments yet') }} - </div> + </div> + + <div v-if="!isFolder" class="table-section" :class="tableData.date.spacing" role="gridcell"> + <div role="rowheader" class="table-mobile-header">{{ tableData.date.title }}</div> + <span + v-if="canShowDeploymentDate" + v-gl-tooltip + :title="deployedDate.tooltip" + class="environment-created-date-timeago table-mobile-content flex-truncate-parent" + > + <span class="flex-truncate-child"> + {{ deployedDate.formatted }} + </span> + </span> </div> <div - v-if="!model.isFolder" + v-if="!isFolder && shouldShowAutoStopDate" class="table-section" - :class="tableData.date.spacing" + :class="tableData.autoStop.spacing" role="gridcell" > - <div role="rowheader" class="table-mobile-header">{{ tableData.date.title }}</div> - - <span v-if="canShowDate" class="environment-created-date-timeago table-mobile-content"> - {{ deployedDate }} + <div role="rowheader" class="table-mobile-header">{{ tableData.autoStop.title }}</div> + <span + v-if="canShowAutoStopDate" + v-gl-tooltip + :title="autoStopDate.tooltip" + class="table-mobile-content flex-truncate-parent" + > + <span class="flex-truncate-child js-auto-stop">{{ autoStopDate.formatted }}</span> </span> </div> <div - v-if="!model.isFolder && displayEnvironmentActions" + v-if="!isFolder && displayEnvironmentActions" class="table-section table-button-footer" :class="tableData.actions.spacing" role="gridcell" > <div class="btn-group table-action-buttons" role="group"> + <pin-component + v-if="canShowAutoStopDate && shouldShowAutoStopDate" + :auto-stop-url="autoStopUrl" + /> + <external-url-component v-if="externalURL && canReadEnvironment" :external-url="externalURL" diff --git a/app/assets/javascripts/environments/components/environment_pin.vue b/app/assets/javascripts/environments/components/environment_pin.vue new file mode 100644 index 00000000000..7908928a7ac --- /dev/null +++ b/app/assets/javascripts/environments/components/environment_pin.vue @@ -0,0 +1,37 @@ +<script> +/** + * Renders a prevent auto-stop button. + * Used in environments table. + */ +import { GlButton, GlTooltipDirective } from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; +import { __ } from '~/locale'; +import eventHub from '../event_hub'; + +export default { + components: { + Icon, + GlButton, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + props: { + autoStopUrl: { + type: String, + required: true, + }, + }, + methods: { + onPinClick() { + eventHub.$emit('cancelAutoStop', this.autoStopUrl); + }, + }, + title: __('Prevent environment from auto-stopping'), +}; +</script> +<template> + <gl-button v-gl-tooltip :title="$options.title" :aria-label="$options.title" @click="onPinClick"> + <icon name="thumbtack" /> + </gl-button> +</template> diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index 453e7610e21..30299ccc7bc 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -6,6 +6,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import _ from 'underscore'; import environmentTableMixin from 'ee_else_ce/environments/mixins/environments_table_mixin'; import { s__ } from '~/locale'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import EnvironmentItem from './environment_item.vue'; export default { @@ -16,7 +17,7 @@ export default { CanaryDeploymentCallout: () => import('ee_component/environments/components/canary_deployment_callout.vue'), }, - mixins: [environmentTableMixin], + mixins: [environmentTableMixin, glFeatureFlagsMixin()], props: { environments: { type: Array, @@ -42,6 +43,9 @@ export default { : env, ); }, + shouldShowAutoStopDate() { + return this.glFeatures.autoStopEnvironments; + }, tableData() { return { // percent spacing for cols, should add up to 100 @@ -65,8 +69,12 @@ export default { title: s__('Environments|Updated'), spacing: 'section-10', }, + autoStop: { + title: s__('Environments|Auto stop in'), + spacing: 'section-5', + }, actions: { - spacing: 'section-30', + spacing: this.shouldShowAutoStopDate ? 'section-25' : 'section-30', }, }; }, @@ -123,6 +131,14 @@ export default { <div class="table-section" :class="tableData.date.spacing" role="columnheader"> {{ tableData.date.title }} </div> + <div + v-if="shouldShowAutoStopDate" + class="table-section" + :class="tableData.autoStop.spacing" + role="columnheader" + > + {{ tableData.autoStop.title }} + </div> </div> <template v-for="(model, i) in sortedEnvironments" :model="model"> <div @@ -130,6 +146,7 @@ export default { :key="`environment-item-${i}`" :model="model" :can-read-environment="canReadEnvironment" + :should-show-auto-stop-date="shouldShowAutoStopDate" :table-data="tableData" /> diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 31347d95a25..34374e306a4 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -90,16 +90,19 @@ export default { Flash(s__('Environments|An error occurred while fetching the environments.')); }, - postAction({ endpoint, errorMessage }) { + postAction({ + endpoint, + errorMessage = s__('Environments|An error occurred while making the request.'), + }) { if (!this.isMakingRequest) { this.isLoading = true; this.service .postAction(endpoint) .then(() => this.fetchEnvironments()) - .catch(() => { + .catch(err => { this.isLoading = false; - Flash(errorMessage || s__('Environments|An error occurred while making the request.')); + Flash(_.isFunction(errorMessage) ? errorMessage(err.response.data) : errorMessage); }); } }, @@ -138,6 +141,13 @@ export default { ); this.postAction({ endpoint: retryUrl, errorMessage }); }, + + cancelAutoStop(autoStopPath) { + const errorMessage = ({ message }) => + message || + s__('Environments|An error occurred while canceling the auto stop, please try again'); + this.postAction({ endpoint: autoStopPath, errorMessage }); + }, }, computed: { @@ -199,6 +209,8 @@ export default { eventHub.$on('requestRollbackEnvironment', this.updateRollbackModal); eventHub.$on('rollbackEnvironment', this.rollbackEnvironment); + + eventHub.$on('cancelAutoStop', this.cancelAutoStop); }, beforeDestroy() { @@ -208,5 +220,7 @@ export default { eventHub.$off('requestRollbackEnvironment', this.updateRollbackModal); eventHub.$off('rollbackEnvironment', this.rollbackEnvironment); + + eventHub.$off('cancelAutoStop', this.cancelAutoStop); }, }; |