Commit b4141ba1 authored by Ash McKenzie's avatar Ash McKenzie

Merge branch 'psi-burndown-tidier-toggle' into 'master'

Hide burndown toggle switch for new milestones

See merge request gitlab-org/gitlab!42656
parents bd43c466 dd6417ee
...@@ -40,6 +40,11 @@ export default { ...@@ -40,6 +40,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
showNewOldBurndownToggle: {
type: Boolean,
required: false,
default: false,
},
}, },
apollo: { apollo: {
burnupData: { burnupData: {
...@@ -69,7 +74,7 @@ export default { ...@@ -69,7 +74,7 @@ export default {
issuesSelected: true, issuesSelected: true,
burnupData: [], burnupData: [],
useLegacyBurndown: !this.glFeatures.burnupCharts, useLegacyBurndown: !this.glFeatures.burnupCharts,
showInfo: true, showInfo: this.showNewOldBurndownToggle,
error: '', error: '',
}; };
}, },
...@@ -258,7 +263,7 @@ export default { ...@@ -258,7 +263,7 @@ export default {
</gl-button> </gl-button>
</gl-button-group> </gl-button-group>
<gl-button-group v-if="glFeatures.burnupCharts"> <gl-button-group v-if="glFeatures.burnupCharts && showNewOldBurndownToggle">
<gl-button <gl-button
ref="oldBurndown" ref="oldBurndown"
:category="useLegacyBurndown ? 'primary' : 'secondary'" :category="useLegacyBurndown ? 'primary' : 'secondary'"
......
...@@ -29,6 +29,7 @@ export default () => { ...@@ -29,6 +29,7 @@ export default () => {
const dueDate = $chartEl.data('dueDate'); const dueDate = $chartEl.data('dueDate');
const milestoneId = $chartEl.data('milestoneId'); const milestoneId = $chartEl.data('milestoneId');
const burndownEventsPath = $chartEl.data('burndownEventsPath'); const burndownEventsPath = $chartEl.data('burndownEventsPath');
const isLegacy = $chartEl.data('isLegacy');
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
...@@ -41,6 +42,7 @@ export default () => { ...@@ -41,6 +42,7 @@ export default () => {
render(createElement) { render(createElement) {
return createElement('burn-charts', { return createElement('burn-charts', {
props: { props: {
showNewOldBurndownToggle: isLegacy,
burndownEventsPath, burndownEventsPath,
startDate, startDate,
dueDate, dueDate,
......
...@@ -19,28 +19,9 @@ module EE ...@@ -19,28 +19,9 @@ module EE
milestone.is_a?(EE::Milestone) && !milestone.supports_milestone_charts? && show_promotions? milestone.is_a?(EE::Milestone) && !milestone.supports_milestone_charts? && show_promotions?
end end
def show_burndown_placeholder?(milestone, warning) def show_burndown_placeholder?(milestone)
return false if cookies['hide_burndown_message'].present? milestone.supports_milestone_charts? &&
return false unless milestone.supports_milestone_charts? can?(current_user, :admin_milestone, milestone.resource_parent)
warning.nil? && can?(current_user, :admin_milestone, milestone.resource_parent)
end
def data_warning_for(burndown)
return unless burndown
message =
if burndown.empty?
"The burndown chart can’t be shown, as all issues assigned to this milestone were closed on an older GitLab version before data was recorded. "
elsif !burndown.accurate?
"Some issues can’t be shown in the burndown chart, as they were closed on an older GitLab version before data was recorded. "
end
if message
link = link_to "About burndown charts", help_page_path('user/project/milestones/burndown_charts.md'), class: 'burndown-docs-link'
content_tag(:div, (message + link).html_safe, id: "data-warning", class: "settings-message prepend-top-20")
end
end end
def milestone_weight_tooltip_text(weight) def milestone_weight_tooltip_text(weight)
...@@ -50,5 +31,13 @@ module EE ...@@ -50,5 +31,13 @@ module EE
_("Weight %{weight}") % { weight: weight } _("Weight %{weight}") % { weight: weight }
end end
end end
def first_resource_state_event
strong_memoize(:first_resource_state_event) { ::ResourceStateEvent.first }
end
def legacy_milestone?(milestone)
first_resource_state_event && milestone.created_at < first_resource_state_event.created_at
end
end end
end end
- milestone = local_assigns[:milestone] - milestone = local_assigns[:milestone]
- burndown = burndown_chart(milestone) - burndown = burndown_chart(milestone)
- warning = data_warning_for(burndown)
- burndown_endpoint = milestone.group_milestone? ? api_v4_groups_milestones_burndown_events_path(id: milestone.group.id, milestone_id: milestone.id) : api_v4_projects_milestones_burndown_events_path(id: milestone.project.id, milestone_id: milestone.timebox_id) - burndown_endpoint = milestone.group_milestone? ? api_v4_groups_milestones_burndown_events_path(id: milestone.group.id, milestone_id: milestone.id) : api_v4_projects_milestones_burndown_events_path(id: milestone.project.id, milestone_id: milestone.timebox_id)
= warning
- if can_generate_chart?(milestone, burndown) - if can_generate_chart?(milestone, burndown)
.burndown-chart.mb-2{ data: { start_date: burndown.start_date.strftime("%Y-%m-%d"), .burndown-chart.mb-2{ data: { start_date: burndown.start_date.strftime("%Y-%m-%d"),
due_date: burndown.due_date.strftime("%Y-%m-%d"), due_date: burndown.due_date.strftime("%Y-%m-%d"),
milestone_id: milestone.to_global_id, milestone_id: milestone.to_global_id,
is_legacy: legacy_milestone?(milestone),
burndown_events_path: expose_url(burndown_endpoint) } } burndown_events_path: expose_url(burndown_endpoint) } }
- elsif show_burndown_placeholder?(milestone, warning) - elsif show_burndown_placeholder?(milestone)
.burndown-hint.content-block.container-fluid .burndown-hint.content-block.container-fluid
= sprite_icon('close', size: 16, css_class: 'dismiss-icon') = sprite_icon('close', size: 16, css_class: 'dismiss-icon')
.row .row
......
...@@ -42,47 +42,6 @@ RSpec.describe 'Milestones on EE' do ...@@ -42,47 +42,6 @@ RSpec.describe 'Milestones on EE' do
end end
end end
context 'when a closed issue do not have closed events' do
it 'shows warning' do
close_issue(create(:issue, issue_params))
close_issue(create(:issue, issue_params))
# Legacy issue: No closed events being created
create(:closed_issue, issue_params)
visit_milestone
expect(page).to have_selector('#data-warning', count: 1)
expect(page.find('#data-warning').text).to include("Some issues can’t be shown in the burndown chart")
expect(page).to have_selector('.burndown-chart')
end
end
context 'when all closed issues do not have closed events' do
it 'shows warning and hides burndown' do
create(:closed_issue, issue_params)
create(:closed_issue, issue_params)
visit_milestone
expect(page).to have_selector('#data-warning', count: 1)
expect(page.find('#data-warning').text).to include("The burndown chart can’t be shown")
expect(page).not_to have_selector('.burndown-chart')
end
end
context 'data is accurate' do
it 'does not show warning' do
create(:issue, issue_params)
close_issue(create(:issue, issue_params))
visit_milestone
expect(page).not_to have_selector('#data-warning')
expect(page).to have_selector('.burndown-chart')
end
end
context 'with due & start date not set' do context 'with due & start date not set' do
let(:milestone_without_dates) { create(:milestone, project: project) } let(:milestone_without_dates) { create(:milestone, project: project) }
......
...@@ -184,11 +184,6 @@ describe('burndown_chart', () => { ...@@ -184,11 +184,6 @@ describe('burndown_chart', () => {
expect(findBurnupChart().props('issuesSelected')).toBe(false); expect(findBurnupChart().props('issuesSelected')).toBe(false);
}); });
it('shows old/new burndown buttons', () => {
expect(findOldBurndownChartButton().exists()).toBe(true);
expect(findNewBurndownChartButton().exists()).toBe(true);
});
it('uses burndown data computed from burnup data', () => { it('uses burndown data computed from burnup data', () => {
createComponent({ createComponent({
data: { data: {
...@@ -204,15 +199,37 @@ describe('burndown_chart', () => { ...@@ -204,15 +199,37 @@ describe('burndown_chart', () => {
expect(openIssuesCount).toEqual([expectedCount]); expect(openIssuesCount).toEqual([expectedCount]);
expect(openIssuesWeight).toEqual([expectedWeight]); expect(openIssuesWeight).toEqual([expectedWeight]);
}); });
});
describe('showNewOldBurndownToggle', () => {
it('hides old/new burndown buttons if feature disabled', () => {
createComponent({ featureEnabled: false, props: { showNewOldBurndownToggle: true } });
expect(findOldBurndownChartButton().exists()).toBe(false);
expect(findNewBurndownChartButton().exists()).toBe(false);
});
it('hides old/new burndown buttons if props is false', () => {
createComponent({ featureEnabled: true, props: { showNewOldBurndownToggle: false } });
expect(findOldBurndownChartButton().exists()).toBe(false);
expect(findNewBurndownChartButton().exists()).toBe(false);
});
it('shows old/new burndown buttons if prop true', () => {
createComponent({ featureEnabled: true, props: { showNewOldBurndownToggle: true } });
expect(findOldBurndownChartButton().exists()).toBe(true);
expect(findNewBurndownChartButton().exists()).toBe(true);
});
it('calls fetchLegacyBurndownEvents, but only once', () => { it('calls fetchLegacyBurndownEvents, but only once', () => {
createComponent({ featureEnabled: true, props: { showNewOldBurndownToggle: true } });
jest.spyOn(wrapper.vm, 'fetchLegacyBurndownEvents'); jest.spyOn(wrapper.vm, 'fetchLegacyBurndownEvents');
mock.onGet(defaultProps.burndownEventsPath).reply(200, []); mock.onGet(defaultProps.burndownEventsPath).reply(200, []);
findOldBurndownChartButton().vm.$emit('click'); findOldBurndownChartButton().vm.$emit('click');
findOldBurndownChartButton().vm.$emit('click');
expect(wrapper.vm.fetchLegacyBurndownEvents).toHaveBeenCalledTimes(1); expect(wrapper.vm.fetchLegacyBurndownEvents).toHaveBeenCalledTimes(1);
}); });
}); });
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe TimeboxesHelper do
describe '#show_burndown_placeholder?' do
let_it_be(:user) { build(:user) }
subject { helper.show_burndown_placeholder?(milestone) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
describe('milestone does not support burndown charts') do
let(:milestone) { double('Milestone', supports_milestone_charts?: false) }
it { is_expected.to be false }
end
describe('user without permission') do
let(:milestone) { double('Milestone', supports_milestone_charts?: true, resource_parent: 'board') }
before do
stub_can_admin_milestone(false)
end
it { is_expected.to be false }
end
describe('user with permission') do
let(:milestone) { double('Milestone', supports_milestone_charts?: true, resource_parent: 'board') }
before do
stub_can_admin_milestone(true)
end
it { is_expected.to be true }
end
end
describe '#legacy_milestone?' do
subject { legacy_milestone?(milestone) }
describe 'without any ResourceStateEvents' do
let(:milestone) { double('Milestone', created_at: Date.current) }
it { is_expected.to be_nil }
end
describe 'with ResourceStateEvent created before milestone' do
let(:milestone) { double('Milestone', created_at: Date.current) }
before do
create_resource_state_event(Date.yesterday)
end
it { is_expected.to eq(false) }
end
describe 'with ResourceStateEvent created same day as milestone' do
let(:milestone) { double('Milestone', created_at: Date.current) }
before do
create_resource_state_event
end
it { is_expected.to eq(false) }
end
describe 'with ResourceStateEvent created after milestone' do
let(:milestone) { double('Milestone', created_at: Date.yesterday) }
before do
create_resource_state_event
end
it { is_expected.to eq(true) }
end
end
def create_resource_state_event(created_at = Date.current)
create(:resource_state_event, created_at: created_at)
end
def stub_can_admin_milestone(ability)
allow(helper).to receive(:can?).with(user, :admin_milestone, milestone.resource_parent).and_return(ability)
end
end
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