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
This commit is contained in:
commit
513629f346
7 changed files with 99 additions and 12 deletions
|
@ -87,6 +87,7 @@ v 8.12.0
|
|||
- Fix markdown anchor icon interaction (ClemMakesApps)
|
||||
- Test migration paths from 8.5 until current release !4874
|
||||
- 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)
|
||||
- Require confirmation when not logged in for unsubscribe links !6223 (Maximiliano Perez Coto)
|
||||
- Add `wiki_page_events` to project hook APIs (Ben Boeckel)
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
max-width: 90%;
|
||||
}
|
||||
|
||||
li.milestone {
|
||||
.milestones {
|
||||
.milestone {
|
||||
padding: 10px 16px;
|
||||
|
||||
h4 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -11,6 +14,7 @@ li.milestone {
|
|||
height: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.milestone-content {
|
||||
.issues-count {
|
||||
|
@ -64,3 +68,14 @@ li.milestone {
|
|||
border-bottom: 1px solid $border-color;
|
||||
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
|
|||
milestone.issues.with_label(label.title).send(state).size
|
||||
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)
|
||||
options = {
|
||||
class: 'progress-bar progress-bar-success',
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
- if @project
|
||||
- counts = milestone_counts(@project.milestones)
|
||||
|
||||
%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
|
||||
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
|
||||
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
|
||||
All
|
||||
- if @project
|
||||
%span.badge #{counts[:all]}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
- if @project
|
||||
.row
|
||||
.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?
|
||||
= link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-xs btn-grouped" do
|
||||
Edit
|
||||
|
|
|
@ -3,10 +3,15 @@ FactoryGirl.define do
|
|||
title
|
||||
project
|
||||
|
||||
trait :closed do
|
||||
state :closed
|
||||
trait :active do
|
||||
state "active"
|
||||
end
|
||||
|
||||
trait :closed do
|
||||
state "closed"
|
||||
end
|
||||
|
||||
factory :active_milestone, traits: [:active]
|
||||
factory :closed_milestone, traits: [:closed]
|
||||
end
|
||||
end
|
||||
|
|
33
spec/helpers/milestones_helper_spec.rb
Normal file
33
spec/helpers/milestones_helper_spec.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
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
|
Loading…
Reference in a new issue