Commit ca6cef2e authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '299902-remove-jquery-reference-from-stage-vue' into 'master'

Implement mini graph pipeline to use gl-dropdown [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!52821
parents 6acc8ef6 85f7fb65
......@@ -11,11 +11,11 @@
* 3. Merge request widget
* 4. Commit widget
*/
import $ from 'jquery';
import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import axios from '~/lib/utils/axios_utils';
import eventHub from '../../event_hub';
import JobItem from '../graph/job_item.vue';
......@@ -24,14 +24,14 @@ import { PIPELINES_TABLE } from '../../constants';
export default {
components: {
GlIcon,
JobItem,
GlLoadingIcon,
GlDropdown,
JobItem,
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagsMixin()],
props: {
stage: {
type: Object,
......@@ -50,30 +50,25 @@ export default {
default: '',
},
},
data() {
return {
isLoading: false,
dropdownContent: '',
dropdownContent: [],
};
},
computed: {
dropdownClass() {
return this.dropdownContent.length > 0
? 'js-builds-dropdown-container'
: 'js-builds-dropdown-loading';
isCiMiniPipelineGlDropdown() {
// Feature flag ci_mini_pipeline_gl_dropdown
// See more at https://gitlab.com/gitlab-org/gitlab/-/issues/300400
return this.glFeatures?.ciMiniPipelineGlDropdown;
},
triggerButtonClass() {
return `ci-status-icon-${this.stage.status.group}`;
},
borderlessIcon() {
return `${this.stage.status.icon}_borderless`;
},
},
watch: {
updateDropdown() {
if (this.updateDropdown && this.isDropdownOpen() && !this.isLoading) {
......@@ -81,14 +76,17 @@ export default {
}
},
},
updated() {
if (this.dropdownContent.length > 0) {
if (!this.isCiMiniPipelineGlDropdown && this.dropdownContent.length) {
this.stopDropdownClickPropagation();
}
},
methods: {
onShowDropdown() {
eventHub.$emit('clickedDropdown');
this.isLoading = true;
this.fetchJobs();
},
onClickStage() {
if (!this.isDropdownOpen()) {
eventHub.$emit('clickedDropdown');
......@@ -96,7 +94,6 @@ export default {
this.fetchJobs();
}
},
fetchJobs() {
axios
.get(this.stage.dropdown_path)
......@@ -105,13 +102,16 @@ export default {
this.isLoading = false;
})
.catch(() => {
this.closeDropdown();
if (this.isCiMiniPipelineGlDropdown) {
this.$refs.stageGlDropdown.hide();
} else {
this.closeDropdown();
}
this.isLoading = false;
Flash(__('Something went wrong on our end.'));
});
},
/**
* When the user right clicks or cmd/ctrl + click in the job name
* the dropdown should not be closed and the link should open in another tab,
......@@ -119,6 +119,8 @@ export default {
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
*
* Note: This should be removed once ci_mini_pipeline_gl_dropdown FF is removed as true.
*/
stopDropdownClickPropagation() {
$(
......@@ -128,23 +130,24 @@ export default {
e.stopPropagation();
});
},
closeDropdown() {
if (this.isDropdownOpen()) {
$(this.$refs.dropdown).dropdown('toggle');
}
},
isDropdownOpen() {
return this.$el.classList.contains('show');
},
pipelineActionRequestComplete() {
if (this.type === PIPELINES_TABLE) {
// warn the table to update
eventHub.$emit('refreshPipelinesTable');
return;
}
// close the dropdown in mr widget
if (this.isCiMiniPipelineGlDropdown) {
this.$refs.stageGlDropdown.hide();
} else {
// close the dropdown in mr widget
$(this.$refs.dropdown).dropdown('toggle');
}
},
......@@ -154,32 +157,30 @@ export default {
<template>
<div class="dropdown">
<button
id="stageDropdown"
ref="dropdown"
<gl-dropdown
v-if="isCiMiniPipelineGlDropdown"
ref="stageGlDropdown"
v-gl-tooltip.hover
:class="triggerButtonClass"
data-testid="mini-pipeline-graph-dropdown"
:title="stage.title"
class="mini-pipeline-graph-dropdown-toggle"
data-testid="mini-pipeline-graph-dropdown-toggle"
data-toggle="dropdown"
data-display="static"
type="button"
aria-haspopup="true"
aria-expanded="false"
@click="onClickStage"
>
<span :aria-label="stage.title" aria-hidden="true" class="gl-pointer-events-none">
<gl-icon :name="borderlessIcon" />
</span>
</button>
<div
class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
aria-labelledby="stageDropdown"
variant="link"
:lazy="true"
:popper-opts="{ placement: 'bottom' }"
:toggle-class="['mini-pipeline-graph-gl-dropdown-toggle', triggerButtonClass]"
menu-class="mini-pipeline-graph-dropdown-menu"
@show="onShowDropdown"
>
<template #button-content>
<span class="gl-pointer-events-none">
<gl-icon :name="borderlessIcon" />
</span>
</template>
<gl-loading-icon v-if="isLoading" />
<ul v-else class="js-builds-dropdown-list scrollable-menu">
<ul
v-else
class="js-builds-dropdown-list scrollable-menu"
data-testid="mini-pipeline-graph-dropdown-menu-list"
>
<li v-for="job in dropdownContent" :key="job.id">
<job-item
:dropdown-length="dropdownContent.length"
......@@ -189,6 +190,45 @@ export default {
/>
</li>
</ul>
</div>
</gl-dropdown>
<template v-else>
<button
id="stageDropdown"
ref="dropdown"
v-gl-tooltip.hover
:class="triggerButtonClass"
:title="stage.title"
class="mini-pipeline-graph-dropdown-toggle"
data-testid="mini-pipeline-graph-dropdown-toggle"
data-toggle="dropdown"
data-display="static"
type="button"
aria-haspopup="true"
aria-expanded="false"
@click="onClickStage"
>
<span :aria-label="stage.title" aria-hidden="true" class="gl-pointer-events-none">
<gl-icon :name="borderlessIcon" />
</span>
</button>
<div
class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
aria-labelledby="stageDropdown"
>
<gl-loading-icon v-if="isLoading" />
<ul v-else class="js-builds-dropdown-list scrollable-menu">
<li v-for="job in dropdownContent" :key="job.id">
<job-item
:dropdown-length="dropdownContent.length"
:job="job"
css-class-job-name="mini-pipeline-graph-dropdown-item"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</li>
</ul>
</div>
</template>
</div>
</template>
......@@ -67,7 +67,8 @@
// Mini Pipelines
.stage-cell {
.mini-pipeline-graph-dropdown-toggle {
.mini-pipeline-graph-dropdown-toggle,
.mini-pipeline-graph-gl-dropdown-toggle {
svg {
height: $ci-action-icon-size;
width: $ci-action-icon-size;
......@@ -138,7 +139,13 @@
}
// Dropdown button in mini pipeline graph
button.mini-pipeline-graph-dropdown-toggle {
button.mini-pipeline-graph-dropdown-toggle,
// As the `mini-pipeline-item` mixin specificity is lower
// than the toggle of dropdown with 'variant="link"' we add
// classes ".gl-button.btn-link" to make it more specific.
// Once FF ci_mini_pipeline_gl_dropdown is removed, the `mini-pipeline-item`
// itself could increase its specificity to simplify this selector
button.gl-button.btn-link.mini-pipeline-graph-gl-dropdown-toggle {
@include mini-pipeline-item();
}
......
......@@ -18,6 +18,9 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
before_action only: [:pipelines] do
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
end
BRANCH_SEARCH_LIMIT = 1000
......
......@@ -45,6 +45,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:suggestions_custom_commit, @project)
push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml)
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
......
......@@ -16,6 +16,7 @@ class Projects::PipelinesController < Projects::ApplicationController
push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true)
push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, project, type: :development, default_enabled: :yaml)
end
before_action :ensure_pipeline, only: [:show]
before_action :push_experiment_to_gon, only: :index, if: :html_request?
......
---
name: ci_mini_pipeline_gl_dropdown
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52821
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300400
milestone: '13.9'
type: development
group: group::continuous integration
default_enabled: false
......@@ -18,6 +18,7 @@ RSpec.describe 'User adds a merge request to a merge train', :js do
before do
stub_feature_flags(disable_merge_trains: false)
stub_feature_flags(ci_mini_pipeline_gl_dropdown: false)
stub_licensed_features(merge_pipelines: true, merge_trains: true)
project.add_maintainer(user)
project.update!(merge_pipelines_enabled: true, merge_trains_enabled: true)
......
......@@ -518,58 +518,75 @@ RSpec.describe 'Pipelines', :js do
end
end
context 'mini pipeline graph' do
let!(:build) do
create(:ci_build, :pending, pipeline: pipeline,
stage: 'build',
name: 'build')
end
shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled|
context 'mini pipeline graph' do
let!(:build) do
create(:ci_build, :pending, pipeline: pipeline,
stage: 'build',
name: 'build')
end
dropdown_toggle_selector = '[data-testid="mini-pipeline-graph-dropdown-toggle"]'
before do
stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled)
visit_project_pipelines
end
before do
visit_project_pipelines
end
let_it_be(:dropdown_toggle_selector) do
if ci_mini_pipeline_gl_dropdown_enabled
'[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle'
else
'[data-testid="mini-pipeline-graph-dropdown-toggle"]'
end
end
it 'renders a mini pipeline graph' do
expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
expect(page).to have_selector(dropdown_toggle_selector)
end
it 'renders a mini pipeline graph' do
expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
expect(page).to have_selector(dropdown_toggle_selector)
end
context 'when clicking a stage badge' do
it 'opens a dropdown' do
find(dropdown_toggle_selector).click
context 'when clicking a stage badge' do
it 'opens a dropdown' do
find(dropdown_toggle_selector).click
expect(page).to have_link build.name
end
expect(page).to have_link build.name
end
it 'is possible to cancel pending build' do
find(dropdown_toggle_selector).click
find('.js-ci-action').click
wait_for_requests
it 'is possible to cancel pending build' do
find(dropdown_toggle_selector).click
find('.js-ci-action').click
wait_for_requests
expect(build.reload).to be_canceled
expect(build.reload).to be_canceled
end
end
end
context 'for a failed pipeline' do
let!(:build) do
create(:ci_build, :failed, pipeline: pipeline,
stage: 'build',
name: 'build')
end
context 'for a failed pipeline' do
let!(:build) do
create(:ci_build, :failed, pipeline: pipeline,
stage: 'build',
name: 'build')
end
it 'displays the failure reason' do
find(dropdown_toggle_selector).click
it 'displays the failure reason' do
find(dropdown_toggle_selector).click
within('.js-builds-dropdown-list') do
build_element = page.find('.mini-pipeline-graph-dropdown-item')
expect(build_element['title']).to eq('build - failed - (unknown failure)')
within('.js-builds-dropdown-list') do
build_element = page.find('.mini-pipeline-graph-dropdown-item')
expect(build_element['title']).to eq('build - failed - (unknown failure)')
end
end
end
end
end
context 'with ci_mini_pipeline_gl_dropdown disabled' do
it_behaves_like "mini pipeline renders", false
end
context 'with ci_mini_pipeline_gl_dropdown enabled' do
it_behaves_like "mini pipeline renders", true
end
context 'with pagination' do
before do
allow(Ci::Pipeline).to receive(:default_per_page).and_return(1)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment