Merge branch 'dashboard-milestones' into 'master'
Add dashboard milestones. Closes #1422. ![Screen_Shot_2015-03-03_at_16.20.36](https://dev.gitlab.org/gitlab/gitlabhq/uploads/795b480a2552e1d26436c3db2158cb81/Screen_Shot_2015-03-03_at_16.20.36.png) See merge request !1621
This commit is contained in:
commit
e916f1c295
13 changed files with 209 additions and 9 deletions
|
@ -19,6 +19,7 @@ v 7.9.0 (unreleased)
|
|||
- Add a service to send updates to an Irker gateway (Romain Coltel)
|
||||
- Add brakeman (security scanner for Ruby on Rails)
|
||||
- Slack username and channel options
|
||||
- Add grouped milestones from all projects to dashboard.
|
||||
|
||||
v 7.8.1
|
||||
- Fix run of custom post receive hooks
|
||||
|
|
34
app/controllers/dashboard/milestones_controller.rb
Normal file
34
app/controllers/dashboard/milestones_controller.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
class Dashboard::MilestonesController < ApplicationController
|
||||
before_filter :load_projects
|
||||
|
||||
def index
|
||||
project_milestones = case params[:state]
|
||||
when 'all'; state
|
||||
when 'closed'; state('closed')
|
||||
else state('active')
|
||||
end
|
||||
@dashboard_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(30)
|
||||
end
|
||||
|
||||
def show
|
||||
project_milestones = Milestone.where(project_id: @projects).order("due_date ASC")
|
||||
@dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_projects
|
||||
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
|
||||
end
|
||||
|
||||
def title
|
||||
params[:title]
|
||||
end
|
||||
|
||||
def state(state = nil)
|
||||
conditions = { project_id: @projects }
|
||||
conditions.reverse_merge!(state: state) if state
|
||||
Milestone.where(conditions).order("title ASC")
|
||||
end
|
||||
end
|
|
@ -4,10 +4,10 @@ class Groups::MilestonesController < ApplicationController
|
|||
before_filter :authorize_group_milestone!, only: :update
|
||||
|
||||
def index
|
||||
project_milestones = case params[:status]
|
||||
when 'all'; status
|
||||
when 'closed'; status('closed')
|
||||
else status('active')
|
||||
project_milestones = case params[:state]
|
||||
when 'all'; state
|
||||
when 'closed'; state('closed')
|
||||
else state('active')
|
||||
end
|
||||
@group_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(30)
|
||||
|
@ -44,7 +44,7 @@ class Groups::MilestonesController < ApplicationController
|
|||
params[:title]
|
||||
end
|
||||
|
||||
def status(state = nil)
|
||||
def state(state = nil)
|
||||
conditions = { project_id: group.projects }
|
||||
conditions.reverse_merge!(state: state) if state
|
||||
Milestone.where(conditions).order("title ASC")
|
||||
|
|
|
@ -4,6 +4,8 @@ module MilestonesHelper
|
|||
namespace_project_milestones_path(@project.namespace, @project, opts)
|
||||
elsif @group
|
||||
group_milestones_path(@group, opts)
|
||||
else
|
||||
dashboard_milestones_path(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
10
app/views/dashboard/milestones/_issue.html.haml
Normal file
10
app/views/dashboard/milestones/_issue.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid }
|
||||
%span.milestone-row
|
||||
- project = issue.project
|
||||
%strong #{project.name_with_namespace} ·
|
||||
= link_to [project.namespace.becomes(Namespace), project, issue] do
|
||||
%span.cgray ##{issue.iid}
|
||||
= link_to_gfm issue.title, [project.namespace.becomes(Namespace), project, issue], title: issue.title
|
||||
.pull-right.assignee-icon
|
||||
- if issue.assignee
|
||||
= image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
|
6
app/views/dashboard/milestones/_issues.html.haml
Normal file
6
app/views/dashboard/milestones/_issues.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
.panel.panel-default
|
||||
.panel-heading= title
|
||||
%ul{ class: "well-list issues-sortable-list" }
|
||||
- if issues
|
||||
- issues.each do |issue|
|
||||
= render 'issue', issue: issue
|
10
app/views/dashboard/milestones/_merge_request.html.haml
Normal file
10
app/views/dashboard/milestones/_merge_request.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
%li{ id: dom_id(merge_request, 'sortable'), class: 'mr-row', 'data-iid' => merge_request.iid }
|
||||
%span.milestone-row
|
||||
- project = merge_request.project
|
||||
%strong #{project.name_with_namespace} ·
|
||||
= link_to [project.namespace.becomes(Namespace), project, merge_request] do
|
||||
%span.cgray ##{merge_request.iid}
|
||||
= link_to_gfm merge_request.title, [project.namespace.becomes(Namespace), project, merge_request], title: merge_request.title
|
||||
.pull-right.assignee-icon
|
||||
- if merge_request.assignee
|
||||
= image_tag avatar_icon(merge_request.assignee.email, 16), class: "avatar s16"
|
6
app/views/dashboard/milestones/_merge_requests.html.haml
Normal file
6
app/views/dashboard/milestones/_merge_requests.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
.panel.panel-default
|
||||
.panel-heading= title
|
||||
%ul{ class: "well-list merge_requests-sortable-list" }
|
||||
- if merge_requests
|
||||
- merge_requests.each do |merge_request|
|
||||
= render 'merge_request', merge_request: merge_request
|
39
app/views/dashboard/milestones/index.html.haml
Normal file
39
app/views/dashboard/milestones/index.html.haml
Normal file
|
@ -0,0 +1,39 @@
|
|||
%h3.page-title
|
||||
Milestones
|
||||
%span.pull-right #{@dashboard_milestones.count} milestones
|
||||
|
||||
%p.light
|
||||
List all milestones from all projects you have access to.
|
||||
|
||||
%hr
|
||||
|
||||
= render 'shared/milestones_filter'
|
||||
.milestones
|
||||
.panel.panel-default
|
||||
%ul.well-list
|
||||
- if @dashboard_milestones.blank?
|
||||
%li
|
||||
.nothing-here-block No milestones to show
|
||||
- else
|
||||
- @dashboard_milestones.each do |milestone|
|
||||
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
|
||||
%h4
|
||||
= link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
|
||||
%div
|
||||
%div
|
||||
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
|
||||
= pluralize milestone.issue_count, 'Issue'
|
||||
|
||||
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) 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.milestones.each do |milestone|
|
||||
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
|
||||
%span.label.label-default
|
||||
= milestone.project.name_with_namespace
|
||||
= paginate @dashboard_milestones, theme: "gitlab"
|
82
app/views/dashboard/milestones/show.html.haml
Normal file
82
app/views/dashboard/milestones/show.html.haml
Normal file
|
@ -0,0 +1,82 @@
|
|||
%h4.page-title
|
||||
.issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" }
|
||||
- if @dashboard_milestone.closed?
|
||||
Closed
|
||||
- else
|
||||
Open
|
||||
Milestone #{@dashboard_milestone.title}
|
||||
|
||||
%hr
|
||||
- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active?
|
||||
.alert.alert-success
|
||||
%span All issues for this milestone are closed. You may close the milestone now.
|
||||
|
||||
.description
|
||||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
%th Project
|
||||
%th Open issues
|
||||
%th State
|
||||
%th Due date
|
||||
- @dashboard_milestone.milestones.each do |milestone|
|
||||
%tr
|
||||
%td
|
||||
= link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
|
||||
%td
|
||||
= milestone.issues.opened.count
|
||||
%td
|
||||
- if milestone.closed?
|
||||
Closed
|
||||
- else
|
||||
Open
|
||||
%td
|
||||
= milestone.expires_at
|
||||
|
||||
.context
|
||||
%p.lead
|
||||
Progress:
|
||||
#{@dashboard_milestone.closed_items_count} closed
|
||||
–
|
||||
#{@dashboard_milestone.open_items_count} open
|
||||
.progress.progress-info
|
||||
.progress-bar{style: "width: #{@dashboard_milestone.percent_complete}%;"}
|
||||
|
||||
%ul.nav.nav-tabs
|
||||
%li.active
|
||||
= link_to '#tab-issues', 'data-toggle' => 'tab' do
|
||||
Issues
|
||||
%span.badge= @dashboard_milestone.issue_count
|
||||
%li
|
||||
= link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
|
||||
Merge Requests
|
||||
%span.badge= @dashboard_milestone.merge_requests_count
|
||||
%li
|
||||
= link_to '#tab-participants', 'data-toggle' => 'tab' do
|
||||
Participants
|
||||
%span.badge= @dashboard_milestone.participants.count
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active#tab-issues
|
||||
.row
|
||||
.col-md-6
|
||||
= render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues
|
||||
.col-md-6
|
||||
= render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues
|
||||
|
||||
.tab-pane#tab-merge-requests
|
||||
.row
|
||||
.col-md-6
|
||||
= render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests
|
||||
.col-md-6
|
||||
= render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests
|
||||
|
||||
.tab-pane#tab-participants
|
||||
%ul.bordered-list
|
||||
- @dashboard_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
|
|
@ -40,7 +40,8 @@
|
|||
.progress-bar{style: "width: #{milestone.percent_complete}%;"}
|
||||
%div
|
||||
%br
|
||||
- milestone.projects.each do |project|
|
||||
- milestone.milestones.each do |milestone|
|
||||
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
|
||||
%span.label.label-default
|
||||
= project.name
|
||||
= milestone.project.name
|
||||
= paginate @group_milestones, theme: "gitlab"
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
%i.fa.fa-cube
|
||||
%span
|
||||
Projects
|
||||
= nav_link(controller: :milestones) do
|
||||
= link_to dashboard_milestones_path, title: 'Milestones' do
|
||||
%i.fa.fa-clock-o
|
||||
%span
|
||||
Milestones
|
||||
= nav_link(path: 'dashboard#issues') do
|
||||
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do
|
||||
%i.fa.fa-exclamation-circle
|
||||
|
|
|
@ -220,6 +220,10 @@ Gitlab::Application.routes.draw do
|
|||
get :issues
|
||||
get :merge_requests
|
||||
end
|
||||
|
||||
scope module: :dashboard do
|
||||
resources :milestones, only: [:index, :show]
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -236,7 +240,7 @@ Gitlab::Application.routes.draw do
|
|||
scope module: :groups do
|
||||
resources :group_members, only: [:create, :update, :destroy]
|
||||
resource :avatar, only: [:destroy]
|
||||
resources :milestones
|
||||
resources :milestones, only: [:index, :show, :update]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue