Commit 00014f65 authored by Simon Knox's avatar Simon Knox Committed by Ezekiel Kigbo

Add burnup charts to Iterations report

Allow passing either milestone to iteration to query
parent 58827738
......@@ -35,6 +35,11 @@ export default {
required: false,
default: '',
},
iterationId: {
type: String,
required: false,
default: '',
},
burndownEventsPath: {
type: String,
required: false,
......@@ -49,16 +54,17 @@ export default {
apollo: {
burnupData: {
skip() {
return !this.glFeatures.burnupCharts || !this.milestoneId;
return !this.glFeatures.burnupCharts || (!this.milestoneId && !this.iterationId);
},
query: BurnupQuery,
variables() {
return {
milestoneId: this.milestoneId,
id: this.iterationId || this.milestoneId,
isIteration: Boolean(this.iterationId),
};
},
update(data) {
const sparseBurnupData = data?.milestone?.burnupTimeSeries || [];
const sparseBurnupData = data?.[this.parent]?.burnupTimeSeries || [];
return this.padSparseBurnupData(sparseBurnupData);
},
......@@ -79,6 +85,9 @@ export default {
};
},
computed: {
parent() {
return this.iterationId ? 'iteration' : 'milestone';
},
title() {
return this.glFeatures.burnupCharts ? __('Charts') : __('Burndown chart');
},
......
query IterationBurnupTimesSeriesData($milestoneId: MilestoneID!) {
milestone(id: $milestoneId) {
query IterationBurnupTimesSeriesData($id: ID!, $isIteration: Boolean = false) {
milestone(id: $id) @skip(if: $isIteration) {
title
id
burnupTimeSeries {
date
scopeCount
scopeWeight
completedCount
completedWeight
}
}
iteration(id: $id) @include(if: $isIteration) {
title
id
burnupTimeSeries {
......
......@@ -9,7 +9,9 @@ import {
GlDropdown,
GlDropdownItem,
} from '@gitlab/ui';
import BurnCharts from 'ee/burndown_chart/components/burn_charts.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __ } from '~/locale';
import IterationReportSummary from './iteration_report_summary.vue';
import IterationForm from './iteration_form.vue';
......@@ -30,6 +32,7 @@ const page = {
export default {
components: {
BurnCharts,
GlAlert,
GlBadge,
GlLoadingIcon,
......@@ -61,6 +64,7 @@ export default {
},
},
},
mixins: [glFeatureFlagsMixin()],
props: {
fullPath: {
type: String,
......@@ -215,6 +219,12 @@ export default {
:iteration-id="iteration.id"
:namespace-type="namespaceType"
/>
<burn-charts
v-if="glFeatures.burnupCharts"
:start-date="iteration.startDate"
:due-date="iteration.dueDate"
:iteration-id="iteration.id"
/>
<iteration-report-tabs
:full-path="fullPath"
:iteration-id="iteration.id"
......
......@@ -4,6 +4,9 @@ class Groups::IterationsController < Groups::ApplicationController
before_action :check_iterations_available!
before_action :authorize_show_iteration!, only: [:index, :show]
before_action :authorize_create_iteration!, only: [:new, :edit]
before_action do
push_frontend_feature_flag(:burnup_charts, group)
end
feature_category :issue_tracking
......
......@@ -3,6 +3,9 @@
class Projects::Iterations::InheritedController < Projects::ApplicationController
before_action :check_iterations_available!
before_action :authorize_show_iteration!
before_action do
push_frontend_feature_flag(:burnup_charts, project)
end
feature_category :issue_tracking
......
......@@ -3,6 +3,9 @@
class Projects::IterationsController < Projects::ApplicationController
before_action :check_iterations_available!
before_action :authorize_show_iteration!
before_action do
push_frontend_feature_flag(:burnup_charts, project)
end
feature_category :issue_tracking
......
......@@ -10,7 +10,7 @@ RSpec.describe 'User views iteration' do
let_it_be(:sub_project) { create(:project, group: sub_group) }
let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user }
let_it_be(:guest_user) { create(:group_member, :guest, user: create(:user), group: group).user }
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iid: 1, id: 2, group: group, title: 'Correct Iteration', start_date: now - 1.day, due_date: now) }
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iid: 1, id: 2, group: group, title: 'Correct Iteration', description: 'iteration description', start_date: now - 1.day, due_date: now) }
let_it_be(:other_iteration) { create(:iteration, :skip_future_date_validation, iid: 2, id: 1, group: group, title: 'Wrong Iteration', start_date: now - 4.days, due_date: now - 3.days) }
let_it_be(:sub_group_iteration) { create(:iteration, id: 3, group: sub_group) }
let_it_be(:issue) { create(:issue, project: project, iteration: iteration) }
......@@ -20,60 +20,64 @@ RSpec.describe 'User views iteration' do
let_it_be(:other_issue) { create(:issue, project: project, iteration: other_iteration) }
context 'with license', :js do
context 'view an iteration' do
before do
stub_licensed_features(iterations: true)
end
shared_examples 'shows iteration info' do
before do
stub_licensed_features(iterations: true)
sign_in(user)
sign_in(current_user)
visit group_iteration_path(iteration.group, iteration.iid)
end
it 'shows iteration info and dates' do
expect(page).to have_content(iteration.title)
expect(page).to have_content(iteration.description)
expect(page).to have_content(iteration.start_date.strftime('%b %-d, %Y'))
expect(page).to have_content(iteration.due_date.strftime('%b %-d, %Y'))
end
it 'shows correct summary information' do
expect(page).to have_content("Complete 25%")
expect(page).to have_content("Open 2")
expect(page).to have_content("In progress 1")
expect(page).to have_content("Completed 1")
end
it 'shows all issues within the group' do
expect(page).to have_content(issue.title)
expect(page).to have_content(assigned_issue.title)
expect(page).to have_content(closed_issue.title)
expect(page).to have_content(sub_group_issue.title)
expect(page).not_to have_content(other_issue.title)
it 'shows iteration info' do
aggregate_failures 'expect title, description, and dates' do
expect(page).to have_content(iteration.title)
expect(page).to have_content(iteration.description)
expect(page).to have_content(iteration.start_date.strftime('%b %-d, %Y'))
expect(page).to have_content(iteration.due_date.strftime('%b %-d, %Y'))
end
aggregate_failures 'expect summary information' do
expect(page).to have_content("Complete 25%")
expect(page).to have_content("Open 2")
expect(page).to have_content("In progress 1")
expect(page).to have_content("Completed 1")
end
aggregate_failures 'expect burnup and burndown charts' do
expect(page).to have_content('Burndown chart')
expect(page).to have_content('Burnup chart')
end
aggregate_failures 'expect list of assigned issues' do
expect(page).to have_content(issue.title)
expect(page).to have_content(assigned_issue.title)
expect(page).to have_content(closed_issue.title)
expect(page).to have_content(sub_group_issue.title)
expect(page).not_to have_content(other_issue.title)
end
if shows_actions
expect(page).to have_button('Actions')
else
expect(page).not_to have_button('Actions')
end
end
end
context 'when user has edit permissions' do
before do
stub_licensed_features(iterations: true)
sign_in(user)
visit group_iteration_path(iteration.group, iteration.iid)
end
it 'shows action dropdown for editing the iteration' do
expect(page).to have_button('Actions')
it_behaves_like 'shows iteration info' do
let(:current_user) { user }
let(:shows_actions) { true }
end
end
context 'when user does not have edit permissions' do
before do
stub_licensed_features(iterations: true)
sign_in(guest_user)
visit group_iteration_path(iteration.group, iteration.iid)
end
it 'hides action dropdown for editing the iteration' do
expect(page).not_to have_button('Actions')
it_behaves_like 'shows iteration info' do
let(:current_user) { guest_user }
let(:shows_actions) { false }
end
end
end
......
......@@ -26,29 +26,36 @@ RSpec.describe 'User views iteration' do
visit project_iterations_inherited_path(project, iteration.id)
end
it 'shows iteration info and dates' do
expect(page).to have_content(iteration.title)
expect(page).to have_content(iteration.description)
expect(page).to have_content(iteration.start_date.strftime('%b %-d, %Y'))
expect(page).to have_content(iteration.due_date.strftime('%b %-d, %Y'))
end
it 'shows iteration info' do
aggregate_failures 'shows iteration info and dates' do
expect(page).to have_content(iteration.title)
expect(page).to have_content(iteration.description)
expect(page).to have_content(iteration.start_date.strftime('%b %-d, %Y'))
expect(page).to have_content(iteration.due_date.strftime('%b %-d, %Y'))
end
it 'shows correct summary information' do
expect(page).to have_content("Complete 50%")
expect(page).to have_content("Open 1")
expect(page).to have_content("In progress 0")
expect(page).to have_content("Completed 1")
end
aggregate_failures 'shows correct summary information' do
expect(page).to have_content("Complete 50%")
expect(page).to have_content("Open 1")
expect(page).to have_content("In progress 0")
expect(page).to have_content("Completed 1")
end
it 'shows only issues that are part of the project' do
expect(page).to have_content(issue.title)
expect(page).not_to have_content(assigned_issue.title)
expect(page).to have_content(closed_issue.title)
expect(page).not_to have_content(other_issue.title)
end
aggregate_failures 'expect burnup and burndown charts' do
expect(page).to have_content('Burndown chart')
expect(page).to have_content('Burnup chart')
end
aggregate_failures 'shows only issues that are part of the project' do
expect(page).to have_content(issue.title)
expect(page).not_to have_content(assigned_issue.title)
expect(page).to have_content(closed_issue.title)
expect(page).not_to have_content(other_issue.title)
end
it 'hides action dropdown for editing the iteration' do
expect(page).not_to have_button('Actions')
aggregate_failures 'hides action dropdown for editing the iteration' do
expect(page).not_to have_button('Actions')
end
end
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