Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gitlab-ce
Commits
1f1c59b6
Commit
1f1c59b6
authored
May 13, 2014
by
Dmitriy Zaporozhets
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6778 from dblessing/feature/mr_labels
Merge Request Labels
parents
0c621708
5f25cdfe
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
142 additions
and
17 deletions
+142
-17
app/assets/stylesheets/sections/merge_requests.scss
app/assets/stylesheets/sections/merge_requests.scss
+8
-0
app/controllers/application_controller.rb
app/controllers/application_controller.rb
+5
-0
app/controllers/projects/labels_controller.rb
app/controllers/projects/labels_controller.rb
+9
-4
app/models/merge_request.rb
app/models/merge_request.rb
+6
-1
app/models/project.rb
app/models/project.rb
+4
-1
app/views/projects/issues/index.html.haml
app/views/projects/issues/index.html.haml
+2
-1
app/views/projects/merge_requests/_form.html.haml
app/views/projects/merge_requests/_form.html.haml
+38
-0
app/views/projects/merge_requests/_merge_request.html.haml
app/views/projects/merge_requests/_merge_request.html.haml
+6
-0
app/views/projects/merge_requests/_show.html.haml
app/views/projects/merge_requests/_show.html.haml
+1
-0
app/views/projects/merge_requests/index.html.haml
app/views/projects/merge_requests/index.html.haml
+2
-1
app/views/projects/merge_requests/show/_participants.html.haml
...iews/projects/merge_requests/show/_participants.html.haml
+11
-0
app/views/shared/_project_filter.html.haml
app/views/shared/_project_filter.html.haml
+1
-1
lib/api/entities.rb
lib/api/entities.rb
+1
-0
lib/api/merge_requests.rb
lib/api/merge_requests.rb
+4
-0
spec/requests/api/projects_spec.rb
spec/requests/api/projects_spec.rb
+44
-8
No files found.
app/assets/stylesheets/sections/merge_requests.scss
View file @
1f1c59b6
...
@@ -73,6 +73,10 @@
...
@@ -73,6 +73,10 @@
.merge-request-info
{
.merge-request-info
{
color
:
#999
;
color
:
#999
;
.merge-request-labels
{
display
:
inline-block
;
}
}
}
}
}
}
}
...
@@ -111,3 +115,7 @@
...
@@ -111,3 +115,7 @@
}
}
}
}
}
}
.merge-request-show-labels
.label
{
padding
:
6px
10px
;
}
app/controllers/application_controller.rb
View file @
1f1c59b6
...
@@ -117,6 +117,11 @@ class ApplicationController < ActionController::Base
...
@@ -117,6 +117,11 @@ class ApplicationController < ActionController::Base
return
access_denied!
unless
can?
(
current_user
,
:push_code
,
project
)
return
access_denied!
unless
can?
(
current_user
,
:push_code
,
project
)
end
end
def
authorize_labels!
# Labels should be accessible for issues and/or merge requests
authorize_read_issue!
||
authorize_read_merge_request!
end
def
access_denied!
def
access_denied!
render
"errors/access_denied"
,
layout:
"errors"
,
status:
404
render
"errors/access_denied"
,
layout:
"errors"
,
status:
404
end
end
...
...
app/controllers/projects/labels_controller.rb
View file @
1f1c59b6
class
Projects::LabelsController
<
Projects
::
ApplicationController
class
Projects::LabelsController
<
Projects
::
ApplicationController
before_filter
:module_enabled
before_filter
:module_enabled
# Allow read any issue
before_filter
:authorize_labels!
before_filter
:authorize_read_issue!
respond_to
:js
,
:html
respond_to
:js
,
:html
...
@@ -13,12 +12,18 @@ class Projects::LabelsController < Projects::ApplicationController
...
@@ -13,12 +12,18 @@ class Projects::LabelsController < Projects::ApplicationController
def
generate
def
generate
Gitlab
::
IssuesLabels
.
generate
(
@project
)
Gitlab
::
IssuesLabels
.
generate
(
@project
)
redirect_to
project_issues_path
(
@project
)
if
params
[
:redirect
]
==
'issues'
redirect_to
project_issues_path
(
@project
)
elsif
params
[
:redirect
]
==
'merge_requests'
redirect_to
project_merge_requests_path
(
@project
)
end
end
end
protected
protected
def
module_enabled
def
module_enabled
return
render_404
unless
@project
.
issues_enabled
unless
@project
.
issues_enabled
||
@project
.
merge_requests_enabled
return
render_404
end
end
end
end
end
app/models/merge_request.rb
View file @
1f1c59b6
...
@@ -36,7 +36,9 @@ class MergeRequest < ActiveRecord::Base
...
@@ -36,7 +36,9 @@ class MergeRequest < ActiveRecord::Base
delegate
:commits
,
:diffs
,
:last_commit
,
:last_commit_short_sha
,
to: :merge_request_diff
,
prefix:
nil
delegate
:commits
,
:diffs
,
:last_commit
,
:last_commit_short_sha
,
to: :merge_request_diff
,
prefix:
nil
attr_accessible
:title
,
:assignee_id
,
:source_project_id
,
:source_branch
,
:target_project_id
,
:target_branch
,
:milestone_id
,
:state_event
,
:description
attr_accessible
:title
,
:assignee_id
,
:source_project_id
,
:source_branch
,
:target_project_id
,
:target_branch
,
:milestone_id
,
:state_event
,
:description
,
:label_list
attr_accessor
:should_remove_source_branch
attr_accessor
:should_remove_source_branch
...
@@ -44,6 +46,9 @@ class MergeRequest < ActiveRecord::Base
...
@@ -44,6 +46,9 @@ class MergeRequest < ActiveRecord::Base
# It allows us to close or modify broken merge requests
# It allows us to close or modify broken merge requests
attr_accessor
:allow_broken
attr_accessor
:allow_broken
ActsAsTaggableOn
.
strict_case_match
=
true
acts_as_taggable_on
:labels
state_machine
:state
,
initial: :opened
do
state_machine
:state
,
initial: :opened
do
event
:close
do
event
:close
do
transition
[
:reopened
,
:opened
]
=>
:closed
transition
[
:reopened
,
:opened
]
=>
:closed
...
...
app/models/project.rb
View file @
1f1c59b6
...
@@ -281,8 +281,11 @@ class Project < ActiveRecord::Base
...
@@ -281,8 +281,11 @@ class Project < ActiveRecord::Base
self
.
id
self
.
id
end
end
# Tags are shared by issues and merge requests
def
issues_labels
def
issues_labels
@issues_labels
||=
(
issues_default_labels
+
issues
.
tags_on
(
:labels
)).
uniq
.
sort_by
(
&
:name
)
@issues_labels
||=
(
issues_default_labels
+
merge_requests
.
tags_on
(
:labels
)
+
issues
.
tags_on
(
:labels
)).
uniq
.
sort_by
(
&
:name
)
end
end
def
issue_exists?
(
issue_id
)
def
issue_exists?
(
issue_id
)
...
...
app/views/projects/issues/index.html.haml
View file @
1f1c59b6
=
render
"head"
=
render
"head"
.row
.row
.col-md-3
.col-md-3
=
render
'shared/project_filter'
,
project_entities_path:
project_issues_path
(
@project
),
labels:
true
=
render
'shared/project_filter'
,
project_entities_path:
project_issues_path
(
@project
),
labels:
true
,
redirect:
'issues'
.col-md-9.issues-holder
.col-md-9.issues-holder
=
render
"issues"
=
render
"issues"
app/views/projects/merge_requests/_form.html.haml
View file @
1f1c59b6
...
@@ -42,6 +42,15 @@
...
@@ -42,6 +42,15 @@
.col-sm-10
=
f
.
select
(
:milestone_id
,
milestone_options
(
@merge_request
),
{
include_blank:
"Select milestone"
},
{
class:
'select2'
})
.col-sm-10
=
f
.
select
(
:milestone_id
,
milestone_options
(
@merge_request
),
{
include_blank:
"Select milestone"
},
{
class:
'select2'
})
-
if
@merge_request
.
persisted?
# Only allow labels on edit to avoid fork vs upstream repo labels issue
.form-group
=
f
.
label
:label_list
,
class:
'control-label'
do
%i
.icon-tag
Labels
.col-sm-10
=
f
.
text_field
:label_list
,
maxlength:
2000
,
class:
"form-control"
%p
.hint
Separate labels with commas.
.form-actions
.form-actions
-
if
@merge_request
.
new_record?
-
if
@merge_request
.
new_record?
=
f
.
submit
'Submit merge request'
,
class:
"btn btn-create"
=
f
.
submit
'Submit merge request'
,
class:
"btn btn-create"
...
@@ -60,3 +69,32 @@
...
@@ -60,3 +69,32 @@
$
(
'
#merge_request_assignee_id
'
).
val
(
"
#{
current_user
.
id
}
"
).
trigger
(
"
change
"
);
$
(
'
#merge_request_assignee_id
'
).
val
(
"
#{
current_user
.
id
}
"
).
trigger
(
"
change
"
);
e
.
preventDefault
();
e
.
preventDefault
();
});
});
$
(
"
#merge_request_label_list
"
)
.
bind
(
"
keydown
"
,
function
(
event
)
{
if
(
event
.
keyCode
===
$
.
ui
.
keyCode
.
TAB
&&
$
(
this
).
data
(
"
autocomplete
"
).
menu
.
active
)
{
event
.
preventDefault
();
}
})
.
bind
(
"
click
"
,
function
(
event
)
{
$
(
this
).
autocomplete
(
"
search
"
,
""
);
})
.
autocomplete
({
minLength
:
0
,
source
:
function
(
request
,
response
)
{
response
(
$
.
ui
.
autocomplete
.
filter
(
#{
raw
labels_autocomplete_source
}
,
extractLast
(
request
.
term
)
)
);
},
focus
:
function
()
{
return
false
;
},
select
:
function
(
event
,
ui
)
{
var
terms
=
split
(
this
.
value
);
terms
.
pop
();
terms
.
push
(
ui
.
item
.
value
);
terms
.
push
(
""
);
this
.
value
=
terms
.
join
(
"
,
"
);
return
false
;
}
});
app/views/projects/merge_requests/_merge_request.html.haml
View file @
1f1c59b6
...
@@ -31,3 +31,9 @@
...
@@ -31,3 +31,9 @@
.pull-right
.pull-right
%small
updated
#{
time_ago_with_tooltip
(
merge_request
.
updated_at
,
'bottom'
,
'merge_request_updated_ago'
)
}
%small
updated
#{
time_ago_with_tooltip
(
merge_request
.
updated_at
,
'bottom'
,
'merge_request_updated_ago'
)
}
.merge-request-labels
-
merge_request
.
labels
.
each
do
|
label
|
%span
{
class:
"label #{label_css_class(label.name)}"
}
%i
.icon-tag
=
label
.
name
app/views/projects/merge_requests/_show.html.haml
View file @
1f1c59b6
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
=
render
"projects/merge_requests/show/mr_box"
=
render
"projects/merge_requests/show/mr_box"
=
render
"projects/merge_requests/show/state_widget"
=
render
"projects/merge_requests/show/state_widget"
=
render
"projects/merge_requests/show/commits"
=
render
"projects/merge_requests/show/commits"
=
render
"projects/merge_requests/show/participants"
-
if
@commits
.
present?
-
if
@commits
.
present?
%ul
.nav.nav-tabs
%ul
.nav.nav-tabs
...
...
app/views/projects/merge_requests/index.html.haml
View file @
1f1c59b6
...
@@ -8,7 +8,8 @@
...
@@ -8,7 +8,8 @@
%hr
%hr
.row
.row
.col-md-3
.col-md-3
=
render
'shared/project_filter'
,
project_entities_path:
project_merge_requests_path
(
@project
)
=
render
'shared/project_filter'
,
project_entities_path:
project_merge_requests_path
(
@project
),
labels:
true
,
redirect:
'merge_requests'
.col-md-9
.col-md-9
.mr-filters.append-bottom-10
.mr-filters.append-bottom-10
.dropdown.inline
.dropdown.inline
...
...
app/views/projects/merge_requests/show/_participants.html.haml
0 → 100644
View file @
1f1c59b6
.participants
%cite
.cgray
#{
@merge_request
.
participants
.
count
}
participants
-
@merge_request
.
participants
.
each
do
|
participant
|
=
link_to_member
(
@project
,
participant
,
name:
false
,
size:
24
)
.merge-request-show-labels.pull-right
-
@merge_request
.
labels
.
each
do
|
label
|
%span
{
class:
"label #{label_css_class(label.name)}"
}
%i
.icon-tag
=
label
.
name
app/views/shared/_project_filter.html.haml
View file @
1f1c59b6
...
@@ -44,7 +44,7 @@
...
@@ -44,7 +44,7 @@
.light-well
.light-well
Add first label to your issues
Add first label to your issues
%br
%br
or
#{
link_to
'generate'
,
generate_project_labels_path
(
@project
),
method: :post
}
default set of labels
or
#{
link_to
'generate'
,
generate_project_labels_path
(
@project
,
redirect:
redirect
),
method: :post
}
default set of labels
%fieldset
%fieldset
-
if
%w(state scope milestone_id assignee_id label_name)
.
select
{
|
k
|
params
[
k
].
present?
}.
any?
-
if
%w(state scope milestone_id assignee_id label_name)
.
select
{
|
k
|
params
[
k
].
present?
}.
any?
...
...
lib/api/entities.rb
View file @
1f1c59b6
...
@@ -136,6 +136,7 @@ module API
...
@@ -136,6 +136,7 @@ module API
expose
:target_branch
,
:source_branch
,
:upvotes
,
:downvotes
expose
:target_branch
,
:source_branch
,
:upvotes
,
:downvotes
expose
:author
,
:assignee
,
using:
Entities
::
UserBasic
expose
:author
,
:assignee
,
using:
Entities
::
UserBasic
expose
:source_project_id
,
:target_project_id
expose
:source_project_id
,
:target_project_id
expose
:label_list
,
as: :labels
end
end
class
SSHKey
<
Grape
::
Entity
class
SSHKey
<
Grape
::
Entity
...
...
lib/api/merge_requests.rb
View file @
1f1c59b6
...
@@ -67,6 +67,7 @@ module API
...
@@ -67,6 +67,7 @@ module API
# assignee_id - Assignee user ID
# assignee_id - Assignee user ID
# title (required) - Title of MR
# title (required) - Title of MR
# description - Description of MR
# description - Description of MR
# labels (optional) - Labels for MR as a comma-separated list
#
#
# Example:
# Example:
# POST /projects/:id/merge_requests
# POST /projects/:id/merge_requests
...
@@ -75,6 +76,7 @@ module API
...
@@ -75,6 +76,7 @@ module API
authorize!
:write_merge_request
,
user_project
authorize!
:write_merge_request
,
user_project
required_attributes!
[
:source_branch
,
:target_branch
,
:title
]
required_attributes!
[
:source_branch
,
:target_branch
,
:title
]
attrs
=
attributes_for_keys
[
:source_branch
,
:target_branch
,
:assignee_id
,
:title
,
:target_project_id
,
:description
]
attrs
=
attributes_for_keys
[
:source_branch
,
:target_branch
,
:assignee_id
,
:title
,
:target_project_id
,
:description
]
attrs
[
:label_list
]
=
params
[
:labels
]
if
params
[
:labels
].
present?
merge_request
=
::
MergeRequests
::
CreateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
merge_request
=
::
MergeRequests
::
CreateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
if
merge_request
.
valid?
if
merge_request
.
valid?
...
@@ -95,11 +97,13 @@ module API
...
@@ -95,11 +97,13 @@ module API
# title - Title of MR
# title - Title of MR
# state_event - Status of MR. (close|reopen|merge)
# state_event - Status of MR. (close|reopen|merge)
# description - Description of MR
# description - Description of MR
# labels (optional) - Labels for a MR as a comma-separated list
# Example:
# Example:
# PUT /projects/:id/merge_request/:merge_request_id
# PUT /projects/:id/merge_request/:merge_request_id
#
#
put
":id/merge_request/:merge_request_id"
do
put
":id/merge_request/:merge_request_id"
do
attrs
=
attributes_for_keys
[
:source_branch
,
:target_branch
,
:assignee_id
,
:title
,
:state_event
,
:description
]
attrs
=
attributes_for_keys
[
:source_branch
,
:target_branch
,
:assignee_id
,
:title
,
:state_event
,
:description
]
attrs
[
:label_list
]
=
params
[
:labels
]
if
params
[
:labels
].
present?
merge_request
=
user_project
.
merge_requests
.
find
(
params
[
:merge_request_id
])
merge_request
=
user_project
.
merge_requests
.
find
(
params
[
:merge_request_id
])
authorize!
:modify_merge_request
,
merge_request
authorize!
:modify_merge_request
,
merge_request
merge_request
=
::
MergeRequests
::
UpdateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
(
merge_request
)
merge_request
=
::
MergeRequests
::
UpdateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
(
merge_request
)
...
...
spec/requests/api/projects_spec.rb
View file @
1f1c59b6
...
@@ -14,6 +14,12 @@ describe API::API, api: true do
...
@@ -14,6 +14,12 @@ describe API::API, api: true do
let
(
:users_project
)
{
create
(
:users_project
,
user:
user
,
project:
project
,
project_access:
UsersProject
::
MASTER
)
}
let
(
:users_project
)
{
create
(
:users_project
,
user:
user
,
project:
project
,
project_access:
UsersProject
::
MASTER
)
}
let
(
:users_project2
)
{
create
(
:users_project
,
user:
user3
,
project:
project
,
project_access:
UsersProject
::
DEVELOPER
)
}
let
(
:users_project2
)
{
create
(
:users_project
,
user:
user3
,
project:
project
,
project_access:
UsersProject
::
DEVELOPER
)
}
let
(
:issue_with_labels
)
{
create
(
:issue
,
author:
user
,
assignee:
user
,
project:
project
,
:label_list
=>
"label1, label2"
)
}
let
(
:issue_with_labels
)
{
create
(
:issue
,
author:
user
,
assignee:
user
,
project:
project
,
:label_list
=>
"label1, label2"
)
}
let
(
:merge_request_with_labels
)
do
create
(
:merge_request
,
:simple
,
author:
user
,
assignee:
user
,
source_project:
project
,
target_project:
project
,
title:
'Test'
,
label_list:
'label3, label4'
)
end
describe
"GET /projects"
do
describe
"GET /projects"
do
before
{
project
}
before
{
project
}
...
@@ -634,15 +640,45 @@ describe API::API, api: true do
...
@@ -634,15 +640,45 @@ describe API::API, api: true do
end
end
end
end
describe
"GET /projects/:id/labels"
do
describe
'GET /projects/:id/labels'
do
before
{
issue_with_labels
}
context
'with an issue'
do
before
{
issue_with_labels
}
it
"should return project labels"
do
it
'should return project labels'
do
get
api
(
"/projects/
#{
project
.
id
}
/labels"
,
user
)
get
api
(
"/projects/
#{
project
.
id
}
/labels"
,
user
)
response
.
status
.
should
==
200
response
.
status
.
should
==
200
json_response
.
should
be_an
Array
json_response
.
should
be_an
Array
json_response
.
first
[
'name'
].
should
==
issue_with_labels
.
labels
.
first
.
name
json_response
.
first
[
'name'
].
should
==
issue_with_labels
.
labels
.
first
.
name
json_response
.
last
[
'name'
].
should
==
issue_with_labels
.
labels
.
last
.
name
json_response
.
last
[
'name'
].
should
==
issue_with_labels
.
labels
.
last
.
name
end
end
context
'with a merge request'
do
before
{
merge_request_with_labels
}
it
'should return project labels'
do
get
api
(
"/projects/
#{
project
.
id
}
/labels"
,
user
)
response
.
status
.
should
==
200
json_response
.
should
be_an
Array
json_response
.
first
[
'name'
].
should
==
merge_request_with_labels
.
labels
.
first
.
name
json_response
.
last
[
'name'
].
should
==
merge_request_with_labels
.
labels
.
last
.
name
end
end
context
'with an issue and a merge request'
do
before
do
issue_with_labels
merge_request_with_labels
end
it
'should return project labels from both'
do
get
api
(
"/projects/
#{
project
.
id
}
/labels"
,
user
)
response
.
status
.
should
==
200
json_response
.
should
be_an
Array
all_labels
=
issue_with_labels
.
labels
.
map
(
&
:name
).
to_a
.
concat
(
merge_request_with_labels
.
labels
.
map
(
&
:name
).
to_a
)
json_response
.
map
{
|
e
|
e
[
'name'
]
}.
should
=~
all_labels
end
end
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment