Commit 513629f3 authored by Fatih Acet's avatar Fatih Acet

Merge branch 'gitlab-ce-milestone-tab-badges' into 'master'

Milestone tab badges

### What does this MR do?
Adds count badges to the tabs on the Milestone page to mirror the Issue page.

### Are there points in the code the reviewer needs to double check?
CSS: Padding was added to the `.milestone` element to make expired milestones look good.

### Why was this MR needed?
For consistency with other tabs

### What are the relevant issue numbers?
Closes #20114 

### Screenshots (if relevant)

**Before**
<img src="/uploads/1f75853a863a9058ee409916b7ee4057/Screen_Shot_2016-07-22_at_13.22.20.png" width="362">

**After**
<img src="/uploads/8a058290850f571db249dd9b23f5138d/Screen_Shot_2016-07-22_at_13.21.58.png"  width="303">

![Screen_Shot_2016-08-23_at_1.42.56_AM](/uploads/b072dc6bdf505b2fce46660beaf0eae7/Screen_Shot_2016-08-23_at_1.42.56_AM.png)

![Screen_Shot_2016-08-23_at_1.43.15_AM](/uploads/e7440bf2aa628aa4dba63863083699c0/Screen_Shot_2016-08-23_at_1.43.15_AM.png)

### Does this MR meet the acceptance criteria?

- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- Tests
  - [x] Added for this feature/bug
  - [x] All builds are passing
- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)

See merge request !5946
parents d4007fd4 8499de19
...@@ -87,6 +87,7 @@ v 8.12.0 ...@@ -87,6 +87,7 @@ v 8.12.0
- Fix markdown anchor icon interaction (ClemMakesApps) - Fix markdown anchor icon interaction (ClemMakesApps)
- Test migration paths from 8.5 until current release !4874 - Test migration paths from 8.5 until current release !4874
- Replace animateEmoji timeout with eventListener (ClemMakesApps) - Replace animateEmoji timeout with eventListener (ClemMakesApps)
- Show badges in Milestone tabs. !5946 (Dan Rowden)
- Optimistic locking for Issues and Merge Requests (title and description overriding prevention) - Optimistic locking for Issues and Merge Requests (title and description overriding prevention)
- Require confirmation when not logged in for unsubscribe links !6223 (Maximiliano Perez Coto) - Require confirmation when not logged in for unsubscribe links !6223 (Maximiliano Perez Coto)
- Add `wiki_page_events` to project hook APIs (Ben Boeckel) - Add `wiki_page_events` to project hook APIs (Ben Boeckel)
......
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
max-width: 90%; max-width: 90%;
} }
li.milestone { .milestones {
.milestone {
padding: 10px 16px;
h4 { h4 {
font-weight: bold; font-weight: bold;
} }
...@@ -10,6 +13,7 @@ li.milestone { ...@@ -10,6 +13,7 @@ li.milestone {
.progress { .progress {
height: 6px; height: 6px;
} }
}
} }
.milestone-content { .milestone-content {
...@@ -64,3 +68,14 @@ li.milestone { ...@@ -64,3 +68,14 @@ li.milestone {
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
padding: 20px 0; padding: 20px 0;
} }
@media (max-width: $screen-sm-min) {
.milestone-actions {
@include clearfix();
padding-top: $gl-vert-padding;
.btn:first-child {
margin-left: 0;
}
}
}
...@@ -35,6 +35,30 @@ module MilestonesHelper ...@@ -35,6 +35,30 @@ module MilestonesHelper
milestone.issues.with_label(label.title).send(state).size milestone.issues.with_label(label.title).send(state).size
end end
# Returns count of milestones for different states
# Uses explicit hash keys as the 'opened' state URL params differs from the db value
# and we need to add the total
def milestone_counts(milestones)
counts = milestones.reorder(nil).group(:state).count
{
opened: counts['active'] || 0,
closed: counts['closed'] || 0,
all: counts.values.sum || 0
}
end
# Show 'active' class if provided GET param matches check
# `or_blank` allows the function to return 'active' when given an empty param
# Could be refactored to be simpler but that may make it harder to read
def milestone_class_for_state(param, check, match_blank_param = false)
if match_blank_param
'active' if param.blank? || param == check
else
'active' if param == check
end
end
def milestone_progress_bar(milestone) def milestone_progress_bar(milestone)
options = { options = {
class: 'progress-bar progress-bar-success', class: 'progress-bar progress-bar-success',
......
- if @project
- counts = milestone_counts(@project.milestones)
%ul.nav-links %ul.nav-links
%li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} %li{class: milestone_class_for_state(params[:state], 'opened', true)}
= link_to milestones_filter_path(state: 'opened') do = link_to milestones_filter_path(state: 'opened') do
Open Open
%li{class: ("active" if params[:state] == 'closed')} - if @project
%span.badge #{counts[:opened]}
%li{class: milestone_class_for_state(params[:state], 'closed')}
= link_to milestones_filter_path(state: 'closed') do = link_to milestones_filter_path(state: 'closed') do
Closed Closed
%li{class: ("active" if params[:state] == 'all')} - if @project
%span.badge #{counts[:closed]}
%li{class: milestone_class_for_state(params[:state], 'all')}
= link_to milestones_filter_path(state: 'all') do = link_to milestones_filter_path(state: 'all') do
All All
- if @project
%span.badge #{counts[:all]}
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
- if @project - if @project
.row .row
.col-sm-6= render('shared/milestone_expired', milestone: milestone) .col-sm-6= render('shared/milestone_expired', milestone: milestone)
.col-sm-6 .col-sm-6.milestone-actions
- if can?(current_user, :admin_milestone, milestone.project) and milestone.active? - 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 btn-grouped" do = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs btn-grouped" do
Edit Edit
......
...@@ -3,10 +3,15 @@ FactoryGirl.define do ...@@ -3,10 +3,15 @@ FactoryGirl.define do
title title
project project
trait :active do
state "active"
end
trait :closed do trait :closed do
state :closed state "closed"
end end
factory :active_milestone, traits: [:active]
factory :closed_milestone, traits: [:closed] factory :closed_milestone, traits: [:closed]
end end
end end
require 'spec_helper'
describe MilestonesHelper do
describe '#milestone_counts' do
let(:project) { FactoryGirl.create(:project) }
let(:counts) { helper.milestone_counts(project.milestones) }
context 'when there are milestones' do
let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) }
let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) }
let!(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) }
it 'returns the correct counts' do
expect(counts).to eq(opened: 2, closed: 1, all: 3)
end
end
context 'when there are only milestones of one type' do
let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) }
let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) }
it 'returns the correct counts' do
expect(counts).to eq(opened: 2, closed: 0, all: 2)
end
end
context 'when there are no milestones' do
it 'returns the correct counts' do
expect(counts).to eq(opened: 0, closed: 0, all: 0)
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