From ca6fd8841e3bf1d6db9370fd7aa7934b320550e4 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 25 Jun 2014 11:15:27 +0200 Subject: [PATCH 01/16] Add group milestones routes and controller. --- app/controllers/groups/milestones_controller.rb | 7 +++++++ app/views/groups/milestones/index.html.haml | 0 app/views/layouts/nav/_group.html.haml | 5 +++++ config/routes.rb | 2 ++ 4 files changed, 14 insertions(+) create mode 100644 app/controllers/groups/milestones_controller.rb create mode 100644 app/views/groups/milestones/index.html.haml diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb new file mode 100644 index 0000000000..fc53810512 --- /dev/null +++ b/app/controllers/groups/milestones_controller.rb @@ -0,0 +1,7 @@ +class Groups::MilestonesController < ApplicationController + layout 'group' + + def index + @group = Group.find_by(path: params[:group_id]) + end +end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index d306e1eeb5..5fa14bd0d9 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -12,6 +12,11 @@ Merge Requests - if current_user %span.count= current_user.cared_merge_requests.opened.of_group(@group).count + = nav_link(path: 'groups#milestones') do + = link_to merge_requests_group_path(@group) do + Milestones + - if current_user + %span.count= current_user.cared_merge_requests.opened.of_group(@group).count = nav_link(path: 'groups#members') do = link_to "Members", members_group_path(@group) diff --git a/config/routes.rb b/config/routes.rb index 14ff52f387..244cb33989 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -151,8 +151,10 @@ Gitlab::Application.routes.draw do end resources :users_groups, only: [:create, :update, :destroy] + scope module: :groups do resource :avatar, only: [:destroy] + resources :milestones end end From aaba993352d65ad645215083cd6a4a46006f4b32 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 25 Jun 2014 12:30:57 +0200 Subject: [PATCH 02/16] Skeleton of the group milestone index page. --- app/helpers/groups_helper.rb | 12 +++++++++++ app/views/groups/_filter.html.haml | 12 +++++++++++ .../groups/milestones/_milestone.html.haml | 13 ++++++++++++ app/views/groups/milestones/index.html.haml | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 app/views/groups/_filter.html.haml create mode 100644 app/views/groups/milestones/_milestone.html.haml diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index cfc9a572ca..0762a6925b 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -31,6 +31,18 @@ module GroupsHelper end title + end + def group_filter_path(entity, options={}) + exist_opts = { + state: params[:state], + scope: params[:scope] + } + + options = exist_opts.merge(options) + + path = request.path + path << "?#{options.to_param}" + path end end diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml new file mode 100644 index 0000000000..2e97ea40af --- /dev/null +++ b/app/views/groups/_filter.html.haml @@ -0,0 +1,12 @@ += form_tag group_filter_path(entity), method: 'get' do + %fieldset + %ul.nav.nav-pills.nav-stacked + %li{class: ("active" if !params[:status])} + = link_to group_filter_path(entity, status: nil) do + Active + %li{class: ("active" if params[:status] == 'closed')} + = link_to group_filter_path(entity, status: 'closed') do + Closed + %li{class: ("active" if params[:status] == 'all')} + = link_to group_filter_path(entity, status: 'all') do + All diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml new file mode 100644 index 0000000000..1f8488782c --- /dev/null +++ b/app/views/groups/milestones/_milestone.html.haml @@ -0,0 +1,13 @@ +- if @milestones.any? + - @issues.group_by(&:project).each do |group| + .panel.panel-default.panel-small + - project = group[0] + .panel-heading + = link_to_project project + = link_to 'show all', project_issues_path(project), class: 'pull-right' + + %ul.well-list.issues-list + - group[1].each do |issue| + = render 'projects/issues/issue', issue: issue + = paginate @issues, theme: "gitlab" + diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index e69de29bb2..8ba325d94a 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -0,0 +1,21 @@ +%h3.page-title + Milestones + %span.pull-right milestones + +%p.light + Only milestones from + %strong #{@group.name} + group are listed here. + +%hr + +.row + .fixed.sidebar-expand-button.hidden-lg.hidden-md + %i.icon-list.icon-2x + .col-md-3.responsive-side + = render 'groups/filter', entity: 'milestones' + .col-md-9 + - if @milestones.blank? + .nothing-here-block No milestones to show + - else + = render 'groups/milestones/milestone' From e1afea777a6f0d2e28adc2765c9445cb10bd25f8 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 25 Jun 2014 13:30:23 +0200 Subject: [PATCH 03/16] Show title of milestone. --- .../groups/milestones_controller.rb | 3 +++ .../groups/milestones/_milestone.html.haml | 13 ------------- app/views/groups/milestones/index.html.haml | 19 +++++++++++++++---- 3 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 app/views/groups/milestones/_milestone.html.haml diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index fc53810512..88a709024d 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -3,5 +3,8 @@ class Groups::MilestonesController < ApplicationController def index @group = Group.find_by(path: params[:group_id]) + project_ids = @group.projects + project_milestones = Milestone.where(project_id: project_ids) + @milestones = project_milestones end end diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml deleted file mode 100644 index 1f8488782c..0000000000 --- a/app/views/groups/milestones/_milestone.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- if @milestones.any? - - @issues.group_by(&:project).each do |group| - .panel.panel-default.panel-small - - project = group[0] - .panel-heading - = link_to_project project - = link_to 'show all', project_issues_path(project), class: 'pull-right' - - %ul.well-list.issues-list - - group[1].each do |issue| - = render 'projects/issues/issue', issue: issue - = paginate @issues, theme: "gitlab" - diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 8ba325d94a..a9cf06b817 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -15,7 +15,18 @@ .col-md-3.responsive-side = render 'groups/filter', entity: 'milestones' .col-md-9 - - if @milestones.blank? - .nothing-here-block No milestones to show - - else - = render 'groups/milestones/milestone' + .panel.panel-default + %ul.well-list + - if @milestones.blank? + %li + .nothing-here-block No milestones to show + - else + - @milestones.group_by(&:title).each do |milestone| + %li{class: "milestone milestone-open", id: 1 } + .pull-right + = link_to root_path, class: "btn btn-small edit-milestone-link btn-grouped" do + %i.icon-edit + Edit + = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" + %h4 + = link_to_gfm truncate(milestone.first, length: 100), root_path From 58570880f0ffde173de31a0093f6a9d243467fef Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 25 Jun 2014 16:19:03 +0200 Subject: [PATCH 04/16] Create group milestones service. --- .../groups/milestones_controller.rb | 2 + app/services/milestones/group_service.rb | 73 +++++++++++++++++++ app/views/groups/milestones/index.html.haml | 25 ++++++- 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 app/services/milestones/group_service.rb diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 88a709024d..e85ef3ff25 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -6,5 +6,7 @@ class Groups::MilestonesController < ApplicationController project_ids = @group.projects project_milestones = Milestone.where(project_id: project_ids) @milestones = project_milestones + @group_milestones = Milestones::GroupService.new(@group, current_user, project_milestones) end + end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb new file mode 100644 index 0000000000..1655100e01 --- /dev/null +++ b/app/services/milestones/group_service.rb @@ -0,0 +1,73 @@ +module Milestones + class GroupService < Milestones::BaseService + def initialize(group, user, project_milestones) + @group = group + @user = user + @project_milestones = project_milestones.group_by(&:title) + end + + def titles + @project_milestones.map{ |title, milestone| title } + end + + def project_names + names = {} + @project_milestones.map do |title, milestone| + projects = milestone.map{|m| m.project.name } + names.store(title, projects) + end + names + end + + def issue_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.count }.sum } + end + + def mr_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.count }.sum } + end + + def open_issues_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.opened.count }.sum } + end + + def closed_issues_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.closed.count }.sum } + end + + def open_mr_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.opened.count }.sum } + end + + def close_mr_count + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.closed.count }.sum } + end + + def open_items_count + open_issues_count.merge(open_mr_count){ |title,issue,mr| issue + mr } + end + + def closed_items_count + closed_issues_count.merge(close_mr_count){ |title,issue,mr| issue + mr } + end + + def total_items_count + issue_count.merge(mr_count){ |title,issue,mr| issue + mr } + end + + def percent_complete + percentage_per_milestone = {} + closed_items_count.map do |title, closed_items| + total_items = total_items_count[title] + percentage = begin + ((closed_items * 100) / total_items).abs + rescue ZeroDivisionError + 100 + end + percentage_per_milestone.store(title, percentage) + end + percentage_per_milestone + end + + end +end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index a9cf06b817..b5d68153a9 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -17,11 +17,11 @@ .col-md-9 .panel.panel-default %ul.well-list - - if @milestones.blank? + - if @group_milestones.blank? %li .nothing-here-block No milestones to show - else - - @milestones.group_by(&:title).each do |milestone| + - @group_milestones.titles.each do |title| %li{class: "milestone milestone-open", id: 1 } .pull-right = link_to root_path, class: "btn btn-small edit-milestone-link btn-grouped" do @@ -29,4 +29,23 @@ Edit = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" %h4 - = link_to_gfm truncate(milestone.first, length: 100), root_path + = link_to_gfm truncate(title, length: 100), root_path + - if false + %span.muted Empty + - else + %div + %div + = link_to root_path do + = pluralize @group_milestones.issue_count[title], 'Issue' +   + = link_to root_path do + = pluralize @group_milestones.mr_count[title], 'Merge Request' +   + %span.light #{@group_milestones.percent_complete[title]}% complete + .progress.progress-info + .progress-bar{style: "width: #{@group_milestones.percent_complete[title]}%;"} + %div + %br + - @group_milestones.project_names[title].each do |name| + %span.label.label-default + = name From 8e8c074205f4c85238309f4e21e80748f09d0ec8 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 26 Jun 2014 09:41:36 +0200 Subject: [PATCH 05/16] Reuse existing milestones counting. --- app/services/milestones/group_service.rb | 4 ++-- app/views/groups/milestones/index.html.haml | 2 +- app/views/layouts/nav/_group.html.haml | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb index 1655100e01..74bf126652 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/group_service.rb @@ -44,11 +44,11 @@ module Milestones end def open_items_count - open_issues_count.merge(open_mr_count){ |title,issue,mr| issue + mr } + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.open_items_count }.sum } end def closed_items_count - closed_issues_count.merge(close_mr_count){ |title,issue,mr| issue + mr } + @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.closed_items_count }.sum } end def total_items_count diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b5d68153a9..2e51d74ca8 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,6 +1,6 @@ %h3.page-title Milestones - %span.pull-right milestones + %span.pull-right #{@group_milestones.titles.count} milestones %p.light Only milestones from diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 5fa14bd0d9..429848e3cb 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -13,10 +13,8 @@ - if current_user %span.count= current_user.cared_merge_requests.opened.of_group(@group).count = nav_link(path: 'groups#milestones') do - = link_to merge_requests_group_path(@group) do + = link_to group_milestones_path(@group) do Milestones - - if current_user - %span.count= current_user.cared_merge_requests.opened.of_group(@group).count = nav_link(path: 'groups#members') do = link_to "Members", members_group_path(@group) From 0723bf1afaaf13ddcb58c211161389052d18e501 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 26 Jun 2014 10:57:36 +0200 Subject: [PATCH 06/16] Move group milestone processing from service to model. --- .../groups/milestones_controller.rb | 3 +- app/models/group_milestone.rb | 41 ++++++++++++ app/services/milestones/group_service.rb | 67 +------------------ app/views/groups/milestones/index.html.haml | 19 +++--- 4 files changed, 53 insertions(+), 77 deletions(-) create mode 100644 app/models/group_milestone.rb diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index e85ef3ff25..cb5fed0bc3 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -5,8 +5,7 @@ class Groups::MilestonesController < ApplicationController @group = Group.find_by(path: params[:group_id]) project_ids = @group.projects project_milestones = Milestone.where(project_id: project_ids) - @milestones = project_milestones - @group_milestones = Milestones::GroupService.new(@group, current_user, project_milestones) + @group_milestones = Milestones::GroupService.new(project_milestones).execute end end diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb new file mode 100644 index 0000000000..c2fb3a5ede --- /dev/null +++ b/app/models/group_milestone.rb @@ -0,0 +1,41 @@ +class GroupMilestone + + def initialize(title, milestones) + @title = title + @milestones = milestones + end + + def title + @title + end + + def milestones + @milestones + end + + def project_names + milestones.map{ |milestone| milestone.project.name } + end + + def issue_count + milestones.map{ |milestone| milestone.issues.count }.sum + end + + def merge_requests_count + milestones.map{ |milestone| milestone.merge_requests.count }.sum + end + + def closed_items_count + milestones.map{ |milestone| milestone.closed_items_count }.sum + end + + def total_items_count + milestones.map{ |milestone| milestone.total_items_count }.sum + end + + def percent_complete + ((closed_items_count * 100) / total_items_count).abs + rescue ZeroDivisionError + 100 + end +end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb index 74bf126652..3a7e092a77 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/group_service.rb @@ -1,72 +1,11 @@ module Milestones class GroupService < Milestones::BaseService - def initialize(group, user, project_milestones) - @group = group - @user = user + def initialize(project_milestones) @project_milestones = project_milestones.group_by(&:title) end - def titles - @project_milestones.map{ |title, milestone| title } - end - - def project_names - names = {} - @project_milestones.map do |title, milestone| - projects = milestone.map{|m| m.project.name } - names.store(title, projects) - end - names - end - - def issue_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.count }.sum } - end - - def mr_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.count }.sum } - end - - def open_issues_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.opened.count }.sum } - end - - def closed_issues_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.issues.closed.count }.sum } - end - - def open_mr_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.opened.count }.sum } - end - - def close_mr_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.merge_requests.closed.count }.sum } - end - - def open_items_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.open_items_count }.sum } - end - - def closed_items_count - @project_milestones.merge(@project_milestones){ |title, milestone| milestone.map{|m| m.closed_items_count }.sum } - end - - def total_items_count - issue_count.merge(mr_count){ |title,issue,mr| issue + mr } - end - - def percent_complete - percentage_per_milestone = {} - closed_items_count.map do |title, closed_items| - total_items = total_items_count[title] - percentage = begin - ((closed_items * 100) / total_items).abs - rescue ZeroDivisionError - 100 - end - percentage_per_milestone.store(title, percentage) - end - percentage_per_milestone + def execute + @project_milestones.map{ |title, milestone| GroupMilestone.new(title, milestone) } end end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 2e51d74ca8..97cc88db52 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,6 +1,6 @@ %h3.page-title Milestones - %span.pull-right #{@group_milestones.titles.count} milestones + %span.pull-right #{@group_milestones.count} milestones %p.light Only milestones from @@ -21,31 +21,28 @@ %li .nothing-here-block No milestones to show - else - - @group_milestones.titles.each do |title| + - @group_milestones.each do |milestone| %li{class: "milestone milestone-open", id: 1 } .pull-right - = link_to root_path, class: "btn btn-small edit-milestone-link btn-grouped" do - %i.icon-edit - Edit = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" %h4 - = link_to_gfm truncate(title, length: 100), root_path + = link_to_gfm truncate(milestone.title, length: 100), root_path - if false %span.muted Empty - else %div %div = link_to root_path do - = pluralize @group_milestones.issue_count[title], 'Issue' + = pluralize milestone.issue_count, 'Issue'   = link_to root_path do - = pluralize @group_milestones.mr_count[title], 'Merge Request' + = pluralize milestone.merge_requests_count, 'Merge Request'   - %span.light #{@group_milestones.percent_complete[title]}% complete + %span.light #{milestone.percent_complete}% complete .progress.progress-info - .progress-bar{style: "width: #{@group_milestones.percent_complete[title]}%;"} + .progress-bar{style: "width: #{milestone.percent_complete}%;"} %div %br - - @group_milestones.project_names[title].each do |name| + - milestone.project_names.each do |name| %span.label.label-default = name From 4ca8a175a2695dd2fc28084253a4471bad30bf00 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 26 Jun 2014 11:58:40 +0200 Subject: [PATCH 07/16] Filter group milestones. --- .../groups/milestones_controller.rb | 10 +++++ app/helpers/groups_helper.rb | 3 +- app/models/group_milestone.rb | 9 ++++ app/views/groups/_filter.html.haml | 4 +- app/views/groups/milestones/index.html.haml | 42 +++++++++---------- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index cb5fed0bc3..5e810942d1 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -6,6 +6,16 @@ class Groups::MilestonesController < ApplicationController project_ids = @group.projects project_milestones = Milestone.where(project_id: project_ids) @group_milestones = Milestones::GroupService.new(project_milestones).execute + @group_milestones = case params[:status] + when 'all'; @group_milestones + when 'closed'; status('closed') + else status('active') + end end + private + + def status(state) + @group_milestones.map{ |milestone| next if milestone.state != state; milestone }.compact + end end diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 0762a6925b..0dc53dedeb 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -35,8 +35,7 @@ module GroupsHelper def group_filter_path(entity, options={}) exist_opts = { - state: params[:state], - scope: params[:scope] + status: params[:status] } options = exist_opts.merge(options) diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index c2fb3a5ede..132c0eb249 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -38,4 +38,13 @@ class GroupMilestone rescue ZeroDivisionError 100 end + + def state + state = milestones.map{ |milestone| milestone.state } + if state.all?{ |milestone_state| milestone_state == 'active' } + 'active' + else + 'closed' + end + end end diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml index 2e97ea40af..393be3f1d1 100644 --- a/app/views/groups/_filter.html.haml +++ b/app/views/groups/_filter.html.haml @@ -1,8 +1,8 @@ = form_tag group_filter_path(entity), method: 'get' do %fieldset %ul.nav.nav-pills.nav-stacked - %li{class: ("active" if !params[:status])} - = link_to group_filter_path(entity, status: nil) do + %li{class: ("active" if (params[:status] == 'active' || !params[:status]))} + = link_to group_filter_path(entity, status: 'active') do Active %li{class: ("active" if params[:status] == 'closed')} = link_to group_filter_path(entity, status: 'closed') do diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 97cc88db52..9ce8bf32ae 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -13,7 +13,7 @@ .fixed.sidebar-expand-button.hidden-lg.hidden-md %i.icon-list.icon-2x .col-md-3.responsive-side - = render 'groups/filter', entity: 'milestones' + = render 'groups/filter', entity: 'milestone' .col-md-9 .panel.panel-default %ul.well-list @@ -22,27 +22,25 @@ .nothing-here-block No milestones to show - else - @group_milestones.each do |milestone| - %li{class: "milestone milestone-open", id: 1 } - .pull-right - = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" + %li{class: "milestone milestone-#{milestone.state == 'closed' ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } + - unless milestone.state == 'closed' + .pull-right + = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" %h4 = link_to_gfm truncate(milestone.title, length: 100), root_path - - if false - %span.muted Empty - - else + %div %div - %div - = link_to root_path do - = pluralize milestone.issue_count, 'Issue' -   - = link_to root_path do - = pluralize milestone.merge_requests_count, 'Merge Request' -   - %span.light #{milestone.percent_complete}% complete - .progress.progress-info - .progress-bar{style: "width: #{milestone.percent_complete}%;"} - %div - %br - - milestone.project_names.each do |name| - %span.label.label-default - = name + = link_to root_path do + = pluralize milestone.issue_count, 'Issue' +   + = link_to root_path do + = pluralize milestone.merge_requests_count, 'Merge Request' +   + %span.light #{milestone.percent_complete}% complete + .progress.progress-info + .progress-bar{style: "width: #{milestone.percent_complete}%;"} + %div + %br + - milestone.project_names.each do |name| + %span.label.label-default + = name From f0af302c8323cf18943d6de5854bbbaa32d891a9 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 26 Jun 2014 13:32:35 +0200 Subject: [PATCH 08/16] Close and reopen group milestones. --- .../groups/milestones_controller.rb | 29 +++++++++++++++++-- app/models/group_milestone.rb | 7 +++-- app/views/groups/milestones/index.html.haml | 13 +++++---- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 5e810942d1..c7eab368e2 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -2,9 +2,8 @@ class Groups::MilestonesController < ApplicationController layout 'group' def index - @group = Group.find_by(path: params[:group_id]) - project_ids = @group.projects - project_milestones = Milestone.where(project_id: project_ids) + @group = group + project_milestones = Milestone.where(project_id: @group.projects) @group_milestones = Milestones::GroupService.new(project_milestones).execute @group_milestones = case params[:status] when 'all'; @group_milestones @@ -13,8 +12,32 @@ class Groups::MilestonesController < ApplicationController end end + def update + project_milestones = Milestone.where(project_id: group.projects) + @group_milestones = Milestones::GroupService.new(project_milestones).execute + title = params[:id].gsub("-", ".") + + @group_milestones.each do |group_milestone| + next unless group_milestone.title == title + group_milestone.milestones.each do |milestone| + Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) + end + end + + respond_to do |format| + format.js + format.html do + redirect_to group_milestones_path(group) + end + end + end + private + def group + @group ||= Group.find_by(path: params[:group_id]) + end + def status(state) @group_milestones.map{ |milestone| next if milestone.state != state; milestone }.compact end diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 132c0eb249..567e0c2b9f 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -13,8 +13,8 @@ class GroupMilestone @milestones end - def project_names - milestones.map{ |milestone| milestone.project.name } + def projects + milestones.map{ |milestone| milestone.project } end def issue_count @@ -41,7 +41,8 @@ class GroupMilestone def state state = milestones.map{ |milestone| milestone.state } - if state.all?{ |milestone_state| milestone_state == 'active' } + + if state.count("active") == state.size 'active' else 'closed' diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 9ce8bf32ae..25e6fddb47 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -23,9 +23,12 @@ - else - @group_milestones.each do |milestone| %li{class: "milestone milestone-#{milestone.state == 'closed' ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } - - unless milestone.state == 'closed' - .pull-right - = link_to 'Close Milestone', root_path, method: :put, remote: true, class: "btn btn-small btn-remove" + .pull-right + - safe_title = milestone.title.gsub(".", "-") + - if milestone.state == 'closed' + = link_to 'Reopen Milestone', group_milestone_path(@group, safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + - else + = link_to 'Close Milestone', group_milestone_path(@group, safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" %h4 = link_to_gfm truncate(milestone.title, length: 100), root_path %div @@ -41,6 +44,6 @@ .progress-bar{style: "width: #{milestone.percent_complete}%;"} %div %br - - milestone.project_names.each do |name| + - milestone.projects.each do |project| %span.label.label-default - = name + = project.name From b6425f33bc0b0547058e96e5ab99a7892d9297f2 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Thu, 26 Jun 2014 14:19:29 +0200 Subject: [PATCH 09/16] Get one group milestone based on milestone title. --- .../groups/milestones_controller.rb | 22 +++++++++++-------- app/services/milestones/group_service.rb | 8 +++++++ app/views/groups/milestones/index.html.haml | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index c7eab368e2..a86cc58c02 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -2,8 +2,7 @@ class Groups::MilestonesController < ApplicationController layout 'group' def index - @group = group - project_milestones = Milestone.where(project_id: @group.projects) + project_milestones = Milestone.where(project_id: group.projects) @group_milestones = Milestones::GroupService.new(project_milestones).execute @group_milestones = case params[:status] when 'all'; @group_milestones @@ -12,16 +11,17 @@ class Groups::MilestonesController < ApplicationController end end + def show + project_milestones = Milestone.where(project_id: group.projects) + @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) + end + def update project_milestones = Milestone.where(project_id: group.projects) - @group_milestones = Milestones::GroupService.new(project_milestones).execute - title = params[:id].gsub("-", ".") + @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) - @group_milestones.each do |group_milestone| - next unless group_milestone.title == title - group_milestone.milestones.each do |milestone| - Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) - end + @group_milestones.each do |milestone| + Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) end respond_to do |format| @@ -38,6 +38,10 @@ class Groups::MilestonesController < ApplicationController @group ||= Group.find_by(path: params[:group_id]) end + def title + params[:id].gsub("-", ".") + end + def status(state) @group_milestones.map{ |milestone| next if milestone.state != state; milestone }.compact end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb index 3a7e092a77..39ae913a72 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/group_service.rb @@ -8,5 +8,13 @@ module Milestones @project_milestones.map{ |title, milestone| GroupMilestone.new(title, milestone) } end + def milestone(title) + if title + @project_milestones[title] + else + nil + end + end + end end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 25e6fddb47..b93ff09d25 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -30,7 +30,7 @@ - else = link_to 'Close Milestone', group_milestone_path(@group, safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" %h4 - = link_to_gfm truncate(milestone.title, length: 100), root_path + = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, safe_title) %div %div = link_to root_path do From c223fb1a9677ae00285426090618f5762de9f40e Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 27 Jun 2014 10:14:57 +0200 Subject: [PATCH 10/16] Start building group milestone show page. --- .../groups/milestones_controller.rb | 6 +- app/models/group_milestone.rb | 69 ++++++++++++++++- app/services/milestones/group_service.rb | 10 ++- app/views/groups/milestones/_issue.html.haml | 9 +++ app/views/groups/milestones/_issues.html.haml | 6 ++ .../milestones/_merge_request.html.haml | 6 ++ .../milestones/_merge_requests.html.haml | 5 ++ app/views/groups/milestones/index.html.haml | 15 ++-- app/views/groups/milestones/show.html.haml | 77 +++++++++++++++++++ 9 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 app/views/groups/milestones/_issue.html.haml create mode 100644 app/views/groups/milestones/_issues.html.haml create mode 100644 app/views/groups/milestones/_merge_request.html.haml create mode 100644 app/views/groups/milestones/_merge_requests.html.haml create mode 100644 app/views/groups/milestones/show.html.haml diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index a86cc58c02..235b27f53a 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -13,14 +13,16 @@ class Groups::MilestonesController < ApplicationController def show project_milestones = Milestone.where(project_id: group.projects) - @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) + @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) + @project_issues = @group_milestone.filter_by(params[:status], "issues") + @project_merge_requests = @group_milestone.filter_by(params[:status], "merge_requests") end def update project_milestones = Milestone.where(project_id: group.projects) @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title) - @group_milestones.each do |milestone| + @group_milestones.milestones.each do |milestone| Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone) end diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 567e0c2b9f..0faff39ae7 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -9,6 +9,10 @@ class GroupMilestone @title end + def safe_title + @title.gsub(".", "-") + end + def milestones @milestones end @@ -25,6 +29,10 @@ class GroupMilestone milestones.map{ |milestone| milestone.merge_requests.count }.sum end + def open_items_count + milestones.map{ |milestone| milestone.open_items_count }.sum + end + def closed_items_count milestones.map{ |milestone| milestone.closed_items_count }.sum end @@ -42,10 +50,69 @@ class GroupMilestone def state state = milestones.map{ |milestone| milestone.state } - if state.count("active") == state.size + if state.count('active') == state.size 'active' else 'closed' end end + + def active? + state == 'active' + end + + def closed? + state == 'closed' + end + + def opened_unassigned_issues + milestones.map{ |milestone| milestone.issues.opened.unassigned } + end + + def opened_assigned_issues + milestones.map{ |milestone| milestone.issues.opened.assigned } + end + + def closed_issues + milestones.map{ |milestone| milestone.issues.closed } + end + + def participants + milestones.map{ |milestone| milestone.participants.uniq }.reject(&:empty?).flatten + end + + def filter_by(filter, entity) + if entity + milestones = self.milestones.sort_by(&:project_id) + entities = {} + milestones.each do |project_milestone| + next unless project_milestone.send(entity).any? + project_name = project_milestone.project.name + entities_by_state = state_filter(filter, project_milestone.send(entity)) + entities.store(project_name, entities_by_state) + end + entities + else + {} + end + end + + def state_filter(filter, entities) + if entities.present? + sorted_entities = entities.sort_by(&:position) + entities_by_state = case filter + when 'active'; sorted_entities.group_by(&:state)['opened'] + when 'closed'; sorted_entities.group_by(&:state)['closed'] + else sorted_entities + end + if entities_by_state.blank? + [] + else + entities_by_state + end + else + [] + end + end + end diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb index 39ae913a72..2d1aa878c2 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/group_service.rb @@ -5,16 +5,22 @@ module Milestones end def execute - @project_milestones.map{ |title, milestone| GroupMilestone.new(title, milestone) } + build(@project_milestones) end def milestone(title) if title - @project_milestones[title] + group_milestone = @project_milestones[title].group_by(&:title) + build(group_milestone).first else nil end end + private + + def build(milestone) + milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) } + end end end diff --git a/app/views/groups/milestones/_issue.html.haml b/app/views/groups/milestones/_issue.html.haml new file mode 100644 index 0000000000..7009400a46 --- /dev/null +++ b/app/views/groups/milestones/_issue.html.haml @@ -0,0 +1,9 @@ +%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid } + %span.str-truncated + - project = issue.project + = link_to [project, issue] do + %span.cgray ##{issue.iid} + = link_to_gfm issue.title, [project, issue] + .pull-right.assignee-icon + - if issue.assignee + = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16" diff --git a/app/views/groups/milestones/_issues.html.haml b/app/views/groups/milestones/_issues.html.haml new file mode 100644 index 0000000000..3fefb2f010 --- /dev/null +++ b/app/views/groups/milestones/_issues.html.haml @@ -0,0 +1,6 @@ +.panel.panel-default + .panel-heading= name + %ul{ class: "well-list issues-sortable-list" } + - issues.each do |issue| + = render 'issue', issue: issue + diff --git a/app/views/groups/milestones/_merge_request.html.haml b/app/views/groups/milestones/_merge_request.html.haml new file mode 100644 index 0000000000..4f11aaa74b --- /dev/null +++ b/app/views/groups/milestones/_merge_request.html.haml @@ -0,0 +1,6 @@ +%li{ id: dom_id(merge_request, 'sortable'), class: 'mr-row', 'data-iid' => merge_request.iid } + %span.str-truncated + - project = merge_request.project + = link_to [project, merge_request] do + %span.cgray ##{merge_request.iid} + = link_to_gfm truncate(merge_request.title, length: 60), [project, merge_request] diff --git a/app/views/groups/milestones/_merge_requests.html.haml b/app/views/groups/milestones/_merge_requests.html.haml new file mode 100644 index 0000000000..9bb213ffe3 --- /dev/null +++ b/app/views/groups/milestones/_merge_requests.html.haml @@ -0,0 +1,5 @@ +.panel.panel-default + .panel-heading= name + %ul{ class: "well-list merge_requests-sortable-list" } + - merge_requests.sort_by(&:position).each do |merge_request| + = render 'merge_request', merge_request: merge_request diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b93ff09d25..e3dd1ae5ae 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -22,21 +22,20 @@ .nothing-here-block No milestones to show - else - @group_milestones.each do |milestone| - %li{class: "milestone milestone-#{milestone.state == 'closed' ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } + %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } .pull-right - - safe_title = milestone.title.gsub(".", "-") - - if milestone.state == 'closed' - = link_to 'Reopen Milestone', group_milestone_path(@group, safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + - if milestone.closed? + = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" - else - = link_to 'Close Milestone', group_milestone_path(@group, safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" %h4 - = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, safe_title) + = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title) %div %div - = link_to root_path do + = link_to group_milestone_path(@group, milestone.safe_title) do = pluralize milestone.issue_count, 'Issue'   - = link_to root_path do + = link_to group_milestone_path(@group, milestone.safe_title) do = pluralize milestone.merge_requests_count, 'Merge Request'   %span.light #{milestone.percent_complete}% complete diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml new file mode 100644 index 0000000000..a450e7d09a --- /dev/null +++ b/app/views/groups/milestones/show.html.haml @@ -0,0 +1,77 @@ +%h3.page-title + Milestone #{@group_milestone.title} + .pull-right + - if @group_milestone.active? + = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + - else + = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + +- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? + .alert.alert-success + %span All issues for this milestone are closed. You may close the milestone now. + +.back-link + = link_to group_milestones_path(@group) do + ← To milestones list + +.issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } + .state.clearfix + .state-label + - if @group_milestone.closed? + Closed + - else + Open + + %h4.title + = gfm escape_once(@group_milestone.title) + + .context + %p + Progress: + #{@group_milestone.closed_items_count} closed + – + #{@group_milestone.open_items_count} open + + .progress.progress-info + .progress-bar{style: "width: #{@group_milestone.percent_complete}%;"} + +%ul.nav.nav-tabs + %li.active + = link_to '#tab-issues', 'data-toggle' => 'tab' do + Issues + %span.badge= @group_milestone.issue_count + %li + = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do + Merge Requests + %span.badge= @group_milestone.merge_requests_count + %li + = link_to '#tab-participants', 'data-toggle' => 'tab' do + Participants + %span.badge= @group_milestone.participants.count + +.tab-content + .tab-pane.active#tab-issues + .row + .col-md-4.responsive-side + = render 'groups/filter', entity: 'milestone' + .col-md-8 + - @project_issues.each do |name, issues| + = render 'issues', name: name, issues: issues + + .tab-pane#tab-merge-requests + .row + .col-md-4.responsive-side + = render 'groups/filter', entity: 'milestone' + .col-md-8 + - @project_merge_requests.each do |name, merge_requests| + = render 'merge_requests', name: name, merge_requests: merge_requests + + .tab-pane#tab-participants + %ul.bordered-list + - @group_milestone.participants.each do |user| + %li + = link_to user, title: user.name, class: "darken" do + = image_tag avatar_icon(user.email, 32), class: "avatar s32" + %strong= truncate(user.name, lenght: 40) + %br + %small.cgray= user.username From e66a8b4cdab176ff89a685788dcbcac089712e49 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 10:54:57 +0200 Subject: [PATCH 11/16] Move milestone link in group head, 2 column milestone for MR and issues. --- app/assets/stylesheets/sections/groups.scss | 9 +++++++++ .../groups/milestones_controller.rb | 4 ++-- app/models/group_milestone.rb | 12 ++++-------- app/views/groups/milestones/_issue.html.haml | 4 +++- app/views/groups/milestones/_issues.html.haml | 8 ++++---- .../groups/milestones/_merge_request.html.haml | 9 +++++++-- .../milestones/_merge_requests.html.haml | 7 ++++--- app/views/groups/milestones/show.html.haml | 18 ++++++++---------- app/views/layouts/nav/_group.html.haml | 6 +++--- 9 files changed, 44 insertions(+), 33 deletions(-) diff --git a/app/assets/stylesheets/sections/groups.scss b/app/assets/stylesheets/sections/groups.scss index 60ec79acad..e174f72882 100644 --- a/app/assets/stylesheets/sections/groups.scss +++ b/app/assets/stylesheets/sections/groups.scss @@ -7,3 +7,12 @@ .member-search-form { float: left; } + +.milestone-row { + @include str-truncated(90%); +} + +.label.label-default.project-name { + width: 80px; + @include str-truncated(80%); +} diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 235b27f53a..c4b87308e8 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -14,8 +14,8 @@ class Groups::MilestonesController < ApplicationController def show project_milestones = Milestone.where(project_id: group.projects) @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) - @project_issues = @group_milestone.filter_by(params[:status], "issues") - @project_merge_requests = @group_milestone.filter_by(params[:status], "merge_requests") + @issues = @group_milestone.issues + @merge_requests = @group_milestone.merge_requests end def update diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 0faff39ae7..45222f5329 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -65,16 +65,12 @@ class GroupMilestone state == 'closed' end - def opened_unassigned_issues - milestones.map{ |milestone| milestone.issues.opened.unassigned } + def issues + milestones.map{ |milestone| milestone.issues }.flatten.group_by(&:state) end - def opened_assigned_issues - milestones.map{ |milestone| milestone.issues.opened.assigned } - end - - def closed_issues - milestones.map{ |milestone| milestone.issues.closed } + def merge_requests + milestones.map{ |milestone| milestone.merge_requests }.flatten.group_by(&:state) end def participants diff --git a/app/views/groups/milestones/_issue.html.haml b/app/views/groups/milestones/_issue.html.haml index 7009400a46..759003bb56 100644 --- a/app/views/groups/milestones/_issue.html.haml +++ b/app/views/groups/milestones/_issue.html.haml @@ -1,6 +1,8 @@ %li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid } - %span.str-truncated + %span.milestone-row - project = issue.project + %span.label.label-default.project-name + = project.name = link_to [project, issue] do %span.cgray ##{issue.iid} = link_to_gfm issue.title, [project, issue] diff --git a/app/views/groups/milestones/_issues.html.haml b/app/views/groups/milestones/_issues.html.haml index 3fefb2f010..9f350b772b 100644 --- a/app/views/groups/milestones/_issues.html.haml +++ b/app/views/groups/milestones/_issues.html.haml @@ -1,6 +1,6 @@ .panel.panel-default - .panel-heading= name + .panel-heading= title %ul{ class: "well-list issues-sortable-list" } - - issues.each do |issue| - = render 'issue', issue: issue - + - if issues + - issues.each do |issue| + = render 'issue', issue: issue diff --git a/app/views/groups/milestones/_merge_request.html.haml b/app/views/groups/milestones/_merge_request.html.haml index 4f11aaa74b..95d5de002d 100644 --- a/app/views/groups/milestones/_merge_request.html.haml +++ b/app/views/groups/milestones/_merge_request.html.haml @@ -1,6 +1,11 @@ %li{ id: dom_id(merge_request, 'sortable'), class: 'mr-row', 'data-iid' => merge_request.iid } - %span.str-truncated + %span.milestone-row - project = merge_request.project + %span.label.label-default.project-name + = project.name = link_to [project, merge_request] do %span.cgray ##{merge_request.iid} - = link_to_gfm truncate(merge_request.title, length: 60), [project, merge_request] + = link_to_gfm merge_request.title, [project, merge_request] + .pull-right.assignee-icon + - if merge_request.assignee + = image_tag avatar_icon(merge_request.assignee.email, 16), class: "avatar s16" diff --git a/app/views/groups/milestones/_merge_requests.html.haml b/app/views/groups/milestones/_merge_requests.html.haml index 9bb213ffe3..ddf7f5ee55 100644 --- a/app/views/groups/milestones/_merge_requests.html.haml +++ b/app/views/groups/milestones/_merge_requests.html.haml @@ -1,5 +1,6 @@ .panel.panel-default - .panel-heading= name + .panel-heading= title %ul{ class: "well-list merge_requests-sortable-list" } - - merge_requests.sort_by(&:position).each do |merge_request| - = render 'merge_request', merge_request: merge_request + - if merge_requests + - merge_requests.sort_by(&:position).each do |merge_request| + = render 'merge_request', merge_request: merge_request diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index a450e7d09a..d7bf6ae3c5 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -52,19 +52,17 @@ .tab-content .tab-pane.active#tab-issues .row - .col-md-4.responsive-side - = render 'groups/filter', entity: 'milestone' - .col-md-8 - - @project_issues.each do |name, issues| - = render 'issues', name: name, issues: issues + .col-md-6 + = render 'issues', title: "Open", issues: @issues["opened"] + .col-md-6 + = render 'issues', title: "Closed", issues: @issues["closed"] .tab-pane#tab-merge-requests .row - .col-md-4.responsive-side - = render 'groups/filter', entity: 'milestone' - .col-md-8 - - @project_merge_requests.each do |name, merge_requests| - = render 'merge_requests', name: name, merge_requests: merge_requests + .col-md-6 + = render 'merge_requests', title: "Open", merge_requests: @merge_requests["opened"] + .col-md-6 + = render 'merge_requests', title: "Closed", merge_requests: @merge_requests["closed"] .tab-pane#tab-participants %ul.bordered-list diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 429848e3cb..5d161a17bf 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -2,6 +2,9 @@ = nav_link(path: 'groups#show', html_options: {class: 'home'}) do = link_to group_path(@group), title: "Home" do Activity + = nav_link(path: 'groups#milestones') do + = link_to group_milestones_path(@group) do + Milestones = nav_link(path: 'groups#issues') do = link_to issues_group_path(@group) do Issues @@ -12,9 +15,6 @@ Merge Requests - if current_user %span.count= current_user.cared_merge_requests.opened.of_group(@group).count - = nav_link(path: 'groups#milestones') do - = link_to group_milestones_path(@group) do - Milestones = nav_link(path: 'groups#members') do = link_to "Members", members_group_path(@group) From d145f09cd675fa46a6cc20fac8304f02d2d14656 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 11:38:03 +0200 Subject: [PATCH 12/16] Correct authorization for group milestones. --- .../groups/milestones_controller.rb | 6 ++++ app/models/group_milestone.rb | 35 ------------------- app/views/groups/milestones/index.html.haml | 13 +++---- app/views/groups/milestones/show.html.haml | 9 ++--- 4 files changed, 18 insertions(+), 45 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index c4b87308e8..281b2f0c90 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,6 +1,8 @@ class Groups::MilestonesController < ApplicationController layout 'group' + before_filter :authorize_group_milestone!, only: :update + def index project_milestones = Milestone.where(project_id: group.projects) @group_milestones = Milestones::GroupService.new(project_milestones).execute @@ -47,4 +49,8 @@ class Groups::MilestonesController < ApplicationController def status(state) @group_milestones.map{ |milestone| next if milestone.state != state; milestone }.compact end + + def authorize_group_milestone! + return render_404 unless can?(current_user, :manage_group, group) + end end diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 45222f5329..8296a0aa71 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -76,39 +76,4 @@ class GroupMilestone def participants milestones.map{ |milestone| milestone.participants.uniq }.reject(&:empty?).flatten end - - def filter_by(filter, entity) - if entity - milestones = self.milestones.sort_by(&:project_id) - entities = {} - milestones.each do |project_milestone| - next unless project_milestone.send(entity).any? - project_name = project_milestone.project.name - entities_by_state = state_filter(filter, project_milestone.send(entity)) - entities.store(project_name, entities_by_state) - end - entities - else - {} - end - end - - def state_filter(filter, entities) - if entities.present? - sorted_entities = entities.sort_by(&:position) - entities_by_state = case filter - when 'active'; sorted_entities.group_by(&:state)['opened'] - when 'closed'; sorted_entities.group_by(&:state)['closed'] - else sorted_entities - end - if entities_by_state.blank? - [] - else - entities_by_state - end - else - [] - end - end - end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index e3dd1ae5ae..671f81ba06 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -24,18 +24,19 @@ - @group_milestones.each do |milestone| %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } .pull-right - - if milestone.closed? - = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" - - else - = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + - if can?(current_user, :manage_group, @group) + - if milestone.closed? + = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + - else + = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" %h4 = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title) %div %div - = link_to group_milestone_path(@group, milestone.safe_title) do + = link_to group_milestone_path(@group, milestone.safe_title, anchor: 'tab-issues') do = pluralize milestone.issue_count, 'Issue'   - = link_to group_milestone_path(@group, milestone.safe_title) do + = link_to group_milestone_path(@group, milestone.safe_title, anchor: 'tab-merge-requests') do = pluralize milestone.merge_requests_count, 'Merge Request'   %span.light #{milestone.percent_complete}% complete diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index d7bf6ae3c5..7e66318e96 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,10 +1,11 @@ %h3.page-title Milestone #{@group_milestone.title} .pull-right - - if @group_milestone.active? - = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" - - else - = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + - if can?(current_user, :manage_group, @group) + - if @group_milestone.active? + = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + - else + = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" - if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? .alert.alert-success From d3796b84f8f3ab9da30447eb0bac2cf9aed32b31 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 12:41:27 +0200 Subject: [PATCH 13/16] Show all issues and merge requests that could be considered opened or closed, includes reopened and merged. --- .../groups/milestones_controller.rb | 2 -- app/models/group_milestone.rb | 20 +++++++++++++++++-- .../milestones/_merge_requests.html.haml | 2 +- app/views/groups/milestones/show.html.haml | 8 ++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 281b2f0c90..4f7096c42b 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -16,8 +16,6 @@ class Groups::MilestonesController < ApplicationController def show project_milestones = Milestone.where(project_id: group.projects) @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title) - @issues = @group_milestone.issues - @merge_requests = @group_milestone.merge_requests end def update diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 8296a0aa71..cbd9f2a33c 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -66,14 +66,30 @@ class GroupMilestone end def issues - milestones.map{ |milestone| milestone.issues }.flatten.group_by(&:state) + @group_issues ||= milestones.map{ |milestone| milestone.issues }.flatten.group_by(&:state) end def merge_requests - milestones.map{ |milestone| milestone.merge_requests }.flatten.group_by(&:state) + @group_merge_requests ||= milestones.map{ |milestone| milestone.merge_requests }.flatten.group_by(&:state) end def participants milestones.map{ |milestone| milestone.participants.uniq }.reject(&:empty?).flatten end + + def opened_issues + issues.values_at("opened", "reopened").compact.flatten + end + + def closed_issues + issues['closed'] + end + + def opened_merge_requests + merge_requests.values_at("opened", "reopened").compact.flatten + end + + def closed_merge_requests + merge_requests.values_at("closed", "merged", "locked").compact.flatten + end end diff --git a/app/views/groups/milestones/_merge_requests.html.haml b/app/views/groups/milestones/_merge_requests.html.haml index ddf7f5ee55..50057e2c63 100644 --- a/app/views/groups/milestones/_merge_requests.html.haml +++ b/app/views/groups/milestones/_merge_requests.html.haml @@ -2,5 +2,5 @@ .panel-heading= title %ul{ class: "well-list merge_requests-sortable-list" } - if merge_requests - - merge_requests.sort_by(&:position).each do |merge_request| + - merge_requests.each do |merge_request| = render 'merge_request', merge_request: merge_request diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index 7e66318e96..1ed5907b71 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -54,16 +54,16 @@ .tab-pane.active#tab-issues .row .col-md-6 - = render 'issues', title: "Open", issues: @issues["opened"] + = render 'issues', title: "Open", issues: @group_milestone.opened_issues .col-md-6 - = render 'issues', title: "Closed", issues: @issues["closed"] + = render 'issues', title: "Closed", issues: @group_milestone.closed_issues .tab-pane#tab-merge-requests .row .col-md-6 - = render 'merge_requests', title: "Open", merge_requests: @merge_requests["opened"] + = render 'merge_requests', title: "Open", merge_requests: @group_milestone.opened_merge_requests .col-md-6 - = render 'merge_requests', title: "Closed", merge_requests: @merge_requests["closed"] + = render 'merge_requests', title: "Closed", merge_requests: @group_milestone.closed_merge_requests .tab-pane#tab-participants %ul.bordered-list From fdbf77ef994dfdee9377fa917ca35ce3d5bd1231 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 13:27:17 +0200 Subject: [PATCH 14/16] Fix styling issues. --- app/assets/stylesheets/sections/groups.scss | 5 ----- app/models/group_milestone.rb | 20 +++++++++---------- app/services/milestones/group_service.rb | 2 +- app/views/groups/milestones/_issue.html.haml | 3 +-- .../milestones/_merge_request.html.haml | 3 +-- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/assets/stylesheets/sections/groups.scss b/app/assets/stylesheets/sections/groups.scss index e174f72882..e49fe1a9dd 100644 --- a/app/assets/stylesheets/sections/groups.scss +++ b/app/assets/stylesheets/sections/groups.scss @@ -11,8 +11,3 @@ .milestone-row { @include str-truncated(90%); } - -.label.label-default.project-name { - width: 80px; - @include str-truncated(80%); -} diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index cbd9f2a33c..7af61f97a6 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -18,27 +18,27 @@ class GroupMilestone end def projects - milestones.map{ |milestone| milestone.project } + milestones.map { |milestone| milestone.project } end def issue_count - milestones.map{ |milestone| milestone.issues.count }.sum + milestones.map { |milestone| milestone.issues.count }.sum end def merge_requests_count - milestones.map{ |milestone| milestone.merge_requests.count }.sum + milestones.map { |milestone| milestone.merge_requests.count }.sum end def open_items_count - milestones.map{ |milestone| milestone.open_items_count }.sum + milestones.map { |milestone| milestone.open_items_count }.sum end def closed_items_count - milestones.map{ |milestone| milestone.closed_items_count }.sum + milestones.map { |milestone| milestone.closed_items_count }.sum end def total_items_count - milestones.map{ |milestone| milestone.total_items_count }.sum + milestones.map { |milestone| milestone.total_items_count }.sum end def percent_complete @@ -48,7 +48,7 @@ class GroupMilestone end def state - state = milestones.map{ |milestone| milestone.state } + state = milestones.map { |milestone| milestone.state } if state.count('active') == state.size 'active' @@ -66,15 +66,15 @@ class GroupMilestone end def issues - @group_issues ||= milestones.map{ |milestone| milestone.issues }.flatten.group_by(&:state) + @group_issues ||= milestones.map { |milestone| milestone.issues }.flatten.group_by(&:state) end def merge_requests - @group_merge_requests ||= milestones.map{ |milestone| milestone.merge_requests }.flatten.group_by(&:state) + @group_merge_requests ||= milestones.map { |milestone| milestone.merge_requests }.flatten.group_by(&:state) end def participants - milestones.map{ |milestone| milestone.participants.uniq }.reject(&:empty?).flatten + milestones.map { |milestone| milestone.participants.uniq }.reject(&:empty?).flatten end def opened_issues diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb index 2d1aa878c2..11d702f1e7 100644 --- a/app/services/milestones/group_service.rb +++ b/app/services/milestones/group_service.rb @@ -17,7 +17,7 @@ module Milestones end end - private + private def build(milestone) milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) } diff --git a/app/views/groups/milestones/_issue.html.haml b/app/views/groups/milestones/_issue.html.haml index 759003bb56..c0cf56941f 100644 --- a/app/views/groups/milestones/_issue.html.haml +++ b/app/views/groups/milestones/_issue.html.haml @@ -1,8 +1,7 @@ %li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid } %span.milestone-row - project = issue.project - %span.label.label-default.project-name - = project.name + %strong #{project.name} · = link_to [project, issue] do %span.cgray ##{issue.iid} = link_to_gfm issue.title, [project, issue] diff --git a/app/views/groups/milestones/_merge_request.html.haml b/app/views/groups/milestones/_merge_request.html.haml index 95d5de002d..037162a20e 100644 --- a/app/views/groups/milestones/_merge_request.html.haml +++ b/app/views/groups/milestones/_merge_request.html.haml @@ -1,8 +1,7 @@ %li{ id: dom_id(merge_request, 'sortable'), class: 'mr-row', 'data-iid' => merge_request.iid } %span.milestone-row - project = merge_request.project - %span.label.label-default.project-name - = project.name + %strong #{project.name} · = link_to [project, merge_request] do %span.cgray ##{merge_request.iid} = link_to_gfm merge_request.title, [project, merge_request] From eb5182ac8da38e0eadd87cee7385965f05dabc9d Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 15:00:12 +0200 Subject: [PATCH 15/16] Add group service spec. --- .../services/milestones/group_service_spec.rb | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 spec/services/milestones/group_service_spec.rb diff --git a/spec/services/milestones/group_service_spec.rb b/spec/services/milestones/group_service_spec.rb new file mode 100644 index 0000000000..74eb0f99e0 --- /dev/null +++ b/spec/services/milestones/group_service_spec.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +describe Milestones::GroupService do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:group) { create(:group) } + let(:project1) { create(:project, group: group) } + let(:project2) { create(:project, path: 'gitlab-ci', group: group) } + let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } + let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } + let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } + let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } + let(:milestone2_project1) { create(:milestone, title: "VD-123", project: project1) } + let(:milestone2_project2) { create(:milestone, title: "VD-123", project: project2) } + let(:milestone2_project3) { create(:milestone, title: "VD-123", project: project3) } + + describe 'execute' do + context 'with valid projects' do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + milestone2_project1, + milestone2_project2, + milestone2_project3 + ] + @group_milestones = Milestones::GroupService.new(milestones).execute + end + + it 'should have all project milestones' do + expect(@group_milestones.count).to eq(2) + end + + it 'should have all project milestones titles' do + expect(@group_milestones.map { |group_milestone| group_milestone.title }).to match_array(['Milestone v1.2', 'VD-123']) + end + + it 'should have all project milestones' do + expect(@group_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) + end + end + end + + describe 'milestone' do + context 'with valid title' do + before do + milestones = + [ + milestone1_project1, + milestone1_project2, + milestone1_project3, + milestone2_project1, + milestone2_project2, + milestone2_project3 + ] + @group_milestones = Milestones::GroupService.new(milestones).milestone('Milestone v1.2') + end + + it 'should have exactly one group milestone' do + expect(@group_milestones.title).to eq('Milestone v1.2') + end + + it 'should have all project milestones with the same title' do + expect(@group_milestones.milestones.count).to eq(3) + end + end + end +end From 3e52517da1c506885c06c13ff59ff5863bcb68ea Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 30 Jun 2014 16:18:26 +0200 Subject: [PATCH 16/16] Add feature tests for group milestone. --- .../groups/milestones_controller.rb | 2 +- app/models/group_milestone.rb | 2 +- app/views/groups/milestones/index.html.haml | 10 +- app/views/groups/milestones/show.html.haml | 4 +- features/group.feature | 19 ++++ features/steps/group/group.rb | 94 +++++++++++++++++++ 6 files changed, 122 insertions(+), 9 deletions(-) diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 4f7096c42b..8dde8e9146 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -41,7 +41,7 @@ class Groups::MilestonesController < ApplicationController end def title - params[:id].gsub("-", ".") + params[:title] end def status(state) diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 7af61f97a6..013f8db00a 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -10,7 +10,7 @@ class GroupMilestone end def safe_title - @title.gsub(".", "-") + @title.parameterize end def milestones diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 671f81ba06..9dd8fa9664 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -26,17 +26,17 @@ .pull-right - if can?(current_user, :manage_group, @group) - if milestone.closed? - = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" - else - = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" %h4 - = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title) + = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title) %div %div - = link_to group_milestone_path(@group, milestone.safe_title, anchor: 'tab-issues') do + = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do = pluralize milestone.issue_count, 'Issue'   - = link_to group_milestone_path(@group, milestone.safe_title, anchor: 'tab-merge-requests') do + = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do = pluralize milestone.merge_requests_count, 'Merge Request'   %span.light #{milestone.percent_complete}% complete diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index 1ed5907b71..d39870b032 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -3,9 +3,9 @@ .pull-right - if can?(current_user, :manage_group, @group) - if @group_milestone.active? - = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" + = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove" - else - = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" + = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped" - if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active? .alert.alert-success diff --git a/features/group.feature b/features/group.feature index 71c28c07a3..0c70e5b915 100644 --- a/features/group.feature +++ b/features/group.feature @@ -120,3 +120,22 @@ Feature: Groups When I search for 'Mary' member Then I should see user "Mary Jane" in team list Then I should not see user "John Doe" in team list + + + Scenario: I should see group "Owned" milestone index page with no milestones + When I visit group "Owned" page + And I click on group milestones + Then I should see group milestones index page has no milestones + + Scenario: I should see group "Owned" milestone index page with milestones + Given Group has projects with milestones + When I visit group "Owned" page + And I click on group milestones + Then I should see group milestones index page with milestones + + Scenario: I should see group "Owned" milestone show page + Given Group has projects with milestones + When I visit group "Owned" page + And I click on group milestones + And I click on one group milestone + Then I should see group milestone with all issues and MRs assigned to that milestone diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb index f321428592..85276f04dd 100644 --- a/features/steps/group/group.rb +++ b/features/steps/group/group.rb @@ -164,6 +164,36 @@ class Groups < Spinach::FeatureSteps end end + step 'I click on group milestones' do + click_link 'Milestones' + end + + step 'I should see group milestones index page has no milestones' do + page.should have_content('No milestones to show') + end + + step 'Group has projects with milestones' do + group_milestone + end + + step 'I should see group milestones index page with milestones' do + page.should have_content('Version 7.2') + page.should have_content('GL-113') + page.should have_link('2 Issues', href: group_milestone_path("owned", "version-7-2", title: "Version 7.2")) + page.should have_link('3 Merge Requests', href: group_milestone_path("owned", "gl-113", title: "GL-113")) + end + + step 'I click on one group milestone' do + click_link 'GL-113' + end + + step 'I should see group milestone with all issues and MRs assigned to that milestone' do + page.should have_content('Milestone GL-113') + page.should have_content('Progress: 0 closed – 4 open') + page.should have_link(@issue1.title, href: project_issue_path(@project1, @issue1)) + page.should have_link(@mr3.title, href: project_merge_request_path(@project3, @mr3)) + end + protected def assigned_to_me key @@ -173,4 +203,68 @@ class Groups < Spinach::FeatureSteps def project Group.find_by(name: "Owned").projects.first end + + def group_milestone + group = Group.find_by(name: "Owned") + + @project1 = create :project, + group: group + project2 = create :project, + path: 'gitlab-ci', + group: group + @project3 = create :project, + path: 'cookbook-gitlab', + group: group + milestone1_project1 = create :milestone, + title: "Version 7.2", + project: @project1 + milestone1_project2 = create :milestone, + title: "Version 7.2", + project: project2 + milestone1_project3 = create :milestone, + title: "Version 7.2", + project: @project3 + milestone2_project1 = create :milestone, + title: "GL-113", + project: @project1 + milestone2_project2 = create :milestone, + title: "GL-113", + project: project2 + milestone2_project3 = create :milestone, + title: "GL-113", + project: @project3 + @issue1 = create :issue, + project: @project1, + assignee: current_user, + author: current_user, + milestone: milestone2_project1 + issue2 = create :issue, + project: project2, + assignee: current_user, + author: current_user, + milestone: milestone1_project2 + issue3 = create :issue, + project: @project3, + assignee: current_user, + author: current_user, + milestone: milestone1_project1 + mr1 = create :merge_request, + source_project: @project1, + target_project: @project1, + assignee: current_user, + author: current_user, + milestone: milestone2_project1 + mr2 = create :merge_request, + source_project: project2, + target_project: project2, + assignee: current_user, + author: current_user, + milestone: milestone2_project2 + @mr3 = create :merge_request, + source_project: @project3, + target_project: @project3, + assignee: current_user, + author: current_user, + milestone: milestone2_project3 + end end