diff options
Diffstat (limited to 'app')
15 files changed, 105 insertions, 26 deletions
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index 1bf705dcda2..c06ab265915 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -14,6 +14,7 @@ export default { DeployBoard: () => import('ee_component/environments/components/deploy_board_component.vue'), CanaryDeploymentCallout: () => import('ee_component/environments/components/canary_deployment_callout.vue'), + EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'), }, props: { environments: { @@ -111,6 +112,9 @@ export default { shouldShowCanaryCallout(env) { return env.showCanaryCallout && this.showCanaryDeploymentCallout; }, + shouldRenderAlert(env) { + return env?.has_opened_alert; + }, sortEnvironments(environments) { /* * The sorting algorithm should sort in the following priorities: @@ -185,6 +189,11 @@ export default { /> </div> </div> + <environment-alert + v-if="shouldRenderAlert(model)" + :key="`alert-row-${i}`" + :environment="model" + /> <template v-if="shouldRenderFolderContent(model)"> <div v-if="model.isLoadingFolderContent" :key="`loading-item-${i}`"> diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js index 56896ac4d43..6c547c3713a 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js +++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js @@ -1,20 +1,33 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; import canaryCalloutMixin from '../mixins/canary_callout_mixin'; import environmentsFolderApp from './environments_folder_view.vue'; import { parseBoolean } from '../../lib/utils/common_utils'; import Translate from '../../vue_shared/translate'; +import createDefaultClient from '~/lib/graphql'; Vue.use(Translate); +Vue.use(VueApollo); -export default () => - new Vue({ - el: '#environments-folder-list-view', +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +export default () => { + const el = document.getElementById('environments-folder-list-view'); + + return new Vue({ + el, components: { environmentsFolderApp, }, mixins: [canaryCalloutMixin], + apolloProvider, + provide: { + projectPath: el.dataset.projectPath, + }, data() { - const environmentsData = document.querySelector(this.$options.el).dataset; + const environmentsData = el.dataset; return { endpoint: environmentsData.environmentsDataEndpoint, @@ -35,3 +48,4 @@ export default () => }); }, }); +}; diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue index e1e356a977f..16d25615779 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.vue +++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue @@ -23,7 +23,8 @@ export default { }, cssContainerClass: { type: String, - required: true, + required: false, + default: '', }, canReadEnvironment: { type: Boolean, diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js index 4848cb0f13d..8e8af3f32f7 100644 --- a/app/assets/javascripts/environments/index.js +++ b/app/assets/javascripts/environments/index.js @@ -1,20 +1,32 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; import canaryCalloutMixin from './mixins/canary_callout_mixin'; import environmentsComponent from './components/environments_app.vue'; import { parseBoolean } from '../lib/utils/common_utils'; import Translate from '../vue_shared/translate'; +import createDefaultClient from '~/lib/graphql'; Vue.use(Translate); +Vue.use(VueApollo); -export default () => - new Vue({ - el: '#environments-list-view', +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +export default () => { + const el = document.getElementById('environments-list-view'); + return new Vue({ + el, components: { environmentsComponent, }, mixins: [canaryCalloutMixin], + apolloProvider, + provide: { + projectPath: el.dataset.projectPath, + }, data() { - const environmentsData = document.querySelector(this.$options.el).dataset; + const environmentsData = el.dataset; return { endpoint: environmentsData.environmentsDataEndpoint, @@ -39,3 +51,4 @@ export default () => }); }, }); +}; diff --git a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js b/app/assets/javascripts/environments/mixins/canary_callout_mixin.js index 398576a31cb..e9f1a144cb3 100644 --- a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js +++ b/app/assets/javascripts/environments/mixins/canary_callout_mixin.js @@ -2,7 +2,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; export default { data() { - const data = document.querySelector(this.$options.el).dataset; + const data = this.$options.el.dataset; return { canaryDeploymentFeatureId: data.environmentsDataCanaryDeploymentFeatureId, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index 3e2c119fa7c..5066a88b52b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -1,8 +1,15 @@ <script> /* eslint-disable vue/require-default-prop, vue/no-v-html */ -import { GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; +import { + GlIcon, + GlLink, + GlLoadingIcon, + GlSprintf, + GlTooltip, + GlTooltipDirective, +} from '@gitlab/ui'; import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline'; -import { s__ } from '~/locale'; +import { s__, n__ } from '~/locale'; import PipelineStage from '~/pipelines/components/pipelines_list/stage.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; @@ -15,6 +22,7 @@ export default { GlLoadingIcon, GlIcon, GlSprintf, + GlTooltip, PipelineStage, TooltipOnTruncate, LinkedPipelinesMiniList: () => @@ -33,6 +41,11 @@ export default { type: String, required: false, }, + buildsWithCoverage: { + type: Array, + required: false, + default: () => [], + }, // This prop needs to be camelCase, html attributes are case insensive // https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case hasCi: { @@ -100,6 +113,16 @@ export default { } return ''; }, + pipelineCoverageJobNumberText() { + return n__('from %d job', 'from %d jobs', this.buildsWithCoverage.length); + }, + pipelineCoverageTooltipDescription() { + return n__( + 'Coverage value for this pipeline was calculated by the coverage value of %d job.', + 'Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs.', + this.buildsWithCoverage.length, + ); + }, }, errorText: s__( 'Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}.', @@ -139,7 +162,7 @@ export default { > <gl-icon name="question" - :small="12" + :size="12" tabindex="0" role="text" :aria-label="__('Link to go to GitLab pipeline documentation')" @@ -189,14 +212,30 @@ export default { </div> <div v-if="pipeline.coverage" class="coverage" data-testid="pipeline-coverage"> {{ s__('Pipeline|Coverage') }} {{ pipeline.coverage }}% - <span v-if="pipelineCoverageDelta" :class="coverageDeltaClass" data-testid="pipeline-coverage-delta" + >({{ pipelineCoverageDelta }}%)</span > - ({{ pipelineCoverageDelta }}%) + + {{ pipelineCoverageJobNumberText }} + <span ref="pipelineCoverageQuestion"> + <gl-icon name="question" :size="12" /> </span> + <gl-tooltip + :target="() => $refs.pipelineCoverageQuestion" + data-testid="pipeline-coverage-tooltip" + > + {{ pipelineCoverageTooltipDescription }} + <div + v-for="(build, index) in buildsWithCoverage" + :key="`${build.name}-${index}`" + class="gl-mt-3 gl-text-left gl-px-4" + > + {{ build.name }} ({{ build.coverage }}%) + </div> + </gl-tooltip> </div> </div> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue index 5c307b5ff0c..55efd7e7d3b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue @@ -77,6 +77,7 @@ export default { <mr-widget-pipeline :pipeline="pipeline" :pipeline-coverage-delta="mr.pipelineCoverageDelta" + :builds-with-coverage="mr.buildsWithCoverage" :ci-status="mr.ciStatus" :has-ci="mr.hasCI" :pipeline-must-succeed="mr.onlyAllowMergeIfPipelineSucceeds" diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 8c98ba1b023..5695e02bbab 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -52,6 +52,7 @@ export default class MergeRequestStore { this.divergedCommitsCount = data.diverged_commits_count; this.pipeline = data.pipeline || {}; this.pipelineCoverageDelta = data.pipeline_coverage_delta; + this.buildsWithCoverage = data.builds_with_coverage; this.mergePipeline = data.merge_pipeline || {}; this.deployments = this.deployments || data.deployments || []; this.postMergeDeployments = this.postMergeDeployments || []; diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index aa02bc132f9..e65b27db3ae 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -76,8 +76,12 @@ class InvitesController < ApplicationController notice << "or create an account" if Gitlab::CurrentSettings.allow_signup? notice = notice.join(' ') + "." + initial_member = Member.find_by_invite_token(params[:id]) + redirect_params = initial_member ? { invite_email: member.invite_email } : {} + store_location_for :user, request.fullpath - redirect_to new_user_session_path(invite_email: member.invite_email), notice: notice + + redirect_to new_user_session_path(redirect_params), notice: notice end def invite_details diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index a6986029f0d..78161a3b446 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -177,10 +177,6 @@ module Issuable assignees.count > 1 end - def supports_weight? - false - end - def supports_time_tracking? is_a?(TimeTrackable) && !incident? end diff --git a/app/models/member.rb b/app/models/member.rb index 1913df61614..55bb78b7f94 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -161,8 +161,8 @@ class Member < ApplicationRecord where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h end - def find_by_invite_token(invite_token) - invite_token = Devise.token_generator.digest(self, :invite_token, invite_token) + def find_by_invite_token(raw_invite_token) + invite_token = Devise.token_generator.digest(self, :invite_token, raw_invite_token) find_by(invite_token: invite_token) end diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb index d9e8326f159..53a04e5a398 100644 --- a/app/services/snippets/base_service.rb +++ b/app/services/snippets/base_service.rb @@ -46,7 +46,7 @@ module Snippets snippet.errors.add(:snippet_actions, 'have invalid data') end - snippet_error_response(snippet, 403) + snippet_error_response(snippet, 422) end def snippet_error_response(snippet, http_status) diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index cd24c30e46f..554cb4323f7 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -2,4 +2,4 @@ - breadcrumb_title _("Folder/%{name}") % { name: @folder } - page_title _("Environments in %{name}") % { name: @folder } -#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data } } +#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data, project_path: @project.full_path } } diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index 445196ed449..9abc1a5a925 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -5,4 +5,5 @@ "can-create-environment" => can?(current_user, :create_environment, @project).to_s, "new-environment-path" => new_project_environment_path(@project), "help-page-path" => help_page_path("ci/environments/index.md"), - "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards") } } + "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards"), + "project-path" => @project.full_path } } diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml index 82e435fe0d3..79e6f043b64 100644 --- a/app/views/shared/issuable/form/_metadata.html.haml +++ b/app/views/shared/issuable/form/_metadata.html.haml @@ -30,7 +30,7 @@ = render_if_exists "shared/issuable/form/merge_request_blocks", issuable: issuable, form: form - - if has_due_date || issuable.supports_weight? + - if has_due_date .col-lg-6 - if @issue[:issue_type] != 'incident' = render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form |