Commit 11cd5752 authored by Florie Guibert's avatar Florie Guibert

Display Project and Subgroup milestones on Roadmap

- Include descendants when fetching group epics
- Display project/subgroup/group info in popover
parent 7df008a5
...@@ -35,5 +35,17 @@ module Types ...@@ -35,5 +35,17 @@ module Types
field :updated_at, Types::TimeType, null: false, field :updated_at, Types::TimeType, null: false,
description: 'Timestamp of last milestone update' description: 'Timestamp of last milestone update'
field :project_milestone, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates if milestone is at project level',
method: :project_milestone?
field :group_milestone, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates if milestone is at group level',
method: :group_milestone?
field :subgroup_milestone, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates if milestone is at subgroup level',
method: :subgroup_milestone?
end end
end end
...@@ -179,6 +179,10 @@ class Milestone < ApplicationRecord ...@@ -179,6 +179,10 @@ class Milestone < ApplicationRecord
end end
end end
def subgroup_milestone?
group_milestone? && parent.subgroup?
end
private private
def milestone_format_reference(format = :iid) def milestone_format_reference(format = :iid)
......
...@@ -6673,11 +6673,21 @@ type Milestone { ...@@ -6673,11 +6673,21 @@ type Milestone {
""" """
dueDate: Time dueDate: Time
"""
Indicates if milestone is at group level
"""
groupMilestone: Boolean!
""" """
ID of the milestone ID of the milestone
""" """
id: ID! id: ID!
"""
Indicates if milestone is at project level
"""
projectMilestone: Boolean!
""" """
Timestamp of the milestone start date Timestamp of the milestone start date
""" """
...@@ -6688,6 +6698,11 @@ type Milestone { ...@@ -6688,6 +6698,11 @@ type Milestone {
""" """
state: MilestoneStateEnum! state: MilestoneStateEnum!
"""
Indicates if milestone is at subgroup level
"""
subgroupMilestone: Boolean!
""" """
Title of the milestone Title of the milestone
""" """
......
...@@ -18754,6 +18754,24 @@ ...@@ -18754,6 +18754,24 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "groupMilestone",
"description": "Indicates if milestone is at group level",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "id", "name": "id",
"description": "ID of the milestone", "description": "ID of the milestone",
...@@ -18772,6 +18790,24 @@ ...@@ -18772,6 +18790,24 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "projectMilestone",
"description": "Indicates if milestone is at project level",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "startDate", "name": "startDate",
"description": "Timestamp of the milestone start date", "description": "Timestamp of the milestone start date",
...@@ -18804,6 +18840,24 @@ ...@@ -18804,6 +18840,24 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "subgroupMilestone",
"description": "Indicates if milestone is at subgroup level",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "title", "name": "title",
"description": "Title of the milestone", "description": "Title of the milestone",
...@@ -1019,9 +1019,12 @@ Represents a milestone. ...@@ -1019,9 +1019,12 @@ Represents a milestone.
| `createdAt` | Time! | Timestamp of milestone creation | | `createdAt` | Time! | Timestamp of milestone creation |
| `description` | String | Description of the milestone | | `description` | String | Description of the milestone |
| `dueDate` | Time | Timestamp of the milestone due date | | `dueDate` | Time | Timestamp of the milestone due date |
| `groupMilestone` | Boolean! | Indicates if milestone is at group level |
| `id` | ID! | ID of the milestone | | `id` | ID! | ID of the milestone |
| `projectMilestone` | Boolean! | Indicates if milestone is at project level |
| `startDate` | Time | Timestamp of the milestone start date | | `startDate` | Time | Timestamp of the milestone start date |
| `state` | MilestoneStateEnum! | State of the milestone | | `state` | MilestoneStateEnum! | State of the milestone |
| `subgroupMilestone` | Boolean! | Indicates if milestone is at subgroup level |
| `title` | String! | Title of the milestone | | `title` | String! | Title of the milestone |
| `updatedAt` | Time! | Timestamp of last milestone update | | `updatedAt` | Time! | Timestamp of last milestone update |
| `webPath` | String! | Web path of the milestone | | `webPath` | String! | Web path of the milestone |
......
<script> <script>
import { GlPopover } from '@gitlab/ui'; import { __ } from '~/locale';
import { GlIcon, GlPopover } from '@gitlab/ui';
import CommonMixin from '../mixins/common_mixin'; import CommonMixin from '../mixins/common_mixin';
import QuartersPresetMixin from '../mixins/quarters_preset_mixin'; import QuartersPresetMixin from '../mixins/quarters_preset_mixin';
import MonthsPresetMixin from '../mixins/months_preset_mixin'; import MonthsPresetMixin from '../mixins/months_preset_mixin';
...@@ -9,6 +10,7 @@ import { TIMELINE_CELL_MIN_WIDTH, SCROLL_BAR_SIZE } from '../constants'; ...@@ -9,6 +10,7 @@ import { TIMELINE_CELL_MIN_WIDTH, SCROLL_BAR_SIZE } from '../constants';
export default { export default {
cellWidth: TIMELINE_CELL_MIN_WIDTH, cellWidth: TIMELINE_CELL_MIN_WIDTH,
components: { components: {
GlIcon,
GlPopover, GlPopover,
}, },
mixins: [CommonMixin, QuartersPresetMixin, MonthsPresetMixin, WeeksPresetMixin], mixins: [CommonMixin, QuartersPresetMixin, MonthsPresetMixin, WeeksPresetMixin],
...@@ -97,6 +99,26 @@ export default { ...@@ -97,6 +99,26 @@ export default {
} }
return ''; return '';
}, },
milestoneType() {
const { subgroupMilestone, projectMilestone } = this.milestone;
if (projectMilestone) {
return __('Project milestone');
} else if (subgroupMilestone) {
return __('Subgroup milestone');
}
return __('Group milestone');
},
typeIcon() {
const { subgroupMilestone, projectMilestone } = this.milestone;
if (projectMilestone) {
return 'project';
} else if (subgroupMilestone) {
return 'subgroup';
}
return 'group';
},
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
...@@ -144,7 +166,11 @@ export default { ...@@ -144,7 +166,11 @@ export default {
triggers="hover" triggers="hover"
:title="milestone.title" :title="milestone.title"
> >
{{ timeframeString(milestone) }} <div class="milestone-item-type gl-line-height-normal">
<gl-icon :name="typeIcon" class="gl-vertical-align-middle" />
<span class="d-inline-block gl-vertical-align-middle">{{ milestoneType }}</span>
</div>
<div class="milestone-item-date">{{ timeframeString(milestone) }}</div>
</gl-popover> </gl-popover>
</span> </span>
</div> </div>
......
...@@ -3,6 +3,7 @@ query groupMilestones( ...@@ -3,6 +3,7 @@ query groupMilestones(
$state: MilestoneStateEnum $state: MilestoneStateEnum
$startDate: Time $startDate: Time
$dueDate: Time $dueDate: Time
$includeDescendants: Boolean
) { ) {
group(fullPath: $fullPath) { group(fullPath: $fullPath) {
id id
...@@ -11,6 +12,7 @@ query groupMilestones( ...@@ -11,6 +12,7 @@ query groupMilestones(
state: $state state: $state
startDate: $startDate startDate: $startDate
endDate: $dueDate endDate: $dueDate
includeDescendants: $includeDescendants
) { ) {
edges { edges {
node { node {
...@@ -21,6 +23,9 @@ query groupMilestones( ...@@ -21,6 +23,9 @@ query groupMilestones(
dueDate dueDate
startDate startDate
webPath webPath
projectMilestone
groupMilestone
subgroupMilestone
} }
} }
} }
......
...@@ -267,6 +267,7 @@ export const fetchGroupMilestones = ( ...@@ -267,6 +267,7 @@ export const fetchGroupMilestones = (
presetType, presetType,
timeframe: defaultTimeframe || timeframe, timeframe: defaultTimeframe || timeframe,
}), }),
includeDescendants: true,
...filterParams, ...filterParams,
}; };
......
...@@ -547,3 +547,14 @@ html.group-epics-roadmap-html { ...@@ -547,3 +547,14 @@ html.group-epics-roadmap-html {
} }
} }
} }
.milestone-item-type {
.gl-icon {
padding-right: $gl-spacing-scale-1;
}
}
.milestone-item-date {
color: $gray-700;
padding-top: $gl-spacing-scale-1;
}
---
title: Display Project and Subgroup milestones on Roadmap
merge_request: 32496
author:
type: changed
...@@ -608,6 +608,7 @@ describe('Roadmap Vuex Actions', () => { ...@@ -608,6 +608,7 @@ describe('Roadmap Vuex Actions', () => {
state: mockState.milestonessState, state: mockState.milestonessState,
startDate: '2017-11-1', startDate: '2017-11-1',
dueDate: '2018-6-30', dueDate: '2018-6-30',
includeDescendants: true,
}; };
}); });
......
...@@ -10770,6 +10770,9 @@ msgstr "" ...@@ -10770,6 +10770,9 @@ msgstr ""
msgid "Group members" msgid "Group members"
msgstr "" msgstr ""
msgid "Group milestone"
msgstr ""
msgid "Group name" msgid "Group name"
msgstr "" msgstr ""
...@@ -16586,6 +16589,9 @@ msgstr "" ...@@ -16586,6 +16589,9 @@ msgstr ""
msgid "Project members" msgid "Project members"
msgstr "" msgstr ""
msgid "Project milestone"
msgstr ""
msgid "Project name" msgid "Project name"
msgstr "" msgstr ""
...@@ -20727,6 +20733,9 @@ msgstr "" ...@@ -20727,6 +20733,9 @@ msgstr ""
msgid "StorageSize|Unknown" msgid "StorageSize|Unknown"
msgstr "" msgstr ""
msgid "Subgroup milestone"
msgstr ""
msgid "Subgroup overview" msgid "Subgroup overview"
msgstr "" msgstr ""
......
...@@ -498,4 +498,23 @@ describe Milestone do ...@@ -498,4 +498,23 @@ describe Milestone do
end end
end end
end end
describe '#subgroup_milestone' do
context 'parent is subgroup' do
it 'returns true' do
group = create(:group)
subgroup = create(:group, :private, parent: group)
expect(build(:milestone, group: subgroup).subgroup_milestone?).to eq(true)
end
end
context 'parent is not subgroup' do
it 'returns false' do
group = create(:group)
expect(build(:milestone, group: group).subgroup_milestone?).to eq(false)
end
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