Commit c25457a7 authored by Nathan Friend's avatar Nathan Friend Committed by Kamil Trzciński

Add links from milestones to associated releases

This commit adds links inside milestone blocks to the releases
associated with the milestone (if any).
parent 0d753e47
...@@ -30,7 +30,8 @@ $status-box-line-height: 26px; ...@@ -30,7 +30,8 @@ $status-box-line-height: 26px;
margin-bottom: $gl-padding-4; margin-bottom: $gl-padding-4;
} }
.milestone-progress { .milestone-progress,
.milestone-release-links {
a { a {
color: $blue-600; color: $blue-600;
} }
...@@ -238,10 +239,6 @@ $status-box-line-height: 26px; ...@@ -238,10 +239,6 @@ $status-box-line-height: 26px;
} }
} }
.milestone-range {
color: $gl-text-color-tertiary;
}
@include media-breakpoint-down(xs) { @include media-breakpoint-down(xs) {
.milestone-banner-text, .milestone-banner-text,
.milestone-banner-link { .milestone-banner-link {
......
...@@ -170,6 +170,15 @@ module MilestonesHelper ...@@ -170,6 +170,15 @@ module MilestonesHelper
content.join('<br />').html_safe content.join('<br />').html_safe
end end
def recent_releases_with_counts(milestone)
total_count = milestone.releases.size
return [[], 0, 0] if total_count == 0
recent_releases = milestone.releases.recent.to_a
more_count = total_count - recent_releases.size
[recent_releases, total_count, more_count]
end
def milestone_tooltip_due_date(milestone) def milestone_tooltip_due_date(milestone)
if milestone.due_date if milestone.due_date
"#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})" "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})"
......
...@@ -11,7 +11,7 @@ class GlobalMilestone ...@@ -11,7 +11,7 @@ class GlobalMilestone
delegate :title, :state, :due_date, :start_date, :participants, :project, delegate :title, :state, :due_date, :start_date, :participants, :project,
:group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title,
:milestoneish_id, :resource_parent, to: :milestone :milestoneish_id, :resource_parent, :releases, to: :milestone
def to_hash def to_hash
{ {
......
...@@ -28,12 +28,16 @@ class Release < ApplicationRecord ...@@ -28,12 +28,16 @@ class Release < ApplicationRecord
scope :sorted, -> { order(released_at: :desc) } scope :sorted, -> { order(released_at: :desc) }
scope :preloaded, -> { includes(project: :namespace) } scope :preloaded, -> { includes(project: :namespace) }
scope :with_project_and_namespace, -> { includes(project: :namespace) }
scope :recent, -> { sorted.limit(MAX_NUMBER_TO_DISPLAY) }
delegate :repository, to: :project delegate :repository, to: :project
after_commit :create_evidence!, on: :create after_commit :create_evidence!, on: :create
after_commit :notify_new_release, on: :create after_commit :notify_new_release, on: :create
MAX_NUMBER_TO_DISPLAY = 3
def to_param def to_param
CGI.escape(tag) CGI.escape(tag)
end end
......
...@@ -12,8 +12,20 @@ ...@@ -12,8 +12,20 @@
- if @project || milestone.is_a?(GlobalMilestone) || milestone.group_milestone? - if @project || milestone.is_a?(GlobalMilestone) || milestone.group_milestone?
- if milestone.due_date || milestone.start_date - if milestone.due_date || milestone.start_date
.milestone-range.append-bottom-5 .text-tertiary.append-bottom-5
= milestone_date_range(milestone) = milestone_date_range(milestone)
- recent_releases, total_count, more_count = recent_releases_with_counts(milestone)
- unless total_count.zero?
.text-tertiary.append-bottom-5.milestone-release-links
= icon('rocket')
= n_('Release', 'Releases', total_count)
- recent_releases.each do |release|
= link_to release.name, project_releases_path(release.project, anchor: release.tag)
- unless release == recent_releases.last
&bull;
- if total_count > recent_releases.count
&bull;
= link_to n_('%{count} more release', '%{count} more releases', more_count) % { count: more_count }, project_releases_path(milestone.project)
%div %div
= render('shared/milestone_expired', milestone: milestone) = render('shared/milestone_expired', milestone: milestone)
- if milestone.group_milestone? - if milestone.group_milestone?
......
---
title: Add links to associated releases on the Milestones page
merge_request: 16558
author:
type: added
...@@ -210,6 +210,11 @@ msgstr "" ...@@ -210,6 +210,11 @@ msgstr ""
msgid "%{count} more assignees" msgid "%{count} more assignees"
msgstr "" msgstr ""
msgid "%{count} more release"
msgid_plural "%{count} more releases"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} of %{required} approvals from %{name}" msgid "%{count} of %{required} approvals from %{name}"
msgstr "" msgstr ""
...@@ -13803,7 +13808,9 @@ msgid "Related merge requests" ...@@ -13803,7 +13808,9 @@ msgid "Related merge requests"
msgstr "" msgstr ""
msgid "Release" msgid "Release"
msgstr "" msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
msgid "Release notes" msgid "Release notes"
msgstr "" msgstr ""
......
...@@ -34,4 +34,31 @@ describe "User views milestones" do ...@@ -34,4 +34,31 @@ describe "User views milestones" do
.and have_content(closed_issue.title) .and have_content(closed_issue.title)
end end
end end
context "with associated releases" do
set(:first_release) { create(:release, project: project, name: "The first release", milestones: [milestone], released_at: Time.zone.parse('2019-10-07')) }
context "with a single associated release" do
it "shows the associated release" do
expect(page).to have_content("Release #{first_release.name}")
expect(page).to have_link(first_release.name, href: project_releases_path(project, anchor: first_release.tag))
end
end
context "with lots of associated releases" do
set(:second_release) { create(:release, project: project, name: "The second release", milestones: [milestone], released_at: first_release.released_at + 1.day) }
set(:third_release) { create(:release, project: project, name: "The third release", milestones: [milestone], released_at: second_release.released_at + 1.day) }
set(:fourth_release) { create(:release, project: project, name: "The fourth release", milestones: [milestone], released_at: third_release.released_at + 1.day) }
set(:fifth_release) { create(:release, project: project, name: "The fifth release", milestones: [milestone], released_at: fourth_release.released_at + 1.day) }
it "shows the associated releases and the truncation text" do
expect(page).to have_content("Releases #{fifth_release.name}#{fourth_release.name}#{third_release.name} • 2 more releases")
expect(page).to have_link(fifth_release.name, href: project_releases_path(project, anchor: fifth_release.tag))
expect(page).to have_link(fourth_release.name, href: project_releases_path(project, anchor: fourth_release.tag))
expect(page).to have_link(third_release.name, href: project_releases_path(project, anchor: third_release.tag))
expect(page).to have_link("2 more releases", href: project_releases_path(project))
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