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
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
ac5d8fdd
Commit
ac5d8fdd
authored
Mar 21, 2017
by
Valery Sizov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Multiple issue assignees] Starting point[ci skip]
parent
424c40ea
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
180 additions
and
15 deletions
+180
-15
app/controllers/concerns/issuable_collections.rb
app/controllers/concerns/issuable_collections.rb
+1
-1
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+0
-10
app/models/issue.rb
app/models/issue.rb
+16
-0
app/models/merge_request.rb
app/models/merge_request.rb
+11
-0
app/serializers/issuable_entity.rb
app/serializers/issuable_entity.rb
+0
-1
app/serializers/issue_entity.rb
app/serializers/issue_entity.rb
+1
-0
app/serializers/merge_request_entity.rb
app/serializers/merge_request_entity.rb
+1
-0
app/views/projects/issues/_issue.html.haml
app/views/projects/issues/_issue.html.haml
+3
-2
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+4
-0
app/views/shared/issuable/form/_issue_assignee.html.haml
app/views/shared/issuable/form/_issue_assignee.html.haml
+30
-0
app/views/shared/issuable/form/_merge_request_assignee.html.haml
...ws/shared/issuable/form/_merge_request_assignee.html.haml
+31
-0
db/migrate/20170320171632_create_issue_assignees_table.rb
db/migrate/20170320171632_create_issue_assignees_table.rb
+32
-0
db/migrate/20170320173259_migrate_assignees.rb
db/migrate/20170320173259_migrate_assignees.rb
+38
-0
db/schema.rb
db/schema.rb
+12
-1
No files found.
app/controllers/concerns/issuable_collections.rb
View file @
ac5d8fdd
...
...
@@ -40,7 +40,7 @@ module IssuableCollections
end
def
issues_collection
issues_finder
.
execute
.
preload
(
:project
,
:author
,
:assignee
,
:labels
,
:milestone
,
project: :namespace
)
issues_finder
.
execute
.
preload
(
:project
,
:author
,
:assignee
s
,
:labels
,
:milestone
,
project: :namespace
)
end
def
merge_requests_collection
...
...
app/models/concerns/issuable.rb
View file @
ac5d8fdd
...
...
@@ -25,7 +25,6 @@ module Issuable
cache_markdown_field
:description
belongs_to
:author
,
class_name:
"User"
belongs_to
:assignee
,
class_name:
"User"
belongs_to
:updated_by
,
class_name:
"User"
belongs_to
:milestone
has_many
:notes
,
as: :noteable
,
inverse_of: :noteable
,
dependent: :destroy
do
...
...
@@ -94,7 +93,6 @@ module Issuable
attr_mentionable
:description
participant
:author
participant
:assignee
participant
:notes_with_associations
strip_attributes
:title
...
...
@@ -313,14 +311,6 @@ module Issuable
@human_class_name
||=
self
.
class
.
name
.
titleize
.
downcase
end
# Returns a Hash of attributes to be used for Twitter card metadata
def
card_attributes
{
'Author'
=>
author
.
try
(
:name
),
'Assignee'
=>
assignee
.
try
(
:name
)
}
end
def
notes_with_associations
# If A has_many Bs, and B has_many Cs, and you do
# `A.includes(b: :c).each { |a| a.b.includes(:c) }`, sadly ActiveRecord
...
...
app/models/issue.rb
View file @
ac5d8fdd
...
...
@@ -29,6 +29,8 @@ class Issue < ActiveRecord::Base
has_many
:merge_requests_closing_issues
,
class_name:
'MergeRequestsClosingIssues'
,
dependent: :delete_all
has_and_belongs_to_many
:assignees
,
class_name:
"User"
,
join_table: :issue_assignees
validates
:project
,
presence:
true
scope
:cared
,
->
(
user
)
{
where
(
assignee_id:
user
)
}
...
...
@@ -51,6 +53,8 @@ class Issue < ActiveRecord::Base
attr_spammable
:title
,
spam_title:
true
attr_spammable
:description
,
spam_description:
true
participant
:assignees
state_machine
:state
,
initial: :opened
do
event
:close
do
transition
[
:reopened
,
:opened
]
=>
:closed
...
...
@@ -127,6 +131,18 @@ class Issue < ActiveRecord::Base
"id DESC"
)
end
# Returns a Hash of attributes to be used for Twitter card metadata
def
card_attributes
{
'Author'
=>
author
.
try
(
:name
),
'Assignee'
=>
assignee_list
}
end
def
assignee_list
assignees
.
pluck
(
:name
).
join
(
', '
)
end
# `from` argument can be a Namespace or Project.
def
to_reference
(
from
=
nil
,
full:
false
)
reference
=
"
#{
self
.
class
.
reference_prefix
}#{
iid
}
"
...
...
app/models/merge_request.rb
View file @
ac5d8fdd
...
...
@@ -22,6 +22,8 @@ class MergeRequest < ActiveRecord::Base
has_many
:merge_requests_closing_issues
,
class_name:
'MergeRequestsClosingIssues'
,
dependent: :delete_all
belongs_to
:assignee
,
class_name:
"User"
serialize
:merge_params
,
Hash
after_create
:ensure_merge_request_diff
,
unless: :importing?
...
...
@@ -121,6 +123,7 @@ class MergeRequest < ActiveRecord::Base
scope
:references_project
,
->
{
references
(
:target_project
)
}
participant
:approvers_left
participant
:assignee
after_save
:keep_around_commit
...
...
@@ -182,6 +185,14 @@ class MergeRequest < ActiveRecord::Base
work_in_progress?
(
title
)
?
title
:
"WIP:
#{
title
}
"
end
# Returns a Hash of attributes to be used for Twitter card metadata
def
card_attributes
{
'Author'
=>
author
.
try
(
:name
),
'Assignee'
=>
assignee
.
try
(
:name
)
}
end
# `from` argument can be a Namespace or Project.
def
to_reference
(
from
=
nil
,
full:
false
)
reference
=
"
#{
self
.
class
.
reference_prefix
}#{
iid
}
"
...
...
app/serializers/issuable_entity.rb
View file @
ac5d8fdd
class
IssuableEntity
<
Grape
::
Entity
expose
:id
expose
:iid
expose
:assignee_id
expose
:author_id
expose
:description
expose
:lock_version
...
...
app/serializers/issue_entity.rb
View file @
ac5d8fdd
class
IssueEntity
<
IssuableEntity
expose
:branch_name
expose
:confidential
expose
:assignee_ids
expose
:due_date
expose
:moved_to_id
expose
:project_id
...
...
app/serializers/merge_request_entity.rb
View file @
ac5d8fdd
class
MergeRequestEntity
<
IssuableEntity
expose
:approvals_before_merge
expose
:assignee_id
expose
:in_progress_merge_commit_sha
expose
:locked_at
expose
:merge_commit_sha
...
...
app/views/projects/issues/_issue.html.haml
View file @
ac5d8fdd
...
...
@@ -13,9 +13,10 @@
%li
CLOSED
-
if
issue
.
assignee
-
if
issue
.
assignee
s
.
any?
%li
=
link_to_member
(
@project
,
issue
.
assignee
,
name:
false
,
title:
"Assigned to :name"
)
-
issue
.
assignees
.
each
do
|
assignee
|
=
link_to_member
(
@project
,
assignee
,
name:
false
,
title:
"Assigned to :name"
)
=
render
'shared/issuable_meta_data'
,
issuable:
issue
...
...
app/views/shared/issuable/_sidebar.html.haml
View file @
ac5d8fdd
...
...
@@ -22,6 +22,7 @@
=
icon
(
'spin spinner'
,
class:
'hidden js-issuable-todo-loading'
,
'aria-hidden'
:
'true'
)
=
form_for
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
issuable
],
remote:
true
,
format: :json
,
html:
{
class:
'issuable-context-form inline-update js-issuable-update'
}
do
|
f
|
<
<<<<<<
HEAD
.block.assignee
.sidebar-collapsed-icon.sidebar-collapsed-user
{
data:
{
toggle:
"tooltip"
,
placement:
"left"
,
container:
"body"
},
title:
(
issuable
.
assignee
.
name
if
issuable
.
assignee
)
}
-
if
issuable
.
assignee
...
...
@@ -53,6 +54,9 @@
=
f
.
hidden_field
'assignee_id'
,
value:
issuable
.
assignee_id
,
id:
'issue_assignee_id'
=
dropdown_tag
(
'Select assignee'
,
options:
{
toggle_class:
'js-user-search js-author-search'
,
title:
'Assign to'
,
filter:
true
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author'
,
placeholder:
'Search users'
,
data:
{
first_user:
(
current_user
.
username
if
current_user
),
current_user:
true
,
project_id:
(
@project
.
id
if
@project
),
author_id:
issuable
.
author_id
,
field_name:
"
#{
issuable
.
to_ability_name
}
[assignee_id]"
,
issue_update:
issuable_json_path
(
issuable
),
ability_name:
issuable
.
to_ability_name
,
null_user:
true
}
})
==
=====
=
render
"shared/issuable/form/
#{
issuable
.
model_name
.
singular
}
_assignee"
,
can_edit_issuable:
can_edit_issuable
,
issuable:
issuable
,
f:
f
>
>>>>>> [Multiple issue assignees] Starting point[ci skip]
.block.milestone
.sidebar-collapsed-icon
=
icon
(
'clock-o'
,
'aria-hidden'
:
'true'
)
...
...
app/views/shared/issuable/form/_issue_assignee.html.haml
0 → 100644
View file @
ac5d8fdd
-
issue
=
issuable
.block.assignee
.sidebar-collapsed-icon.sidebar-collapsed-user
{
data:
{
toggle:
"tooltip"
,
placement:
"left"
,
container:
"body"
},
title:
(
issuable
.
assignee_list
)
}
-
if
issue
.
assignees
.
any?
-
issue
.
assignees
.
each
do
|
assignee
|
=
link_to_member
(
@project
,
assignee
,
size:
24
)
-
else
=
icon
(
'user'
,
'aria-hidden'
:
'true'
)
.title.hide-collapsed
Assignee
=
icon
(
'spinner spin'
,
class:
'hidden block-loading'
,
'aria-hidden'
:
'true'
)
-
if
can_edit_issuable
=
link_to
'Edit'
,
'#'
,
class:
'edit-link pull-right'
.value.hide-collapsed
-
if
issue
.
assignees
.
any?
-
issue
.
assignees
.
each
do
|
assignee
|
=
link_to_member
(
@project
,
assignee
,
size:
32
,
extra_class:
'bold'
)
do
%span
.username
=
assignee
.
to_reference
-
else
%span
.assign-yourself.no-value
No assignee
-
if
can_edit_issuable
\-
%a
.js-assign-yourself
{
href:
'#'
}
assign yourself
.selectbox.hide-collapsed
=
f
.
hidden_field
'assignee_id'
,
value:
issuable
.
assignee_id
,
id:
'issue_assignee_id'
=
dropdown_tag
(
'Select assignee'
,
options:
{
toggle_class:
'js-user-search js-author-search'
,
title:
'Assign to'
,
filter:
true
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author'
,
placeholder:
'Search users'
,
data:
{
first_user:
(
current_user
.
username
if
current_user
),
current_user:
true
,
project_id:
(
@project
.
id
if
@project
),
author_id:
issuable
.
author_id
,
field_name:
"
#{
issuable
.
to_ability_name
}
[assignee_id]"
,
issue_update:
issuable_json_path
(
issuable
),
ability_name:
issuable
.
to_ability_name
,
null_user:
true
}
})
app/views/shared/issuable/form/_merge_request_assignee.html.haml
0 → 100644
View file @
ac5d8fdd
-
merge_request
=
issuable
.block.assignee
.sidebar-collapsed-icon.sidebar-collapsed-user
{
data:
{
toggle:
"tooltip"
,
placement:
"left"
,
container:
"body"
},
title:
(
merge_request
.
assignee
.
name
if
merge_request
.
assignee
)
}
-
if
merge_request
.
assignee
=
link_to_member
(
@project
,
merge_request
.
assignee
,
size:
24
)
-
else
=
icon
(
'user'
,
'aria-hidden'
:
'true'
)
.title.hide-collapsed
Assignee
=
icon
(
'spinner spin'
,
class:
'hidden block-loading'
,
'aria-hidden'
:
'true'
)
-
if
can_edit_issuable
=
link_to
'Edit'
,
'#'
,
class:
'edit-link pull-right'
.value.hide-collapsed
-
if
merge_request
.
assignee
=
link_to_member
(
@project
,
merge_request
.
assignee
,
size:
32
,
extra_class:
'bold'
)
do
-
unless
merge_request
.
can_be_merged_by?
(
merge_request
.
assignee
)
%span
.pull-right.cannot-be-merged
{
data:
{
toggle:
'tooltip'
,
placement:
'left'
},
title:
'Not allowed to merge'
}
=
icon
(
'exclamation-triangle'
,
'aria-hidden'
:
'true'
)
%span
.username
=
merge_request
.
assignee
.
to_reference
-
else
%span
.assign-yourself.no-value
No assignee
-
if
can_edit_issuable
\-
%a
.js-assign-yourself
{
href:
'#'
}
assign yourself
.selectbox.hide-collapsed
=
f
.
hidden_field
'assignee_id'
,
value:
merge_request
.
assignee_id
,
id:
'issue_assignee_id'
=
dropdown_tag
(
'Select assignee'
,
options:
{
toggle_class:
'js-user-search js-author-search'
,
title:
'Assign to'
,
filter:
true
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author'
,
placeholder:
'Search users'
,
data:
{
first_user:
(
current_user
.
username
if
current_user
),
current_user:
true
,
project_id:
(
@project
.
id
if
@project
),
author_id:
merge_request
.
author_id
,
field_name:
"
#{
merge_request
.
to_ability_name
}
[assignee_id]"
,
issue_update:
merge_request_json_path
(
merge_request
),
ability_name:
'merge_request'
,
null_user:
true
}
})
db/migrate/20170320171632_create_issue_assignees_table.rb
0 → 100644
View file @
ac5d8fdd
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
CreateIssueAssigneesTable
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index" or "add_column_with_default"
# you must disable the use of transactions as these methods can not run in an
# existing transaction. When using "add_concurrent_index" make sure that this
# method is the _only_ method called in the migration, any other changes
# should go in a separate migration. This ensures that upon failure _only_ the
# index creation fails and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
# disable_ddl_transaction!
def
change
create_table
:issue_assignees
do
|
t
|
t
.
references
:user
,
foreign_key:
true
,
index:
true
t
.
references
:issue
,
foreign_key:
true
,
index:
true
end
end
end
db/migrate/20170320173259_migrate_assignees.rb
0 → 100644
View file @
ac5d8fdd
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
MigrateAssignees
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index" or "add_column_with_default"
# you must disable the use of transactions as these methods can not run in an
# existing transaction. When using "add_concurrent_index" make sure that this
# method is the _only_ method called in the migration, any other changes
# should go in a separate migration. This ensures that upon failure _only_ the
# index creation fails and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
# disable_ddl_transaction!
def
up
execute
<<-
EOF
INSERT INTO issue_assignees(issue_id, user_id)
SELECT id, assignee_id FROM issues WHERE assignee_id IS NOT NULL
EOF
end
def
down
execute
<<-
EOF
DELETE FROM issue_assignees
EOF
end
end
db/schema.rb
View file @
ac5d8fdd
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201703
17203554
)
do
ActiveRecord
::
Schema
.
define
(
version:
201703
20173259
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -495,6 +495,14 @@ ActiveRecord::Schema.define(version: 20170317203554) do
add_index
"index_statuses"
,
[
"project_id"
],
name:
"index_index_statuses_on_project_id"
,
unique:
true
,
using: :btree
create_table
"issue_assignees"
,
force: :cascade
do
|
t
|
t
.
integer
"user_id"
,
null:
false
t
.
integer
"issue_id"
,
null:
false
end
add_index
"issue_assignees"
,
[
"issue_id"
,
"user_id"
],
name:
"index_issue_assignees_on_issue_id_and_user_id"
,
unique:
true
,
using: :btree
add_index
"issue_assignees"
,
[
"user_id"
],
name:
"index_issue_assignees_on_user_id"
,
using: :btree
create_table
"issue_metrics"
,
force: :cascade
do
|
t
|
t
.
integer
"issue_id"
,
null:
false
t
.
datetime
"first_mentioned_in_commit_at"
...
...
@@ -1436,6 +1444,7 @@ ActiveRecord::Schema.define(version: 20170317203554) do
t
.
boolean
"authorized_projects_populated"
t
.
boolean
"auditor"
,
default:
false
,
null:
false
t
.
boolean
"ghost"
t
.
boolean
"notified_of_own_activity"
,
default:
false
,
null:
false
end
add_index
"users"
,
[
"admin"
],
name:
"index_users_on_admin"
,
using: :btree
...
...
@@ -1491,6 +1500,8 @@ ActiveRecord::Schema.define(version: 20170317203554) do
add_foreign_key
"boards"
,
"projects"
add_foreign_key
"chat_teams"
,
"namespaces"
,
on_delete: :cascade
add_foreign_key
"ci_triggers"
,
"users"
,
column:
"owner_id"
,
name:
"fk_e8e10d1964"
,
on_delete: :cascade
add_foreign_key
"issue_assignees"
,
"issues"
,
on_delete: :cascade
add_foreign_key
"issue_assignees"
,
"users"
,
on_delete: :cascade
add_foreign_key
"issue_metrics"
,
"issues"
,
on_delete: :cascade
add_foreign_key
"label_priorities"
,
"labels"
,
on_delete: :cascade
add_foreign_key
"label_priorities"
,
"projects"
,
on_delete: :cascade
...
...
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