diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
commit | 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch) | |
tree | 544930fb309b30317ae9797a9683768705d664c4 /app/assets/javascripts/environments | |
parent | 4b1de649d0168371549608993deac953eb692019 (diff) | |
download | gitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/environments')
4 files changed, 180 insertions, 70 deletions
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue index bc35a07fe4a..2192d456861 100644 --- a/app/assets/javascripts/environments/components/environment_actions.vue +++ b/app/assets/javascripts/environments/components/environment_actions.vue @@ -1,5 +1,5 @@ <script> -import { GlButton, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; +import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; import { __, s__, sprintf } from '~/locale'; import { formatTime } from '~/lib/utils/datetime_utility'; import eventHub from '../event_hub'; @@ -9,7 +9,8 @@ export default { GlTooltip: GlTooltipDirective, }, components: { - GlButton, + GlDropdown, + GlDropdownItem, GlIcon, GlLoadingIcon, }, @@ -35,7 +36,7 @@ export default { if (action.scheduledAt) { const confirmationMessage = sprintf( s__( - "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes.", + 'DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes.', ), { jobName: action.name }, ); @@ -67,40 +68,32 @@ export default { }; </script> <template> - <div class="btn-group" role="group"> - <gl-button - v-gl-tooltip - :title="title" - :aria-label="title" - :disabled="isLoading" - class="dropdown dropdown-new js-environment-actions-dropdown" - data-container="body" - data-toggle="dropdown" - data-testid="environment-actions-button" + <gl-dropdown + v-gl-tooltip + :title="title" + :aria-label="title" + :disabled="isLoading" + 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" /> + </template> + <gl-dropdown-item + v-for="(action, i) in actions" + :key="i" + :disabled="isActionDisabled(action)" + data-testid="manual-action-link" + @click="onClickAction(action)" > - <span> - <gl-icon name="play" /> - <gl-icon name="chevron-down" /> - <gl-loading-icon v-if="isLoading" /> + <span class="gl-flex-fill-1">{{ action.name }}</span> + <span v-if="action.scheduledAt" class="gl-text-gray-500 float-right"> + <gl-icon name="clock" /> + {{ remainingTime(action) }} </span> - </gl-button> - - <ul class="dropdown-menu dropdown-menu-right"> - <li v-for="(action, i) in actions" :key="i" class="gl-display-flex"> - <gl-button - :class="{ disabled: isActionDisabled(action) }" - :disabled="isActionDisabled(action)" - variant="link" - class="js-manual-action-link gl-flex-fill-1" - @click="onClickAction(action)" - > - <span class="gl-flex-fill-1">{{ action.name }}</span> - <span v-if="action.scheduledAt" class="text-secondary float-right"> - <gl-icon name="clock" /> - {{ remainingTime(action) }} - </span> - </gl-button> - </li> - </ul> - </div> + </gl-dropdown-item> + </gl-dropdown> </template> diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index 48e81b168ec..347828888dc 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -1,13 +1,14 @@ <script> /* eslint-disable @gitlab/vue-require-i18n-strings */ import { isEmpty } from 'lodash'; -import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; -import { __, sprintf } from '~/locale'; +import { GlTooltipDirective, GlIcon, GlLink } from '@gitlab/ui'; +import { __, s__, 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 TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; +import CiIcon from '~/vue_shared/components/ci_icon.vue'; import eventHub from '../event_hub'; import ActionsComponent from './environment_actions.vue'; import ExternalUrlComponent from './environment_external_url.vue'; @@ -30,6 +31,7 @@ export default { CommitComponent, ExternalUrlComponent, GlIcon, + GlLink, MonitoringButtonComponent, PinComponent, DeleteComponent, @@ -38,6 +40,7 @@ export default { TerminalButtonComponent, TooltipOnTruncate, UserAvatarLink, + CiIcon, }, directives: { GlTooltip: GlTooltipDirective, @@ -81,6 +84,24 @@ export default { }, /** + * @returns {Object|Undefined} The `upcoming_deployment` object if it exists. + * Otherwise, `undefined`. + */ + upcomingDeployment() { + return this.model?.upcoming_deployment; + }, + + /** + * @returns {String} Text that will be shown in the tooltip when + * the user hovers over the upcoming deployment's status icon. + */ + upcomingDeploymentTooltipText() { + return sprintf(s__('Environments|Deployment %{status}'), { + status: this.upcomingDeployment.deployable.status.text, + }); + }, + + /** * Checkes whether the row displayed is a folder. * * @returns {Boolean} @@ -235,6 +256,18 @@ export default { }, /** + * Same as `userImageAltDescription`, but for the + * upcoming deployment's user + * + * @returns {String} + */ + upcomingDeploymentUserImageAltDescription() { + return sprintf(__("%{username}'s avatar"), { + username: this.upcomingDeployment.user.username, + }); + }, + + /** * If provided, returns the commit tag. * * @returns {String|Undefined} @@ -382,6 +415,15 @@ export default { }, /** + * Same as `deploymentInternalId`, but for the upcoming deployment + * + * @returns {String} + */ + upcomingDeploymentInternalId() { + return `#${this.upcomingDeployment.iid}`; + }, + + /** * Verifies if the user object is present under last_deployment object. * * @returns {Boolean} @@ -503,6 +545,13 @@ export default { folderIconName() { return this.model.isOpen ? 'chevron-down' : 'chevron-right'; }, + + upcomingDeploymentCellClasses() { + return [ + this.tableData.upcoming.spacing, + { 'gl-display-none gl-display-md-block': !this.upcomingDeployment }, + ]; + }, }, methods: { @@ -512,6 +561,19 @@ export default { onClickFolder() { eventHub.$emit('toggleFolder', this.model); }, + + /** + * Returns the field title that will be shown in the field's row + * in the mobile view. + * + * @returns `field.mobileTitle` if present; + * if not, falls back to `field.title`. + */ + getMobileViewTitleForField(fieldName) { + const field = this.tableData[fieldName]; + + return field.mobileTitle || field.title; + }, }, }; </script> @@ -530,7 +592,7 @@ export default { role="gridcell" > <div v-if="!isFolder" class="table-mobile-header" role="rowheader"> - {{ tableData.name.title }} + {{ getMobileViewTitleForField('name') }} </div> <span v-if="shouldRenderDeployBoard" class="deploy-board-icon" @click="toggleDeployBoard"> @@ -609,7 +671,9 @@ export default { </div> <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 role="rowheader" class="table-mobile-header"> + {{ getMobileViewTitleForField('commit') }} + </div> <div v-if="hasLastDeploymentKey" class="js-commit-component table-mobile-content"> <commit-component :tag="commitTag" @@ -623,7 +687,9 @@ export default { </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> + <div role="rowheader" class="table-mobile-header"> + {{ getMobileViewTitleForField('date') }} + </div> <span v-if="canShowDeploymentDate" v-gl-tooltip @@ -636,8 +702,51 @@ export default { </span> </div> + <div + v-if="!isFolder" + class="table-section" + :class="upcomingDeploymentCellClasses" + role="gridcell" + data-testid="upcoming-deployment" + > + <div role="rowheader" class="table-mobile-header"> + {{ getMobileViewTitleForField('upcoming') }} + </div> + <div + v-if="upcomingDeployment" + class="gl-w-full gl-display-flex gl-flex-direction-row gl-md-flex-direction-column! gl-justify-content-end" + data-testid="upcoming-deployment-content" + > + <div class="gl-display-flex gl-align-items-center"> + <span class="gl-mr-2">{{ upcomingDeploymentInternalId }}</span> + <gl-link + v-if="upcomingDeployment.deployable" + v-gl-tooltip + :href="upcomingDeployment.deployable.build_path" + :title="upcomingDeploymentTooltipText" + data-testid="upcoming-deployment-status-link" + > + <ci-icon class="gl-mr-2" :status="upcomingDeployment.deployable.status" /> + </gl-link> + </div> + <div class="gl-display-flex"> + <span v-if="upcomingDeployment.user" class="text-break-word"> + by + <user-avatar-link + :link-href="upcomingDeployment.user.web_url" + :img-src="upcomingDeployment.user.avatar_url" + :img-alt="upcomingDeploymentUserImageAltDescription" + :tooltip-text="upcomingDeployment.user.username" + /> + </span> + </div> + </div> + </div> + <div v-if="!isFolder" class="table-section" :class="tableData.autoStop.spacing" role="gridcell"> - <div role="rowheader" class="table-mobile-header">{{ tableData.autoStop.title }}</div> + <div role="rowheader" class="table-mobile-header"> + {{ getMobileViewTitleForField('autoStop') }} + </div> <span v-if="canShowAutoStopDate" v-gl-tooltip diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index c1b9ba755a6..b6a7cce36e9 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -93,7 +93,9 @@ export default { }, beforeDestroy() { + // eslint-disable-next-line @gitlab/no-global-event-off eventHub.$off('toggleFolder'); + // eslint-disable-next-line @gitlab/no-global-event-off eventHub.$off('toggleDeployBoard'); }, @@ -141,13 +143,7 @@ export default { <confirm-rollback-modal :environment="environmentInRollbackModal" /> <div class="gl-w-full"> - <div - class=" - gl-display-flex - gl-flex-direction-column - gl-mt-3 - gl-display-md-none!" - > + <div class="gl-display-flex gl-flex-direction-column gl-mt-3 gl-display-md-none!"> <gl-button v-if="state.reviewAppDetails.can_setup_review_app" v-gl-modal="$options.modal.id" @@ -156,18 +152,16 @@ export default { category="secondary" type="button" class="gl-mb-3 gl-flex-fill-1" + >{{ $options.i18n.reviewAppButtonLabel }}</gl-button > - {{ $options.i18n.reviewAppButtonLabel }} - </gl-button> <gl-button v-if="canCreateEnvironment" :href="newEnvironmentPath" data-testid="new-environment" category="primary" variant="success" + >{{ $options.i18n.newEnvironmentButtonLabel }}</gl-button > - {{ $options.i18n.newEnvironmentButtonLabel }} - </gl-button> </div> <gl-tabs content-class="gl-display-none"> <gl-tab @@ -183,14 +177,7 @@ export default { </gl-tab> <template #tabs-end> <div - class=" - gl-display-none - gl-display-md-flex - gl-lg-align-items-center - gl-lg-flex-direction-row - gl-lg-flex-fill-1 - gl-lg-justify-content-end - gl-lg-mt-0" + class="gl-display-none gl-display-md-flex gl-lg-align-items-center gl-lg-flex-direction-row gl-lg-flex-fill-1 gl-lg-justify-content-end gl-lg-mt-0" > <gl-button v-if="state.reviewAppDetails.can_setup_review_app" @@ -200,18 +187,16 @@ export default { category="secondary" type="button" class="gl-mb-3 gl-lg-mr-3 gl-lg-mb-0" + >{{ $options.i18n.reviewAppButtonLabel }}</gl-button > - {{ $options.i18n.reviewAppButtonLabel }} - </gl-button> <gl-button v-if="canCreateEnvironment" :href="newEnvironmentPath" data-testid="new-environment" category="primary" variant="success" + >{{ $options.i18n.newEnvironmentButtonLabel }}</gl-button > - {{ $options.i18n.newEnvironmentButtonLabel }} - </gl-button> </div> </template> </gl-tabs> diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index c1b3eabec16..d13c7204285 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -15,6 +15,7 @@ export default { CanaryDeploymentCallout: () => import('ee_component/environments/components/canary_deployment_callout.vue'), EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'), + CanaryUpdateModal: () => import('ee_component/environments/components/canary_update_modal.vue'), }, props: { environments: { @@ -58,6 +59,12 @@ export default { default: '', }, }, + data() { + return { + canaryWeight: 0, + environmentToChange: null, + }; + }, computed: { sortedEnvironments() { return this.sortEnvironments(this.environments).map(env => @@ -71,7 +78,7 @@ export default { // percent spacing for cols, should add up to 100 name: { title: s__('Environments|Environment'), - spacing: 'section-15', + spacing: 'section-10', }, deploy: { title: s__('Environments|Deployment'), @@ -83,18 +90,23 @@ export default { }, commit: { title: s__('Environments|Commit'), - spacing: 'section-20', + spacing: 'section-15', }, date: { title: s__('Environments|Updated'), spacing: 'section-10', }, + upcoming: { + title: s__('Environments|Upcoming'), + mobileTitle: s__('Environments|Upcoming deployment'), + spacing: 'section-10', + }, autoStop: { title: s__('Environments|Auto stop in'), - spacing: 'section-5', + spacing: 'section-10', }, actions: { - spacing: 'section-25', + spacing: 'section-20', }, }; }, @@ -139,11 +151,16 @@ export default { sortBy(env => (env.isFolder ? -1 : 1)), )(environments); }, + changeCanaryWeight(model, weight) { + this.environmentToChange = model; + this.canaryWeight = weight; + }, }, }; </script> <template> <div class="ci-table" role="grid"> + <canary-update-modal :environment="environmentToChange" :weight="canaryWeight" /> <div class="gl-responsive-table-row table-row-header" role="row"> <div class="table-section" :class="tableData.name.spacing" role="columnheader"> {{ tableData.name.title }} @@ -160,6 +177,9 @@ export default { <div class="table-section" :class="tableData.date.spacing" role="columnheader"> {{ tableData.date.title }} </div> + <div class="table-section" :class="tableData.upcoming.spacing" role="columnheader"> + {{ tableData.upcoming.title }} + </div> <div class="table-section" :class="tableData.autoStop.spacing" role="columnheader"> {{ tableData.autoStop.title }} </div> @@ -171,6 +191,7 @@ export default { :model="model" :can-read-environment="canReadEnvironment" :table-data="tableData" + data-qa-selector="environment_item" /> <div @@ -185,6 +206,7 @@ export default { :is-loading="model.isLoadingDeployBoard" :is-empty="model.isEmptyDeployBoard" :logs-path="model.logs_path" + @changeCanaryWeight="changeCanaryWeight(model, $event)" /> </div> </div> @@ -207,6 +229,7 @@ export default { :model="children" :can-read-environment="canReadEnvironment" :table-data="tableData" + data-qa-selector="environment_item" /> <div :key="`sub-div-${i}`"> |