diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-12 18:13:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-12 18:13:54 +0300 |
commit | 98638cd5e43611aac2193a5c2f80f72374040430 (patch) | |
tree | 6605f0f284efed1d05708b3799f093eb5e305a8f /app/assets/javascripts/environments | |
parent | 43d816ebc20da6ff959176248c70d8c4c7c9345a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/environments')
4 files changed, 185 insertions, 78 deletions
diff --git a/app/assets/javascripts/environments/components/deploy_freeze_alert.vue b/app/assets/javascripts/environments/components/deploy_freeze_alert.vue new file mode 100644 index 00000000000..aaa7e71758c --- /dev/null +++ b/app/assets/javascripts/environments/components/deploy_freeze_alert.vue @@ -0,0 +1,79 @@ +<script> +import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui'; +import { sortBy } from 'lodash'; +import { formatDate } from '~/lib/utils/datetime/date_format_utility'; +import { helpPagePath } from '~/helpers/help_page_helper'; +import { s__ } from '~/locale'; +import deployFreezesQuery from '../graphql/queries/deploy_freezes.query.graphql'; + +export default { + components: { + GlAlert, + GlLink, + GlSprintf, + }, + inject: ['projectFullPath'], + props: { + name: { + type: String, + required: true, + }, + }, + data() { + return { deployFreezes: [] }; + }, + + apollo: { + deployFreezes: { + query: deployFreezesQuery, + update(data) { + const freezes = data?.project?.environment?.deployFreezes; + return sortBy(freezes, [(freeze) => freeze.startTime]); + }, + variables() { + return { + projectFullPath: this.projectFullPath, + environmentName: this.name, + }; + }, + }, + }, + computed: { + shouldShowDeployFreezeAlert() { + return this.deployFreezes.length > 0; + }, + nextDeployFreeze() { + return this.deployFreezes[0]; + }, + deployFreezeStartTime() { + return formatDate(this.nextDeployFreeze.startTime); + }, + deployFreezeEndTime() { + return formatDate(this.nextDeployFreeze.endTime); + }, + }, + i18n: { + deployFreezeAlert: s__( + 'Environments|A freeze period is in effect from %{startTime} to %{endTime}. Deployments might fail during this time. For more information, see the %{docsLinkStart}deploy freeze documentation%{docsLinkEnd}.', + ), + }, + deployFreezeDocsPath: helpPagePath('user/project/releases/index', { + anchor: 'prevent-unintentional-releases-by-setting-a-deploy-freeze', + }), +}; +</script> +<template> + <gl-alert v-if="shouldShowDeployFreezeAlert" :dismissible="false" class="gl-mt-4"> + <gl-sprintf :message="$options.i18n.deployFreezeAlert"> + <template #startTime + ><span class="gl-font-weight-bold">{{ deployFreezeStartTime }}</span></template + > + <template #endTime + ><span class="gl-font-weight-bold">{{ deployFreezeEndTime }}</span></template + > + <template #docsLink="{ content }" + ><gl-link :href="$options.deployFreezeDocsPath">{{ content }}</gl-link></template + > + </gl-sprintf> + </gl-alert> +</template> diff --git a/app/assets/javascripts/environments/components/environments_detail_header.vue b/app/assets/javascripts/environments/components/environments_detail_header.vue index 1e555347011..0507abf3eaf 100644 --- a/app/assets/javascripts/environments/components/environments_detail_header.vue +++ b/app/assets/javascripts/environments/components/environments_detail_header.vue @@ -7,6 +7,7 @@ import timeagoMixin from '~/vue_shared/mixins/timeago'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import DeleteEnvironmentModal from './delete_environment_modal.vue'; import StopEnvironmentModal from './stop_environment_modal.vue'; +import DeployFreezeAlert from './deploy_freeze_alert.vue'; export default { name: 'EnvironmentsDetailHeader', @@ -15,6 +16,7 @@ export default { GlButton, GlSprintf, TimeAgo, + DeployFreezeAlert, DeleteEnvironmentModal, StopEnvironmentModal, }, @@ -96,81 +98,88 @@ export default { }; </script> <template> - <header class="top-area gl-justify-content-between"> - <div class="gl-display-flex gl-flex-grow-1 gl-align-items-center"> - <h1 class="page-title gl-font-size-h-display"> - {{ environment.name }} - </h1> - <p v-if="shouldShowCancelAutoStopButton" class="gl-mb-0 gl-ml-3" data-testid="auto-stops-at"> - <gl-sprintf :message="$options.i18n.autoStopAtText"> - <template #autoStopAt> - <time-ago :time="environment.autoStopAt" /> - </template> - </gl-sprintf> - </p> - </div> - <div class="nav-controls gl-my-1"> - <form method="POST" :action="cancelAutoStopPath" data-testid="cancel-auto-stop-form"> - <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> - <gl-button + <div> + <deploy-freeze-alert :name="environment.name" /> + <header class="top-area gl-justify-content-between"> + <div class="gl-display-flex gl-flex-grow-1 gl-align-items-center"> + <h1 class="page-title gl-font-size-h-display"> + {{ environment.name }} + </h1> + <p v-if="shouldShowCancelAutoStopButton" - v-gl-tooltip.hover - data-testid="cancel-auto-stop-button" - :title="$options.i18n.cancelAutoStopButtonTitle" - type="submit" - icon="thumbtack" + class="gl-mb-0 gl-ml-3" + data-testid="auto-stops-at" + > + <gl-sprintf :message="$options.i18n.autoStopAtText"> + <template #autoStopAt> + <time-ago :time="environment.autoStopAt" /> + </template> + </gl-sprintf> + </p> + </div> + <div class="nav-controls gl-my-1"> + <form method="POST" :action="cancelAutoStopPath" data-testid="cancel-auto-stop-form"> + <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> + <gl-button + v-if="shouldShowCancelAutoStopButton" + v-gl-tooltip.hover + data-testid="cancel-auto-stop-button" + :title="$options.i18n.cancelAutoStopButtonTitle" + type="submit" + icon="thumbtack" + /> + </form> + <gl-button + v-if="shouldShowTerminalButton" + data-testid="terminal-button" + :href="terminalPath" + icon="terminal" /> - </form> - <gl-button - v-if="shouldShowTerminalButton" - data-testid="terminal-button" - :href="terminalPath" - icon="terminal" - /> - <gl-button - v-if="shouldShowExternalUrlButton" - v-gl-tooltip.hover - data-testid="external-url-button" - :title="$options.i18n.externalButtonTitle" - :href="environment.externalUrl" - is-unsafe-link - icon="external-link" - target="_blank" - >{{ $options.i18n.externalButtonText }}</gl-button - > - <gl-button - v-if="shouldShowMetricsButton" - v-gl-tooltip.hover - data-testid="metrics-button" - :href="metricsPath" - :title="$options.i18n.metricsButtonTitle" - icon="chart" - class="gl-mr-2" - > - {{ $options.i18n.metricsButtonText }} - </gl-button> - <gl-button v-if="canUpdateEnvironment" data-testid="edit-button" :href="updatePath"> - {{ $options.i18n.editButtonText }} - </gl-button> - <gl-button - v-if="shouldShowStopButton" - v-gl-modal-directive="'stop-environment-modal'" - data-testid="stop-button" - icon="stop" - variant="danger" - > - {{ $options.i18n.stopButtonText }} - </gl-button> - <gl-button - v-if="canDestroyEnvironment" - v-gl-modal-directive="'delete-environment-modal'" - data-testid="destroy-button" - variant="danger" - > - {{ $options.i18n.deleteButtonText }} - </gl-button> - </div> - <delete-environment-modal v-if="canDestroyEnvironment" :environment="environment" /> - <stop-environment-modal v-if="shouldShowStopButton" :environment="environment" /> - </header> + <gl-button + v-if="shouldShowExternalUrlButton" + v-gl-tooltip.hover + data-testid="external-url-button" + :title="$options.i18n.externalButtonTitle" + :href="environment.externalUrl" + is-unsafe-link + icon="external-link" + target="_blank" + >{{ $options.i18n.externalButtonText }}</gl-button + > + <gl-button + v-if="shouldShowMetricsButton" + v-gl-tooltip.hover + data-testid="metrics-button" + :href="metricsPath" + :title="$options.i18n.metricsButtonTitle" + icon="chart" + class="gl-mr-2" + > + {{ $options.i18n.metricsButtonText }} + </gl-button> + <gl-button v-if="canUpdateEnvironment" data-testid="edit-button" :href="updatePath"> + {{ $options.i18n.editButtonText }} + </gl-button> + <gl-button + v-if="shouldShowStopButton" + v-gl-modal-directive="'stop-environment-modal'" + data-testid="stop-button" + icon="stop" + variant="danger" + > + {{ $options.i18n.stopButtonText }} + </gl-button> + <gl-button + v-if="canDestroyEnvironment" + v-gl-modal-directive="'delete-environment-modal'" + data-testid="destroy-button" + variant="danger" + > + {{ $options.i18n.deleteButtonText }} + </gl-button> + </div> + <delete-environment-modal v-if="canDestroyEnvironment" :environment="environment" /> + <stop-environment-modal v-if="shouldShowStopButton" :environment="environment" /> + </header> + </div> </template> diff --git a/app/assets/javascripts/environments/graphql/queries/deploy_freezes.query.graphql b/app/assets/javascripts/environments/graphql/queries/deploy_freezes.query.graphql new file mode 100644 index 00000000000..7d701b95bbf --- /dev/null +++ b/app/assets/javascripts/environments/graphql/queries/deploy_freezes.query.graphql @@ -0,0 +1,12 @@ +query getEnvironmentFreezes($projectFullPath: ID!, $environmentName: String) { + project(fullPath: $projectFullPath) { + id + environment(name: $environmentName) { + id + deployFreezes { + startTime + endTime + } + } + } +} diff --git a/app/assets/javascripts/environments/mount_show.js b/app/assets/javascripts/environments/mount_show.js index cc13a237aca..f73cb7fe1bc 100644 --- a/app/assets/javascripts/environments/mount_show.js +++ b/app/assets/javascripts/environments/mount_show.js @@ -3,9 +3,13 @@ import VueApollo from 'vue-apollo'; import VueRouter from 'vue-router'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import EnvironmentsDetailHeader from './components/environments_detail_header.vue'; -import { apolloProvider } from './graphql/client'; +import { apolloProvider as createApolloProvider } from './graphql/client'; import environmentsMixin from './mixins/environments_mixin'; +Vue.use(VueApollo); + +const apolloProvider = createApolloProvider(); + export const initHeader = () => { const el = document.getElementById('environments-detail-view-header'); const container = document.getElementById('environments-detail-view'); @@ -13,7 +17,11 @@ export const initHeader = () => { return new Vue({ el, + apolloProvider, mixins: [environmentsMixin], + provide: { + projectFullPath: dataset.projectFullPath, + }, data() { const environment = { name: dataset.name, @@ -60,7 +68,6 @@ export const initPage = async () => { const dataElement = document.getElementById('environments-detail-view'); const dataSet = convertObjectPropsToCamelCase(JSON.parse(dataElement.dataset.details)); - Vue.use(VueApollo); Vue.use(VueRouter); const el = document.getElementById('environment_details_page'); @@ -90,7 +97,7 @@ export const initPage = async () => { return new Vue({ el, - apolloProvider: apolloProvider(), + apolloProvider, router, provide: { projectPath: dataSet.projectFullPath, |