diff --git a/CHANGELOG b/CHANGELOG
index 8692f61fe367422e77a0caecc11d80562e2b6dfa..bba032036e34114998d149c5bcd17ca307380e0f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,7 @@ v 8.6.0 (unreleased)
   - Allow search for logged out users
   - Don't show Issues/MRs from archived projects in Groups view
   - Increase the notes polling timeout over time (Roberto Dip)
+  - Show labels in dashboard and group milestone views
 
 v 8.5.4
   - Do not cache requests for badges (including builds badge)
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index d7feb5d5c87ea3bf10e202c7c0ad0844b1acbd48..54b28f2dd8d077b6639b50cd3556a69611871fc4 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -23,7 +23,7 @@ class Dispatcher
         new Issue()
         shortcut_handler = new ShortcutsIssuable()
         new ZenMode()
-      when 'projects:milestones:show'
+      when 'projects:milestones:show', 'groups:milestones:show', 'dashboard:milestones:show'
         new Milestone()
       when 'projects:milestones:new', 'projects:milestones:edit'
         new ZenMode()
diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee
index e6d8518bec862f6619d8cf43b841d4c6cfb72906..0037a3a21c268fb917600ccf9dd72cc94450162a 100644
--- a/app/assets/javascripts/milestone.js.coffee
+++ b/app/assets/javascripts/milestone.js.coffee
@@ -69,7 +69,7 @@ class @Milestone
 
     @bindIssuesSorting()
     @bindMergeRequestSorting()
-    @bindTabsSwitching
+    @bindTabsSwitching()
 
   bindIssuesSorting: ->
     $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable(
@@ -104,7 +104,7 @@ class @Milestone
 
     ).disableSelection()
 
-  bindMergeRequestSorting: ->
+  bindTabsSwitching: ->
     $('a[data-toggle="tab"]').on 'show.bs.tab', (e) ->
       currentTabClass  = $(e.target).data('show')
       previousTabClass =  $(e.relatedTarget).data('show')
@@ -112,7 +112,8 @@ class @Milestone
       $(previousTabClass).hide()
       $(currentTabClass).removeClass('hidden')
       $(currentTabClass).show()
-      
+
+  bindMergeRequestSorting: ->
     $("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable(
       connectWith: ".merge_requests-sortable-list",
       dropOnEmpty: true,
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 300c2fa7e1b05554598978c5a8932c71863a6661..d0e72a4422c321f5edb32c9084ebac957b62dbe0 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -19,10 +19,11 @@ li.milestone {
     width: 105px;
   }
 
-  .issue-row, .merge_request-row {
+  .issuable-row {
     .color-label {
       border-radius: 2px;
       padding: 3px !important;
+      margin-right: 7px;
     }
 
     // Issue title
@@ -45,19 +46,14 @@ li.milestone {
 }
 
 .issues-sortable-list, .merge_requests-sortable-list {
-  .issue-detail, .merge_request-detail {
+  .issuable-detail {
     display: block;
+    margin-top: 7px;
 
-    .issue-number, .merge_request-number {
+    .issuable-number {
       color: rgba(0,0,0,0.44);
       margin-right: 5px;
     }
-    .color-label {
-      padding: 6px 10px;
-      margin-right: 7px;
-      margin-top: 10px;
-    }
-
     .avatar {
       float: none;
     }
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 21f30f278c839ce6faedd9d75cbab76c0f0d8c2f..da46731d945eacc310ebe013498c4ff23dd13be2 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -32,10 +32,6 @@ class Projects::MilestonesController < Projects::ApplicationController
   end
 
   def show
-    @issues = @milestone.issues
-    @users = @milestone.participants.uniq
-    @merge_requests = @milestone.merge_requests
-    @labels = @milestone.labels
   end
 
   def create
diff --git a/app/decorators/label_with_milestone.rb b/app/decorators/label_with_milestone.rb
deleted file mode 100644
index a70a4e2f50d2191ad48a06c450f08a0e62ea9222..0000000000000000000000000000000000000000
--- a/app/decorators/label_with_milestone.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-class LabelWithMilestone
-  attr_reader :milestone
-
-  def initialize(label, milestone)
-    @label, @milestone = label, milestone
-  end
-
-  def method_missing(meth, *args)
-    if @label.respond_to?(meth)
-      @label.send(meth, *args)
-    else
-      super
-    end
-  end
-
-  def respond_to?(meth)
-    @label.respond_to?(meth)
-  end
-end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index f7240edd61890c3b73350a4de38c748acea43208..c88a420b41247a261efc86b54615cca805a5cf1a 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -263,11 +263,9 @@ class IssuableFinder
   def by_label(items)
     if labels?
       if filter_by_no_label?
-        items = items.
-          joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{klass.name}' AND label_links.target_id = #{klass.table_name}.id").
-          where(label_links: { id: nil })
+        items = items.without_label
       else
-        items = items.joins(:labels).where(labels: { title: label_names })
+        items = items.with_label(label_names)
 
         if projects
           items = items.where(labels: { project_id: projects })
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 7de81d8dfdb2b7fb2c2b179b4585abe0b7fa2df7..e3e7daa49c5786de8d75ffa6a703b9d5edfdbda6 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -9,6 +9,32 @@ module MilestonesHelper
     end
   end
 
+  def milestones_label_path(opts = {})
+    if @project
+      namespace_project_issues_path(@project.namespace, @project, opts)
+    elsif @group
+      issues_group_path(@group, opts)
+    else
+      issues_dashboard_path(opts)
+    end
+  end
+
+  def milestones_browse_issuables_path(milestone, type:)
+    opts = { milestone_title: milestone.title }
+
+    if @project
+      polymorphic_path([@project.namespace.becomes(Namespace), @project, type], opts)
+    elsif @group
+      polymorphic_url([type, @group], opts)
+    else
+      polymorphic_url([type, :dashboard], opts)
+    end
+  end
+
+  def milestone_issues_by_label_count(milestone, label, state:)
+    milestone.issues.with_label(label.title).send(state).size
+  end
+
   def milestone_progress_bar(milestone)
     options = {
       class: 'progress-bar progress-bar-success',
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index a3c4a3d2776b1ce1c6208a877c8c0d5e6a294b26..27b97944e3817a8bb3833f9cb8123e73562164a9 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -36,6 +36,8 @@ module Issuable
     scope :closed, -> { with_state(:closed) }
     scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') }
     scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') }
+    scope :with_label, ->(title) { joins(:labels).where(labels: { title: title }) }
+    scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
 
     scope :join_project, -> { joins(:project) }
     scope :references_project, -> { references(:project) }
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d67df7c1d9c1933592f0ceebb40ebdd6f0af3b61
--- /dev/null
+++ b/app/models/concerns/milestoneish.rb
@@ -0,0 +1,25 @@
+module Milestoneish
+  def closed_items_count
+    issues.closed.size + merge_requests.closed_and_merged.size
+  end
+
+  def total_items_count
+    issues.size + merge_requests.size
+  end
+
+  def complete?
+    total_items_count == closed_items_count
+  end
+
+  def percent_complete
+    ((closed_items_count * 100) / total_items_count).abs
+  rescue ZeroDivisionError
+    0
+  end
+
+  def remaining_days
+    return 0 if !due_date || expired?
+
+    (due_date - Date.today).to_i
+  end
+end
diff --git a/app/models/global_label.rb b/app/models/global_label.rb
index 0171f7d54b7d6a56157d4bdcd4a1b664aba71fd6..ddd4bad5c216fc8d729302ab820cbd1c21ab3f3c 100644
--- a/app/models/global_label.rb
+++ b/app/models/global_label.rb
@@ -2,16 +2,19 @@ class GlobalLabel
   attr_accessor :title, :labels
   alias_attribute :name, :title
 
+  delegate :color, :description, to: :@first_label
+
   def self.build_collection(labels)
     labels = labels.group_by(&:title)
 
-    labels.map do |title, label|
-      new(title, label)
+    labels.map do |title, labels|
+      new(title, labels)
     end
   end
 
   def initialize(title, labels)
     @title = title
     @labels = labels
+    @first_label = labels.find { |lbl| lbl.description.present? } || labels.first
   end
 end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index e13aaf16732d85d87e25973afd5cf25c8982c6ce..97bd79af083027cdbd9c0fcac1250364fb397ac8 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -1,4 +1,6 @@
 class GlobalMilestone
+  include Milestoneish
+
   attr_accessor :title, :milestones
   alias_attribute :name, :title
 
@@ -31,32 +33,6 @@ class GlobalMilestone
     @projects ||= Project.for_milestones(milestones.map(&:id))
   end
 
-  def issues_count
-    issues.count
-  end
-
-  def merge_requests_count
-    merge_requests.count
-  end
-
-  def open_items_count
-    opened_issues.count + opened_merge_requests.count
-  end
-
-  def closed_items_count
-    closed_issues.count + closed_merge_requests.count
-  end
-
-  def total_items_count
-    issues_count + merge_requests_count
-  end
-
-  def percent_complete
-    ((closed_items_count * 100) / total_items_count).abs
-  rescue ZeroDivisionError
-    0
-  end
-
   def state
     state = milestones.map { |milestone| milestone.state }
 
@@ -88,29 +64,8 @@ class GlobalMilestone
   end
 
   def labels
-    @labels ||= milestones.map do |ms|
-                  ms.labels.map { |label| LabelWithMilestone.new(label, ms) }
-                end.flatten.sort_by!(&:title)
-  end
-
-  def opened_issues
-    issues.opened
-  end
-
-  def closed_issues
-    issues.closed
-  end
-
-  def opened_merge_requests
-    merge_requests.opened
-  end
-
-  def closed_merge_requests
-    merge_requests.with_states(:closed, :merged, :locked)
-  end
-
-  def complete?
-    total_items_count == closed_items_count
+    @labels ||= GlobalLabel.build_collection(milestones.map(&:labels).flatten)
+                           .sort_by!(&:title)
   end
 
   def due_date
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f575494e2bf2696a7c729adb63e8a8d869004a66..0c1a47b3f6a6d3c1b80dafc95d7833e8e399098a 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -137,7 +137,6 @@ class MergeRequest < ActiveRecord::Base
   scope :by_milestone, ->(milestone) { where(milestone_id: milestone) }
   scope :in_projects, ->(project_ids) { where("source_project_id in (:project_ids) OR target_project_id in (:project_ids)", project_ids: project_ids) }
   scope :of_projects, ->(ids) { where(target_project_id: ids) }
-  scope :opened, -> { with_states(:opened, :reopened) }
   scope :merged, -> { with_state(:merged) }
   scope :closed_and_merged, -> { with_states(:closed, :merged) }
 
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 7dc2f909b2f82367795642741ff396510e5c3894..e3969f32dd6a828e242e31f64c71d1c4ece8b467 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -24,12 +24,13 @@ class Milestone < ActiveRecord::Base
   include Sortable
   include Referable
   include StripAttribute
+  include Milestoneish
 
   belongs_to :project
   has_many :issues
   has_many :labels, -> { distinct.reorder('labels.title') },  through: :issues
   has_many :merge_requests
-  has_many :participants, through: :issues, source: :assignee
+  has_many :participants, -> { distinct.reorder('users.name') }, through: :issues, source: :assignee
 
   scope :active, -> { with_state(:active) }
   scope :closed, -> { with_state(:closed) }
@@ -92,30 +93,6 @@ class Milestone < ActiveRecord::Base
     end
   end
 
-  def open_items_count
-    self.issues.opened.count + self.merge_requests.opened.count
-  end
-
-  def closed_items_count
-    self.issues.closed.count + self.merge_requests.closed_and_merged.count
-  end
-
-  def total_items_count
-    self.issues.count + self.merge_requests.count
-  end
-
-  def percent_complete
-    ((closed_items_count * 100) / total_items_count).abs
-  rescue ZeroDivisionError
-    0
-  end
-
-  def remaining_days
-    return 0 if !due_date || expired?
-
-    (due_date - Date.today).to_i
-  end
-
   def expires_at
     if due_date
       if due_date.past?
diff --git a/app/models/project.rb b/app/models/project.rb
index 3a28d5d7fee30074d7e2f70ad677256ff740b865..3235a1cee5051c7055a7b7f7b3661232a2487484 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -215,7 +215,7 @@ class Project < ActiveRecord::Base
   scope :public_only, -> { where(visibility_level: Project::PUBLIC) }
   scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) }
   scope :non_archived, -> { where(archived: false) }
-  scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids) }
+  scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
 
   state_machine :import_status, initial: :none do
     event :import_start do
diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml
index ea6c304d7de0ad563744c8faa9c50fc2a5a7e683..6173ca6ab9bb5cf76c87b0180f3cecabdd9dcb1f 100644
--- a/app/views/dashboard/milestones/_milestone.html.haml
+++ b/app/views/dashboard/milestones/_milestone.html.haml
@@ -1,25 +1,6 @@
-%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
-  .row
-    .col-sm-6
-      %strong
-        = link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
-    .col-sm-6
-      .pull-right.light #{milestone.percent_complete}% complete
-  .row
-    .col-sm-6
-      = link_to issues_dashboard_path(milestone_title: milestone.title) do
-        = pluralize milestone.issues_count, 'Issue'
-      &middot;
-      = link_to merge_requests_dashboard_path(milestone_title: milestone.title) do
-        = pluralize milestone.merge_requests_count, 'Merge Request'
-    .col-sm-6
-      = milestone_progress_bar(milestone)
-  .row
-    .col-sm-6
-      .expiration
-        = render 'shared/milestone_expired', milestone: milestone
-      .projects
-        - milestone.milestones.each do |milestone|
-          = link_to milestone_path(milestone) do
-            %span.label.label-gray
-              = milestone.project.name_with_namespace
+= render 'shared/milestones/milestone',
+          milestone_path: dashboard_milestone_path(milestone.safe_title, title: milestone.title),
+          issues_path: issues_dashboard_path(milestone_title: milestone.title),
+          merge_requests_path: merge_requests_dashboard_path(milestone_title: milestone.title),
+          milestone: milestone,
+          dashboard: true
diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml
index 88edc025c6236509c2d6c42aad7e15eb4afa9eab..60c84a2642079156bec92509f8fa3180e7bbefb2 100644
--- a/app/views/dashboard/milestones/show.html.haml
+++ b/app/views/dashboard/milestones/show.html.haml
@@ -1,85 +1,5 @@
-- page_title @milestone.title, "Milestones"
 - header_title "Milestones", dashboard_milestones_path
 
-.detail-page-header
-  .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
-    - if @milestone.closed?
-      Closed
-    - else
-      Open
-  %span.identifier
-    Milestone #{@milestone.title}
-
-.detail-page-description.gray-content-block.second-block
-  %h2.title
-    = markdown escape_once(@milestone.title), pipeline: :single_line
-
-- if @milestone.complete? && @milestone.active?
-  .alert.alert-success.prepend-top-default
-    %span All issues for this milestone are closed. Navigate to the project to close the milestone.
-
-.table-holder
-  %table.table
-    %thead
-      %tr
-        %th Project
-        %th Open issues
-        %th State
-        %th Due date
-    - @milestone.milestones.each do |milestone|
-      %tr
-        %td
-          = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
-        %td
-          = milestone.issues.opened.count
-        %td
-          - if milestone.closed?
-            Closed
-          - else
-            Open
-        %td
-          = milestone.expires_at
-
-.context
-  .milestone-summary
-    %h4 Progress
-    %strong= @milestone.issues.size
-    issues:
-    %span.milestone-stat
-      %strong= @milestone.opened_issues.size
-      open and
-      %strong= @milestone.closed_issues.size
-      closed
-    %span.milestone-stat
-      %strong== #{@milestone.percent_complete}%
-      complete
-
-  = milestone_progress_bar(@milestone)
-
-%ul.nav-links.no-top.no-bottom
-  %li.active
-    = link_to '#tab-issues', 'data-toggle' => 'tab' do
-      Issues
-      %span.badge= @milestone.issues_count
-  %li
-    = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
-      Merge Requests
-      %span.badge= @milestone.merge_requests_count
-  %li
-    = link_to '#tab-participants', 'data-toggle' => 'tab' do
-      Participants
-      %span.badge= @milestone.participants.count
-  %li
-    = link_to '#tab-labels', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
-      Labels
-      %span.badge= @milestone.labels.count
-
-.tab-content.milestone-content
-  .tab-pane.active#tab-issues
-    = render 'shared/milestones/issues_tab', unassigned: @milestone.opened_issues.unassigned, assigned: @milestone.opened_issues.assigned, closed: @milestone.closed_issues, show_full_project_name: true
-  .tab-pane#tab-merge-requests
-    = render 'shared/milestones/merge_requests_tab', unassigned: @milestone.opened_merge_requests.unassigned, assigned: @milestone.opened_merge_requests.assigned, closed: @milestone.merge_requests.closed, merged: @milestone.merge_requests.merged, show_full_project_name: true
-  .tab-pane#tab-participants
-    = render 'shared/milestones/participants_tab', users: @milestone.participants
-  .tab-pane#tab-labels
-    = render 'shared/milestones/labels_tab', labels: @milestone.labels, show_full_project_name: true
+= render 'shared/milestones/top', milestone: @milestone
+= render 'shared/milestones/summary', milestone: @milestone
+= render 'shared/milestones/tabs', milestone: @milestone, show_full_project_name: true
diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml
index 50558d7dce854b75a0b7c8d4c106fc8f30ad1c2a..4c4e0a267288dc0459721c9aeae0dcfb5b4ae9b7 100644
--- a/app/views/groups/milestones/_milestone.html.haml
+++ b/app/views/groups/milestones/_milestone.html.haml
@@ -1,29 +1,5 @@
-%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
-  .row
-    .col-sm-6
-      %strong
-        = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
-    .col-sm-6
-      .pull-right.light #{milestone.percent_complete}% complete
-  .row
-    .col-sm-6
-      = link_to issues_group_path(@group, milestone_title: milestone.title) do
-        = pluralize milestone.issues_count, 'Issue'
-      &middot;
-      = link_to merge_requests_group_path(@group, milestone_title: milestone.title) do
-        = pluralize milestone.merge_requests_count, 'Merge Request'
-    .col-sm-6
-      = milestone_progress_bar(milestone)
-  .row
-    .col-sm-6
-      %div
-        - milestone.milestones.each do |milestone|
-          = link_to milestone_path(milestone) do
-            %span.label.label-gray
-              = milestone.project.name
-    .col-sm-6
-      - if can?(current_user, :admin_milestones, @group)
-        - if milestone.closed?
-          = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen"
-        - else
-          = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-xs btn-close"
+= render 'shared/milestones/milestone',
+          milestone_path: group_milestone_path(@group, milestone.safe_title, title: milestone.title),
+          issues_path: issues_group_path(@group, milestone_title: milestone.title),
+          merge_requests_path: merge_requests_group_path(@group, milestone_title: milestone.title),
+          milestone: milestone
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index bd61e50a5bdca1b529b6ac7ceef69cd8d3218564..fb6f0da28f82b2829bb75f33a5539b6e59448322 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,91 +1,4 @@
-- page_title @milestone.title, "Milestones"
 = render "header_title"
-
-.detail-page-header
-  .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
-    - if @milestone.closed?
-      Closed
-    - else
-      Open
-  %span.identifier
-    Milestone #{@milestone.title}
-  .pull-right
-    - if can?(current_user, :admin_milestones, @group)
-      - if @milestone.active?
-        = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
-      - else
-        = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
-
-.detail-page-description.gray-content-block.second-block
-  %h2.title
-    = markdown escape_once(@milestone.title), pipeline: :single_line
-
-- if @milestone.complete? && @milestone.active?
-  .alert.alert-success.prepend-top-default
-    %span All issues for this milestone are closed. You may close the milestone now.
-
-.table-holder
-  %table.table
-    %thead
-      %tr
-        %th Project
-        %th Open issues
-        %th State
-        %th Due date
-    - @milestone.milestones.each do |milestone|
-      %tr
-        %td
-          = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
-        %td
-          = milestone.issues.opened.count
-        %td
-          - if milestone.closed?
-            Closed
-          - else
-            Open
-        %td
-          = milestone.expires_at
-
-.context
-  .milestone-summary
-    %h4 Progress
-    %strong= @milestone.issues.size
-    issues:
-    %span.milestone-stat
-      %strong= @milestone.opened_issues.size
-      open and
-      %strong= @milestone.closed_issues.size
-      closed
-    %span.milestone-stat
-      %strong== #{@milestone.percent_complete}%
-      complete
-
-  = milestone_progress_bar(@milestone)
-
-%ul.nav-links.no-top.no-bottom
-  %li.active
-    = link_to '#tab-issues', 'data-toggle' => 'tab' do
-      Issues
-      %span.badge= @milestone.issues_count
-  %li
-    = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
-      Merge Requests
-      %span.badge= @milestone.merge_requests_count
-  %li
-    = link_to '#tab-participants', 'data-toggle' => 'tab' do
-      Participants
-      %span.badge= @milestone.participants.count
-  %li
-    = link_to '#tab-labels', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
-      Labels
-      %span.badge= @milestone.labels.count
-
-.tab-content.milestone-content
-  .tab-pane.active#tab-issues
-    = render 'shared/milestones/issues_tab', unassigned: @milestone.opened_issues.unassigned, assigned: @milestone.opened_issues.assigned, closed: @milestone.closed_issues, show_project_name: true
-  .tab-pane#tab-merge-requests
-    = render 'shared/milestones/merge_requests_tab', unassigned: @milestone.opened_merge_requests.unassigned, assigned: @milestone.opened_merge_requests.assigned, closed: @milestone.merge_requests.closed, merged: @milestone.merge_requests.merged, show_project_name: true
-  .tab-pane#tab-participants
-    = render 'shared/milestones/participants_tab', users: @milestone.participants
-  .tab-pane#tab-labels
-    = render 'shared/milestones/labels_tab', labels: @milestone.labels, show_project_name: true
+= render 'shared/milestones/top', milestone: @milestone, group: @group
+= render 'shared/milestones/summary', milestone: @milestone
+= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true
diff --git a/app/views/projects/milestones/_milestone.html.haml b/app/views/projects/milestones/_milestone.html.haml
index 67d95ab0364d349cec2441263ae7f81a8ad7800a..77b566db6b6003fa475edce90af2fb6d0d4fe88b 100644
--- a/app/views/projects/milestones/_milestone.html.haml
+++ b/app/views/projects/milestones/_milestone.html.haml
@@ -1,31 +1,5 @@
-%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) }
-  .row
-    .col-sm-6
-      %strong
-        = link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
-
-    .col-sm-6
-      .pull-right.light #{milestone.percent_complete}% complete
-  .row
-    .col-sm-6
-      = link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title) do
-        = pluralize milestone.issues.count, 'Issue'
-      &middot;
-      = link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title) do
-        = pluralize milestone.merge_requests.count, 'Merge Request'
-    .col-sm-6
-      = milestone_progress_bar(milestone)
-
-  .row
-    .col-sm-6
-      = render 'shared/milestone_expired', milestone: milestone
-    .col-sm-6
-      - if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
-        = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs" do
-          = icon('pencil-square-o')
-          Edit
-        \
-        = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-xs btn-close"
-        = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-xs btn-remove" do
-          = icon('trash-o')
-          Delete
+= render 'shared/milestones/milestone',
+          milestone_path: namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone),
+          issues_path: namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title),
+          merge_requests_path: namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_title: milestone.title),
+          milestone: milestone
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 4aa1a53e87ed17813817d1d6c804e164238ed536..b4597043a27af1ec6a0fc1cc541e056e4da12886 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -42,62 +42,9 @@
           = preserve do
             = markdown @milestone.description
 
-- if @milestone.issues.any? && @milestone.can_be_closed?
+- if @milestone.complete? && @milestone.active?
   .alert.alert-success.prepend-top-default
     %span All issues for this milestone are closed. You may close milestone now.
 
-.context.prepend-top-default
-  .milestone-summary
-    %h4 Progress
-    %strong= @milestone.issues.count
-    issues:
-    %span.milestone-stat
-      %strong= @milestone.open_items_count
-      open and
-      %strong= @milestone.closed_items_count
-      closed
-    %span.milestone-stat
-      %strong== #{@milestone.percent_complete}%
-      complete
-    %span.milestone-stat
-      %span.remaining-days= milestone_remaining_days(@milestone)
-    %span.pull-right.tab-issues-buttons
-      - if can?(current_user, :create_issue, @project)
-        = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn  btn-grouped", title: "New Issue" do
-          %i.fa.fa-plus
-          New Issue
-      - if can?(current_user, :read_issue, @project)
-        = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped"
-    %span.pull-right.tab-merge-requests-buttons.hidden
-      - if can?(current_user, :read_merge_request, @project)
-        = link_to 'Browse Merge Requests', namespace_project_merge_requests_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped"
-
-  = milestone_progress_bar(@milestone)
-
-%ul.nav-links.no-top.no-bottom
-  %li.active
-    = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
-      Issues
-      %span.badge= @issues.count
-  %li
-    = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do
-      Merge Requests
-      %span.badge= @merge_requests.count
-  %li
-    = link_to '#tab-participants', 'data-toggle' => 'tab' do
-      Participants
-      %span.badge= @users.count
-  %li
-    = link_to '#tab-labels', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
-      Labels
-      %span.badge= @labels.count
-
-.tab-content.milestone-content
-  .tab-pane.active#tab-issues
-    = render 'shared/milestones/issues_tab', unassigned: @issues.opened.unassigned, assigned: @issues.opened.assigned, closed: @issues.closed
-  .tab-pane#tab-merge-requests
-    = render 'shared/milestones/merge_requests_tab', unassigned: @merge_requests.opened.unassigned, assigned: @merge_requests.opened.assigned, closed: @merge_requests.closed, merged: @merge_requests.merged
-  .tab-pane#tab-participants
-    = render 'shared/milestones/participants_tab', users: @users
-  .tab-pane#tab-labels
-    = render 'shared/milestones/labels_tab', labels: @labels
+= render 'shared/milestones/summary', milestone: @milestone, project: @project
+= render 'shared/milestones/tabs', milestone: @milestone
diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f7c6fc14adf196b0ea186f01f6312e8800bb3a2c
--- /dev/null
+++ b/app/views/shared/milestones/_issuable.html.haml
@@ -0,0 +1,25 @@
+-# @project is present when viewing Project's milestone
+- project = @project || issuable.project
+- assignee = issuable.assignee
+- issuable_type = issuable.class.table_name
+- base_url_args = [project.namespace.becomes(Namespace), project, issuable_type]
+
+%li{ id: dom_id(issuable, 'sortable'),  class: "issuable-row", 'data-iid' => issuable.iid, 'data-url' => polymorphic_path(issuable) }
+  %span
+    - if show_project_name
+      %strong #{project.name} &middot;
+    - elsif show_full_project_name
+      %strong #{project.name_with_namespace} &middot;
+    = link_to_gfm issuable.title, [project.namespace.becomes(Namespace), project, issuable], title: issuable.title
+  %div{class: 'issuable-detail'}
+    = link_to [project.namespace.becomes(Namespace), project, issuable] do
+      %span{ class: 'issuable-number' }>= issuable.to_reference
+
+    - issuable.labels.each do |label|
+      = link_to polymorphic_path(base_url_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }) do
+        - render_colored_label(label)
+
+    - if assignee
+      = link_to polymorphic_path(base_url_args, { milestone_title: @milestone.title, assignee_id: issuable.assignee_id, state: 'all' }),
+                class: 'has_tooltip', data: { 'original-title' => "Assigned to #{sanitize(assignee.name)}", container: 'body' } do
+        - image_tag(avatar_icon(issuable.assignee, 16), class: "avatar s16", alt: '')
diff --git a/app/views/shared/milestones/_records.html.haml b/app/views/shared/milestones/_issuables.html.haml
similarity index 52%
rename from app/views/shared/milestones/_records.html.haml
rename to app/views/shared/milestones/_issuables.html.haml
index 29fd6aaac9b2e388ac37e21f5057c5c7e97a50d7..8619939dde7993c575825c8d22704f13793d4bf3 100644
--- a/app/views/shared/milestones/_records.html.haml
+++ b/app/views/shared/milestones/_issuables.html.haml
@@ -6,9 +6,11 @@
   .panel-heading
     = title
     - if show_counter
-      .pull-right= records.size
+      .pull-right= issuables.size
 
-  - class_prefix = dom_class(records).pluralize
+  - class_prefix = dom_class(issuables).pluralize
   %ul{ class: "well-list #{class_prefix}-sortable-list", id: "#{class_prefix}-list-#{id}", "data-state" => id }
-    - records.sort_by(&:position).each do |record|
-      = render 'shared/milestones/record', record: record, show_project_name: show_project_name, show_full_project_name: show_full_project_name
+    = render partial: 'shared/milestones/issuable',
+             collection: issuables.sort_by(&:position),
+             as: :issuable,
+             locals: { show_project_name: show_project_name, show_full_project_name: show_full_project_name }
diff --git a/app/views/shared/milestones/_issues_tab.html.haml b/app/views/shared/milestones/_issues_tab.html.haml
index 44a221114bbd78b9393524b10b4dba58f8c691dd..a8db7f8a556154a5e3c6757549e641f9cb68ba2d 100644
--- a/app/views/shared/milestones/_issues_tab.html.haml
+++ b/app/views/shared/milestones/_issues_tab.html.haml
@@ -3,8 +3,8 @@
 
 .row.prepend-top-default
   .col-md-4
-    = render 'shared/milestones/records', args.merge({ title: 'Unstarted Issues (open and unassigned)', records: unassigned, id: 'unassigned', show_counter: true })
+    = render 'shared/milestones/issuables', args.merge(title: 'Unstarted Issues (open and unassigned)', issuables: issues.opened.unassigned, id: 'unassigned', show_counter: true)
   .col-md-4
-    = render 'shared/milestones/records', args.merge({ title: 'Ongoing Issues (open and assigned)', records: assigned, id: 'ongoing', show_counter: true })
+    = render 'shared/milestones/issuables', args.merge(title: 'Ongoing Issues (open and assigned)', issuables: issues.opened.assigned, id: 'ongoing', show_counter: true)
   .col-md-4
-    = render 'shared/milestones/records', args.merge({ title: 'Completed Issues (closed)', records: closed, id: 'closed', show_counter: true })
+    = render 'shared/milestones/issuables', args.merge(title: 'Completed Issues (closed)', issuables: issues.closed, id: 'closed', show_counter: true)
diff --git a/app/views/shared/milestones/_labels_tab.html.haml b/app/views/shared/milestones/_labels_tab.html.haml
index 88e8e4f90069dee789766b9d5029777ded70946e..ba27bafd1bc0ce870843a609f4c0bb4cb003d10b 100644
--- a/app/views/shared/milestones/_labels_tab.html.haml
+++ b/app/views/shared/milestones/_labels_tab.html.haml
@@ -1,22 +1,18 @@
-- show_project_name = local_assigns.fetch(:show_project_name, false)
-- show_full_project_name = local_assigns.fetch(:show_full_project_name, false)
-
 %ul.bordered-list.manage-labels-list
   - labels.each do |label|
-    - milestone = @milestone.is_a?(Milestone) ? @milestone : label.milestone
+    - options = { milestone_title: @milestone.title, label_name: label.title }
 
     %li
-      = render_colored_label(label)
-      - if show_project_name
-        %strong &middot; #{milestone.project.name}
-      - elsif show_full_project_name
-        %strong &middot; #{milestone.project.name_with_namespace}
+      %span.label-row
+        = link_to milestones_label_path(options) do
+          - render_colored_label(label)
+        %span.prepend-left-10
+          = markdown(label.description, pipeline: :single_line)
 
-      - args = [milestone.project.namespace, milestone.project, milestone_title: milestone.title, label_name: label.title]
-      - options = args.extract_options!
-      %span.issues-count
-        = link_to namespace_project_issues_path(*args, options.merge(state: 'opened')) do
-          = pluralize label.open_issues_count, 'open issue'
-      %span.issues-count
-        = link_to namespace_project_issues_path(*args, options.merge(state: 'closed')) do
-          = pluralize label.closed_issues_count, 'closed issue'
+      .pull-right
+        %strong.issues-count
+          = link_to milestones_label_path(options.merge(state: 'opened')) do
+            - pluralize milestone_issues_by_label_count(@milestone, label, state: :opened), 'open issue'
+        %strong.issues-count
+          = link_to milestones_label_path(options.merge(state: 'closed')) do
+            - pluralize milestone_issues_by_label_count(@milestone, label, state: :closed), 'closed issue'
diff --git a/app/views/shared/milestones/_merge_requests_tab.haml b/app/views/shared/milestones/_merge_requests_tab.haml
index 15b2876c32df610d052f06cce3e3ab5e7c535e0c..c29d8ee6737c1529953a566f552c77e235737c60 100644
--- a/app/views/shared/milestones/_merge_requests_tab.haml
+++ b/app/views/shared/milestones/_merge_requests_tab.haml
@@ -3,10 +3,10 @@
 
 .row.prepend-top-default
   .col-md-3
-    = render 'shared/milestones/records', args.merge({ title: 'Work in progress (open and unassigned)', records: unassigned, id: 'unassigned' })
+    = render 'shared/milestones/issuables', args.merge(title: 'Work in progress (open and unassigned)', issuables: merge_requests.opened.unassigned, id: 'unassigned')
   .col-md-3
-    = render 'shared/milestones/records', args.merge({ title: 'Waiting for merge (open and assigned)', records: assigned, id: 'ongoing' })
+    = render 'shared/milestones/issuables', args.merge(title: 'Waiting for merge (open and assigned)', issuables: merge_requests.opened.assigned, id: 'ongoing')
   .col-md-3
-    = render 'shared/milestones/records', args.merge({ title: 'Rejected (closed)', records: closed, id: 'closed' })
+    = render 'shared/milestones/issuables', args.merge(title: 'Rejected (closed)', issuables: merge_requests.closed, id: 'closed')
   .col-md-3
-    = render 'shared/milestones/records', args.merge({ title: 'Merged', records: merged, id: 'merged', primary: true })
+    = render 'shared/milestones/issuables', args.merge(title: 'Merged', issuables: merge_requests.merged, id: 'merged', primary: true)
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f01138af3f09c20d2eaef18d63366c44d733aa9f
--- /dev/null
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -0,0 +1,45 @@
+- dashboard = local_assigns[:dashboard]
+- custom_dom_id = dom_id(@project ? milestone : milestone.milestones.first)
+
+%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: custom_dom_id }
+  .row
+    .col-sm-6
+      %strong= link_to_gfm truncate(milestone.title, length: 100), milestone_path
+    .col-sm-6
+      .pull-right.light #{milestone.percent_complete}% complete
+  .row
+    .col-sm-6
+      = link_to pluralize(milestone.issues.size, 'Issue'), issues_path
+      &middot;
+      = link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
+    .col-sm-6= milestone_progress_bar(milestone)
+  - if milestone.is_a?(GlobalMilestone)
+    .row
+      .col-sm-6
+        .expiration= render('shared/milestone_expired', milestone: milestone)
+        .projects
+          - milestone.milestones.each do |milestone|
+            = link_to milestone_path(milestone) do
+              %span.label.label-gray
+                = dashboard ? milestone.project.name_with_namespace : milestone.project.name
+      - if @group
+        .col-sm-6
+          - if can?(current_user, :admin_milestones, @group)
+            - if milestone.closed?
+              = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen"
+            - else
+              = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-xs btn-close"
+
+  - if @project
+    .row
+      .col-sm-6= render('shared/milestone_expired', milestone: milestone)
+      .col-sm-6
+        - if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
+          = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs" do
+            = icon('pencil-square-o')
+            Edit
+          \
+          = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-xs btn-close"
+          = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-xs btn-remove" do
+            = icon('trash-o')
+            Delete
diff --git a/app/views/shared/milestones/_record.html.haml b/app/views/shared/milestones/_record.html.haml
deleted file mode 100644
index f82f2132bb65ed36e9b3c592cb9184d8db4f69b9..0000000000000000000000000000000000000000
--- a/app/views/shared/milestones/_record.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
--# @project is present when viewing Project's milestone
-- project = @project || record.project
-- record_type = record.class.table_name
-- base_url_args = [project.namespace.becomes(Namespace), project, record_type]
-
-%li{ id: dom_id(record, 'sortable'),  class: "#{dom_class(record)}-row", 'data-iid' => record.iid, 'data-url' => polymorphic_path(record) }
-  %span
-    - if show_project_name
-      %strong #{project.name} &middot;
-    - elsif show_full_project_name
-      %strong #{project.name_with_namespace} &middot;
-    = link_to_gfm record.title, [project.namespace.becomes(Namespace), project, record], title: record.title
-  %div{class: "#{dom_class(record)}-detail"}
-    = link_to [project.namespace.becomes(Namespace), project, record] do
-      %span{ class: "#{dom_class(record)}-number" } ##{record.iid}
-
-    - record.labels.each do |label|
-      %a{ href: polymorphic_path(base_url_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }) }<
-        = render_colored_label(label)
-
-    - if record.assignee
-      %a{ href: polymorphic_path(base_url_args, { milestone_title: @milestone.title, assignee_id: record.assignee_id, state: 'all' }) }
-        = image_tag(avatar_icon(record.assignee, 16), class: "avatar s16", alt: '')
diff --git a/app/views/shared/milestones/_summary.html.haml b/app/views/shared/milestones/_summary.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..59d4ae29f791f349d13e0bc8903011c5655f3636
--- /dev/null
+++ b/app/views/shared/milestones/_summary.html.haml
@@ -0,0 +1,28 @@
+- project = local_assigns[:project]
+
+.context.prepend-top-default
+  .milestone-summary
+    %h4 Progress
+    %strong= milestone.issues.size
+    issues:
+    %span.milestone-stat
+      %strong= milestone.issues.opened.size
+      open and
+      %strong= milestone.issues.closed.size
+      closed
+    %span.milestone-stat
+      %strong== #{milestone.percent_complete}%
+      complete
+
+    %span.milestone-stat
+      %span.remaining-days= milestone_remaining_days(milestone)
+    %span.pull-right.tab-issues-buttons
+      - if project && can?(current_user, :create_issue, project)
+        = link_to new_namespace_project_issue_path(project.namespace, project, issue: { milestone_id: milestone.id }), class: "btn  btn-grouped", title: "New Issue" do
+          %i.fa.fa-plus
+          New Issue
+      = link_to 'Browse Issues', milestones_browse_issuables_path(milestone, type: :issues), class: "btn btn-grouped"
+    %span.pull-right.tab-merge-requests-buttons.hidden
+      = link_to 'Browse Merge Requests', milestones_browse_issuables_path(milestone, type: :merge_requests), class: "btn btn-grouped"
+
+  = milestone_progress_bar(milestone)
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..57d7ee85a3b3ac27289d39c02e5b5ce21a9c3c31
--- /dev/null
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -0,0 +1,30 @@
+%ul.nav-links.no-top.no-bottom
+  %li.active
+    = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
+      Issues
+      %span.badge= milestone.issues.size
+  %li
+    = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do
+      Merge Requests
+      %span.badge= milestone.merge_requests.size
+  %li
+    = link_to '#tab-participants', 'data-toggle' => 'tab' do
+      Participants
+      %span.badge= milestone.participants.count
+  %li
+    = link_to '#tab-labels', 'data-toggle' => 'tab' do
+      Labels
+      %span.badge= milestone.labels.count
+
+- show_project_name = local_assigns.fetch(:show_project_name, false)
+- show_full_project_name = local_assigns.fetch(:show_full_project_name, false)
+
+.tab-content.milestone-content
+  .tab-pane.active#tab-issues
+    = render 'shared/milestones/issues_tab', issues: milestone.issues, show_project_name: show_project_name, show_full_project_name: show_full_project_name
+  .tab-pane#tab-merge-requests
+    = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name
+  .tab-pane#tab-participants
+    = render 'shared/milestones/participants_tab', users: milestone.participants
+  .tab-pane#tab-labels
+    = render 'shared/milestones/labels_tab', labels: milestone.labels
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4cf1d948b5b952d84f08931b556433b79f0b9e4b
--- /dev/null
+++ b/app/views/shared/milestones/_top.html.haml
@@ -0,0 +1,58 @@
+- page_title milestone.title, "Milestones"
+
+- group = local_assigns[:group]
+
+.detail-page-header
+  .status-box{ class: "status-box-#{milestone.closed? ? 'closed' : 'open'}" }
+    - if milestone.closed?
+      Closed
+    - elsif milestone.expired?
+      Expired
+    - else
+      Open
+  %span.identifier
+    Milestone #{milestone.title}
+  - if milestone.expires_at
+    %span.creator
+      &middot;
+      = milestone.expires_at
+  - if group
+    .pull-right
+      - if can?(current_user, :admin_milestones, group)
+        - if milestone.active?
+          = link_to 'Close Milestone', group_milestone_path(group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
+        - else
+          = link_to 'Reopen Milestone', group_milestone_path(group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
+
+.detail-page-description.gray-content-block.second-block
+  %h2.title
+    = markdown escape_once(milestone.title), pipeline: :single_line
+
+- if milestone.complete? && milestone.active?
+  .alert.alert-success.prepend-top-default
+    - close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
+    %span All issues for this milestone are closed. #{close_msg}
+
+.table-holder
+  %table.table
+    %thead
+      %tr
+        %th Project
+        %th Open issues
+        %th State
+        %th Due date
+    - milestone.milestones.each do |ms|
+      %tr
+        %td
+          - project_name = group ? ms.project.name : ms.project.name_with_namespace
+          = link_to project_name, namespace_project_milestone_path(ms.project.namespace, ms.project, ms)
+        %td
+          = ms.issues.opened.count
+        %td
+          - if ms.closed?
+            Closed
+          - else
+            Open
+        %td
+          = ms.expires_at
+
diff --git a/config/application.rb b/config/application.rb
index fee8637a4cb746bb9ccfc22ed988c8f016c23abf..28684a3e578cf701c3f50241120757bb964a5a24 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -15,7 +15,6 @@ module Gitlab
 
     # Custom directories with classes and modules you want to be autoloadable.
     config.autoload_paths.push(*%W(#{config.root}/lib
-                                   #{config.root}/app/decorators
                                    #{config.root}/app/models/hooks
                                    #{config.root}/app/models/concerns
                                    #{config.root}/app/models/project_services
diff --git a/features/group/milestones.feature b/features/group/milestones.feature
index a097e07583a7ae237585b35e22acb1e40ac73712..d6c05df9840ed4f68ccb3488fe0ef9c5dcc98a7e 100644
--- a/features/group/milestones.feature
+++ b/features/group/milestones.feature
@@ -45,4 +45,3 @@ Feature: Group Milestones
     And I click on one group milestone
     And I click on the "Labels" tab
     Then I should see the list of labels
-    And I should see the project name in the Label row
diff --git a/features/steps/group/milestones.rb b/features/steps/group/milestones.rb
index ce4e52181ce9f8042cdfa925fe1e04843a933f78..a167d25983777be8309af1c035edf1646d00d693 100644
--- a/features/steps/group/milestones.rb
+++ b/features/steps/group/milestones.rb
@@ -96,14 +96,6 @@ class Spinach::Features::GroupMilestones < Spinach::FeatureSteps
     end
   end
 
-  step 'I should see the project name in the Label row' do
-    page.within('#tab-labels') do
-      @global_milestone.projects.each do |project|
-        expect(page).to have_content project.name
-      end
-    end
-  end
-
   private
 
   def group_milestone
diff --git a/features/steps/project/issues/milestones.rb b/features/steps/project/issues/milestones.rb
index e2eda511497f4d6e4bb7974e41f94b8046d04768..4faa0f4707ce85dbb3ab4c5c6bcfd7414cf01bea 100644
--- a/features/steps/project/issues/milestones.rb
+++ b/features/steps/project/issues/milestones.rb
@@ -59,7 +59,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps
   end
 
   step 'I should see 3 issues' do
-    expect(page).to have_selector('#tab-issues li.issue-row', count: 4)
+    expect(page).to have_selector('#tab-issues li.issuable-row', count: 4)
   end
 
   step 'I click link to remove milestone' do
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 1b1380ce4e2c3e31996ad00d678837a633531de5..28f13100d15ae8595a2ab3c4f11c43afa4815fcb 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -60,7 +60,7 @@ describe Milestone, models: true do
     end
 
     it "should recover from dividing by zero" do
-      expect(milestone.issues).to receive(:count).and_return(0)
+      expect(milestone.issues).to receive(:size).and_return(0)
       expect(milestone.percent_complete).to eq(0)
     end
   end
@@ -114,7 +114,6 @@ describe Milestone, models: true do
     end
 
     it { expect(milestone.closed_items_count).to eq(1) }
-    it { expect(milestone.open_items_count).to eq(2) }
     it { expect(milestone.total_items_count).to eq(3) }
     it { expect(milestone.is_empty?).to be_falsey }
   end