Commit 5d573fa1 authored by Simon Knox's avatar Simon Knox Committed by Kushal Pandya

Add basic iteration report view

Filtering iterations by ID, and display just info
No edit view for now
parent 661d1ff7
......@@ -10,6 +10,7 @@ import {
} from '@gitlab/ui';
import { formatDate } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
import IterationReportSummary from './iteration_report_summary.vue';
import IterationForm from './iteration_form.vue';
import IterationReportTabs from './iteration_report_tabs.vue';
import query from '../queries/group_iteration.query.graphql';
......@@ -30,6 +31,7 @@ export default {
GlNewDropdown,
GlNewDropdownItem,
IterationForm,
IterationReportSummary,
IterationReportTabs,
},
apollo: {
......@@ -156,6 +158,7 @@ export default {
</div>
<h3 ref="title" class="page-title">{{ iteration.title }}</h3>
<div ref="description" v-html="iteration.description"></div>
<iteration-report-summary :group-path="groupPath" :iteration-id="iteration.id" />
<iteration-report-tabs :group-path="groupPath" :iteration-id="iteration.id" />
</template>
</div>
......
<script>
import { GlCard, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import query from '../queries/iteration_issues_summary.query.graphql';
export default {
cardBodyClass: 'gl-text-center gl-py-3',
cardClass: 'gl-bg-gray-10 gl-border-0',
components: {
GlCard,
GlIcon,
},
apollo: {
issues: {
query,
variables() {
return this.queryVariables;
},
update(data) {
return {
open: data?.group?.openIssues?.count || 0,
assigned: data?.group?.assignedIssues?.count || 0,
closed: data?.group?.closedIssues?.count || 0,
};
},
error() {
this.error = __('Error loading issues');
},
},
},
props: {
groupPath: {
type: String,
required: true,
},
iterationId: {
type: String,
required: true,
},
},
data() {
return {
issues: {},
};
},
computed: {
queryVariables() {
return {
groupPath: this.groupPath,
id: getIdFromGraphQLId(this.iterationId),
};
},
completedPercent() {
const open = this.issues.open + this.issues.assigned;
const { closed } = this.issues;
if (closed <= 0) {
return 0;
}
return ((closed / (open + closed)) * 100).toFixed(0);
},
showCards() {
return !this.$apollo.queries.issues.loading && Object.values(this.issues).every(a => a >= 0);
},
columns() {
return [
{
title: __('Complete'),
value: `${this.completedPercent}%`,
},
{
title: __('Open'),
value: this.issues.open,
icon: true,
},
{
title: __('In progress'),
value: this.issues.assigned,
icon: true,
},
{
title: __('Completed'),
value: this.issues.closed,
icon: true,
},
];
},
},
};
</script>
<template>
<div v-if="showCards" class="row gl-mt-6">
<div v-for="(column, index) in columns" :key="index" class="col-sm-3">
<gl-card :class="$options.cardClass" :body-class="$options.cardBodyClass">
<span>{{ column.title }}</span>
<span class="gl-font-size-h2 gl-font-weight-bold">{{ column.value }}</span>
<gl-icon v-if="column.icon" name="issues" :size="12" class="gl-text-gray-700" />
</gl-card>
</div>
</div>
</template>
......@@ -181,7 +181,7 @@ export default {
v-else
:items="issues.list"
:fields="$options.fields"
:empty-text="__('No iterations found')"
:empty-text="__('No issues found')"
:show-empty="true"
fixed
stacked="sm"
......
query GroupIteration($groupPath: ID!, $id: ID!) {
group(fullPath: $groupPath) {
openIssues: issues(iterationId: [$id], state: opened, assigneeId: "none") {
count
}
assignedIssues: issues(iterationId: [$id], state: opened, assigneeId: "any") {
count
}
closedIssues: issues(iterationId: [$id], state: closed) {
count
}
}
}
......@@ -51,7 +51,7 @@ describe('Iterations report tabs', () => {
expect(wrapper.contains(GlLoadingIcon)).toBe(false);
expect(wrapper.contains(GlTable)).toBe(true);
expect(wrapper.text()).toContain('No iterations found');
expect(wrapper.text()).toContain('No issues found');
});
it('shows error in a gl-alert', () => {
......
import IterationReportSummary from 'ee/iterations/components/iteration_report_summary.vue';
import { mount } from '@vue/test-utils';
import { GlCard } from '@gitlab/ui';
describe('Iterations report tabs', () => {
let wrapper;
const id = 3;
const groupPath = 'gitlab-org';
const defaultProps = {
groupPath,
iterationId: `gid://gitlab/Iteration/${id}`,
};
const mountComponent = ({ props = defaultProps, loading = false, data = {} } = {}) => {
wrapper = mount(IterationReportSummary, {
propsData: props,
data() {
return data;
},
mocks: {
$apollo: {
queries: { issues: { loading } },
},
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findPercentageCard = () => wrapper.findAll(GlCard).at(0);
const findOpenCard = () => wrapper.findAll(GlCard).at(1);
const findInProgressCard = () => wrapper.findAll(GlCard).at(2);
const findCompletedCard = () => wrapper.findAll(GlCard).at(3);
describe('with valid totals', () => {
beforeEach(() => {
mountComponent();
wrapper.setData({
issues: {
open: 15,
assigned: 5,
closed: 10,
},
});
});
it('shows complete percentage', () => {
expect(findPercentageCard().text()).toContain('33%');
});
it('shows open issues', () => {
expect(findOpenCard().text()).toContain('Open');
expect(findOpenCard().text()).toContain('15');
});
it('shows in progress issues', () => {
expect(findInProgressCard().text()).toContain('In progress');
expect(findInProgressCard().text()).toContain('5');
});
it('shows completed issues', () => {
expect(findCompletedCard().text()).toContain('Completed');
expect(findCompletedCard().text()).toContain('10');
});
});
describe('with no issues', () => {
beforeEach(() => {
mountComponent();
wrapper.setData({
issues: {
open: 0,
assigned: 0,
closed: 0,
},
});
});
it('shows complete percentage', () => {
expect(findPercentageCard().text()).toContain('0%');
expect(findOpenCard().text()).toContain('0');
expect(findInProgressCard().text()).toContain('0');
expect(findCompletedCard().text()).toContain('0');
});
});
});
......@@ -6113,6 +6113,9 @@ msgstr ""
msgid "Complete"
msgstr ""
msgid "Completed"
msgstr ""
msgid "Compliance"
msgstr ""
......@@ -15728,10 +15731,10 @@ msgstr ""
msgid "No grouping"
msgstr ""
msgid "No iteration"
msgid "No issues found"
msgstr ""
msgid "No iterations found"
msgid "No iteration"
msgstr ""
msgid "No iterations to show"
......
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