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
3bdc57f0
Commit
3bdc57f0
authored
Apr 16, 2016
by
Zeger-Jan van de Weg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create table for award emoji
parent
05920a79
Changes
41
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
446 additions
and
307 deletions
+446
-307
app/controllers/concerns/toggle_award_emoji.rb
app/controllers/concerns/toggle_award_emoji.rb
+20
-0
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+3
-1
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+4
-2
app/controllers/projects/notes_controller.rb
app/controllers/projects/notes_controller.rb
+7
-28
app/controllers/projects_controller.rb
app/controllers/projects_controller.rb
+1
-1
app/helpers/issues_helper.rb
app/helpers/issues_helper.rb
+7
-6
app/models/award_emoji.rb
app/models/award_emoji.rb
+35
-0
app/models/concerns/awardable.rb
app/models/concerns/awardable.rb
+81
-0
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+1
-31
app/models/merge_request.rb
app/models/merge_request.rb
+1
-0
app/models/note.rb
app/models/note.rb
+11
-42
app/models/user.rb
app/models/user.rb
+1
-0
app/services/notes/create_service.rb
app/services/notes/create_service.rb
+5
-0
app/services/notes/post_process_service.rb
app/services/notes/post_process_service.rb
+1
-1
app/services/notification_service.rb
app/services/notification_service.rb
+0
-1
app/services/todo_service.rb
app/services/todo_service.rb
+8
-0
app/services/toggle_award_emoji_service.rb
app/services/toggle_award_emoji_service.rb
+21
-0
app/views/award_emoji/_awards_block.html.haml
app/views/award_emoji/_awards_block.html.haml
+15
-0
app/views/emojis/index.html.haml
app/views/emojis/index.html.haml
+2
-2
app/views/projects/issues/_issue.html.haml
app/views/projects/issues/_issue.html.haml
+1
-1
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+1
-1
app/views/projects/merge_requests/_merge_request.html.haml
app/views/projects/merge_requests/_merge_request.html.haml
+1
-1
app/views/projects/merge_requests/_show.html.haml
app/views/projects/merge_requests/_show.html.haml
+2
-2
app/views/votes/_votes_block.html.haml
app/views/votes/_votes_block.html.haml
+4
-4
config/initializers/inflections.rb
config/initializers/inflections.rb
+4
-0
config/routes.rb
config/routes.rb
+3
-4
db/migrate/20160416180807_add_award_emoji.rb
db/migrate/20160416180807_add_award_emoji.rb
+15
-0
db/migrate/20160416182152_convert_award_note_to_emoji_award.rb
...grate/20160416182152_convert_award_note_to_emoji_award.rb
+17
-0
db/migrate/20160416190505_remove_note_is_award.rb
db/migrate/20160416190505_remove_note_is_award.rb
+5
-0
db/schema.rb
db/schema.rb
+32
-21
lib/api/entities.rb
lib/api/entities.rb
+4
-3
lib/award_emoji.rb
lib/award_emoji.rb
+0
-80
lib/gitlab/award_emoji.rb
lib/gitlab/award_emoji.rb
+82
-0
spec/controllers/groups_controller_spec.rb
spec/controllers/groups_controller_spec.rb
+6
-6
spec/factories/award_emoji.rb
spec/factories/award_emoji.rb
+7
-0
spec/factories/notes.rb
spec/factories/notes.rb
+0
-6
spec/helpers/issues_helper_spec.rb
spec/helpers/issues_helper_spec.rb
+4
-7
spec/lib/gitlab/award_emoji_spec.rb
spec/lib/gitlab/award_emoji_spec.rb
+3
-3
spec/models/award_emoji_spec.rb
spec/models/award_emoji_spec.rb
+31
-0
spec/models/concerns/issuable_spec.rb
spec/models/concerns/issuable_spec.rb
+0
-14
spec/models/note_spec.rb
spec/models/note_spec.rb
+0
-39
No files found.
app/controllers/concerns/toggle_award_emoji.rb
0 → 100644
View file @
3bdc57f0
module
ToggleAwardEmoji
extend
ActiveSupport
::
Concern
included
do
before_action
:authenticate_user!
,
only:
[
:toggle_award_emoji
]
end
def
toggle_award_emoji
name
=
params
.
require
(
:name
)
awardable
.
toggle_award_emoji
(
name
,
current_user
)
render
json:
{
ok:
true
}
end
private
def
awardable
raise
NotImplementedError
end
end
app/controllers/projects/issues_controller.rb
View file @
3bdc57f0
class
Projects::IssuesController
<
Projects
::
ApplicationController
class
Projects::IssuesController
<
Projects
::
ApplicationController
include
ToggleSubscriptionAction
include
ToggleSubscriptionAction
include
IssuableActions
include
IssuableActions
include
ToggleAwardEmoji
before_action
:module_enabled
before_action
:module_enabled
before_action
:issue
,
before_action
:issue
,
...
@@ -61,7 +62,7 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -61,7 +62,7 @@ class Projects::IssuesController < Projects::ApplicationController
def
show
def
show
@note
=
@project
.
notes
.
new
(
noteable:
@issue
)
@note
=
@project
.
notes
.
new
(
noteable:
@issue
)
@notes
=
@issue
.
notes
.
nonawards
.
with_associations
.
fresh
@notes
=
@issue
.
notes
.
with_associations
.
fresh
@noteable
=
@issue
@noteable
=
@issue
respond_to
do
|
format
|
respond_to
do
|
format
|
...
@@ -158,6 +159,7 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -158,6 +159,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
alias_method
:subscribable_resource
,
:issue
alias_method
:subscribable_resource
,
:issue
alias_method
:issuable
,
:issue
alias_method
:issuable
,
:issue
alias_method
:awardable
,
:issue
def
authorize_read_issue!
def
authorize_read_issue!
return
render_404
unless
can?
(
current_user
,
:read_issue
,
@issue
)
return
render_404
unless
can?
(
current_user
,
:read_issue
,
@issue
)
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
3bdc57f0
...
@@ -2,6 +2,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -2,6 +2,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
include
ToggleSubscriptionAction
include
ToggleSubscriptionAction
include
DiffHelper
include
DiffHelper
include
IssuableActions
include
IssuableActions
include
ToggleAwardEmoji
before_action
:module_enabled
before_action
:module_enabled
before_action
:merge_request
,
only:
[
before_action
:merge_request
,
only:
[
...
@@ -195,7 +196,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -195,7 +196,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if
params
[
:merge_when_build_succeeds
].
present?
&&
@merge_request
.
ci_commit
&&
@merge_request
.
ci_commit
.
active?
if
params
[
:merge_when_build_succeeds
].
present?
&&
@merge_request
.
ci_commit
&&
@merge_request
.
ci_commit
.
active?
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
@project
,
current_user
,
merge_params
)
MergeRequests
::
MergeWhenBuildSucceedsService
.
new
(
@project
,
current_user
,
merge_params
)
.
execute
(
@merge_request
)
.
execute
(
@merge_request
)
@status
=
:merge_when_build_succeeds
@status
=
:merge_when_build_succeeds
else
else
MergeWorker
.
perform_async
(
@merge_request
.
id
,
current_user
.
id
,
params
)
MergeWorker
.
perform_async
(
@merge_request
.
id
,
current_user
.
id
,
params
)
...
@@ -264,6 +265,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -264,6 +265,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
alias_method
:subscribable_resource
,
:merge_request
alias_method
:subscribable_resource
,
:merge_request
alias_method
:issuable
,
:merge_request
alias_method
:issuable
,
:merge_request
alias_method
:awardable
,
:merge_request
def
closes_issues
def
closes_issues
@closes_issues
||=
@merge_request
.
closes_issues
@closes_issues
||=
@merge_request
.
closes_issues
...
@@ -299,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
...
@@ -299,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def
define_show_vars
def
define_show_vars
# Build a note object for comment form
# Build a note object for comment form
@note
=
@project
.
notes
.
new
(
noteable:
@merge_request
)
@note
=
@project
.
notes
.
new
(
noteable:
@merge_request
)
@notes
=
@merge_request
.
mr_and_commit_notes
.
nonawards
.
inc_author
.
fresh
@notes
=
@merge_request
.
mr_and_commit_notes
.
inc_author
.
fresh
@discussions
=
Note
.
discussions_from_notes
(
@notes
)
@discussions
=
Note
.
discussions_from_notes
(
@notes
)
@noteable
=
@merge_request
@noteable
=
@merge_request
...
...
app/controllers/projects/notes_controller.rb
View file @
3bdc57f0
...
@@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -3,7 +3,7 @@ class Projects::NotesController < Projects::ApplicationController
before_action
:authorize_read_note!
before_action
:authorize_read_note!
before_action
:authorize_create_note!
,
only:
[
:create
]
before_action
:authorize_create_note!
,
only:
[
:create
]
before_action
:authorize_admin_note!
,
only:
[
:update
,
:destroy
]
before_action
:authorize_admin_note!
,
only:
[
:update
,
:destroy
]
before_action
:find_current_user_notes
,
except:
[
:destroy
,
:delete_attachment
,
:award_toggle
]
before_action
:find_current_user_notes
,
only:
[
:index
]
def
index
def
index
current_fetched_at
=
Time
.
now
.
to_i
current_fetched_at
=
Time
.
now
.
to_i
...
@@ -22,8 +22,10 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -22,8 +22,10 @@ class Projects::NotesController < Projects::ApplicationController
def
create
def
create
@note
=
Notes
::
CreateService
.
new
(
project
,
current_user
,
note_params
).
execute
@note
=
Notes
::
CreateService
.
new
(
project
,
current_user
,
note_params
).
execute
@note
=
note
.
is_a?
(
AwardEmoji
)
?
@note
.
to_note_json
:
note_json
(
@note
)
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
json
{
render
json:
note_json
(
@note
)
}
format
.
json
{
render
json:
@note
}
format
.
html
{
redirect_back_or_default
}
format
.
html
{
redirect_back_or_default
}
end
end
end
end
...
@@ -56,35 +58,12 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -56,35 +58,12 @@ class Projects::NotesController < Projects::ApplicationController
end
end
end
end
def
award_toggle
noteable
=
if
note_params
[
:noteable_type
]
==
"issue"
project
.
issues
.
find
(
note_params
[
:noteable_id
])
else
project
.
merge_requests
.
find
(
note_params
[
:noteable_id
])
end
data
=
{
author:
current_user
,
is_award:
true
,
note:
note_params
[
:note
].
delete
(
":"
)
}
note
=
noteable
.
notes
.
find_by
(
data
)
if
note
note
.
destroy
else
Notes
::
CreateService
.
new
(
project
,
current_user
,
note_params
).
execute
end
render
json:
{
ok:
true
}
end
private
private
def
note
def
note
@note
||=
@project
.
notes
.
find
(
params
[
:id
])
@note
||=
@project
.
notes
.
find
(
params
[
:id
])
end
end
alias_method
:awardable
,
:note
def
note_to_html
(
note
)
def
note_to_html
(
note
)
render_to_string
(
render_to_string
(
...
@@ -137,7 +116,7 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -137,7 +116,7 @@ class Projects::NotesController < Projects::ApplicationController
id:
note
.
id
,
id:
note
.
id
,
discussion_id:
note
.
discussion_id
,
discussion_id:
note
.
discussion_id
,
html:
note_to_html
(
note
),
html:
note_to_html
(
note
),
award:
note
.
is_award
,
award:
false
,
note:
note
.
note
,
note:
note
.
note
,
discussion_html:
note_to_discussion_html
(
note
),
discussion_html:
note_to_discussion_html
(
note
),
discussion_with_diff_html:
note_to_discussion_with_diff_html
(
note
)
discussion_with_diff_html:
note_to_discussion_with_diff_html
(
note
)
...
@@ -145,7 +124,7 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -145,7 +124,7 @@ class Projects::NotesController < Projects::ApplicationController
else
else
{
{
valid:
false
,
valid:
false
,
award:
note
.
is_award
,
award:
false
,
errors:
note
.
errors
errors:
note
.
errors
}
}
end
end
...
...
app/controllers/projects_controller.rb
View file @
3bdc57f0
...
@@ -145,7 +145,7 @@ class ProjectsController < Projects::ApplicationController
...
@@ -145,7 +145,7 @@ class ProjectsController < Projects::ApplicationController
participants
=
::
Projects
::
ParticipantsService
.
new
(
@project
,
current_user
).
execute
(
note_type
,
note_id
)
participants
=
::
Projects
::
ParticipantsService
.
new
(
@project
,
current_user
).
execute
(
note_type
,
note_id
)
@suggestions
=
{
@suggestions
=
{
emojis:
AwardEmoji
.
urls
,
emojis:
Gitlab
::
AwardEmoji
.
urls
,
issues:
autocomplete
.
issues
,
issues:
autocomplete
.
issues
,
mergerequests:
autocomplete
.
merge_requests
,
mergerequests:
autocomplete
.
merge_requests
,
members:
participants
members:
participants
...
...
app/helpers/issues_helper.rb
View file @
3bdc57f0
...
@@ -144,16 +144,17 @@ module IssuesHelper
...
@@ -144,16 +144,17 @@ module IssuesHelper
end
end
end
end
def
emoji_author_list
(
notes
,
current_user
)
def
award_user_list
(
awards
,
current_user
)
list
=
notes
.
map
do
|
note
|
list
=
note
.
author
==
current_user
?
"me"
:
note
.
author
.
name
awards
.
map
do
|
award
|
end
award
.
user
==
current_user
?
"me"
:
award
.
user
.
name
end
list
.
join
(
", "
)
list
.
join
(
", "
)
end
end
def
note_active_class
(
note
s
,
current_user
)
def
award_active_class
(
award
s
,
current_user
)
if
current_user
&&
notes
.
pluck
(
:author_id
).
include?
(
current_user
.
id
)
if
current_user
&&
awards
.
find
{
|
a
|
a
.
user_id
==
current_user
.
id
}
"active"
"active"
else
else
""
""
...
...
app/models/award_emoji.rb
0 → 100644
View file @
3bdc57f0
class
AwardEmoji
<
ActiveRecord
::
Base
DOWNVOTE_NAME
=
"thumbsdown"
.
freeze
UPVOTE_NAME
=
"thumbsup"
.
freeze
include
Participable
belongs_to
:awardable
,
polymorphic:
true
belongs_to
:user
validates
:awardable
,
:user
,
presence:
true
validates
:name
,
presence:
true
,
inclusion:
{
in:
Emoji
.
emojis_names
}
validates
:name
,
uniqueness:
{
scope:
[
:user
,
:awardable_type
,
:awardable_id
]
}
participant
:user
scope
:downvotes
,
->
{
where
(
name:
DOWNVOTE_NAME
)
}
scope
:upvotes
,
->
{
where
(
name:
UPVOTE_NAME
)
}
def
downvote?
self
.
name
==
DOWNVOTE_NAME
end
def
upvote?
self
.
name
==
UPVOTE_NAME
end
def
to_note_json
{
valid:
valid?
,
award:
true
,
id:
id
,
name:
name
}
end
end
app/models/concerns/awardable.rb
0 → 100644
View file @
3bdc57f0
module
Awardable
extend
ActiveSupport
::
Concern
included
do
has_many
:award_emoji
,
as: :awardable
,
dependent: :destroy
if
self
<
Participable
participant
:award_emoji
end
end
module
ClassMethods
def
order_upvotes_desc
order_votes_desc
(
AwardEmoji
::
UPVOTE_NAME
)
end
def
order_downvotes_desc
order_votes_desc
(
AwardEmoji
::
DOWNVOTE_NAME
)
end
def
order_votes_desc
(
emoji_name
)
awardable_table
=
self
.
arel_table
awards_table
=
AwardEmoji
.
arel_table
join_clause
=
awardable_table
.
join
(
awards_table
,
Arel
::
Nodes
::
OuterJoin
).
on
(
awards_table
[
:awardable_id
].
eq
(
awardable_table
[
:id
]).
and
(
awards_table
[
:awardable_type
].
eq
(
self
.
name
).
and
(
awards_table
[
:name
].
eq
(
emoji_name
)
)
)
).
join_sources
joins
(
join_clause
).
group
(
awardable_table
[
:id
]).
reorder
(
"COUNT(award_emoji.id) DESC"
)
end
end
def
grouped_awards
(
with_thumbs
=
true
)
awards
=
award_emoji
.
group_by
(
&
:name
)
if
with_thumbs
awards
[
AwardEmoji
::
UPVOTE_NAME
]
||=
AwardEmoji
.
none
awards
[
AwardEmoji
::
DOWNVOTE_NAME
]
||=
AwardEmoji
.
none
end
awards
end
def
downvotes
award_emoji
.
where
(
name:
AwardEmoji
::
DOWNVOTE_NAME
).
count
end
def
upvotes
award_emoji
.
where
(
name:
AwardEmoji
::
UPVOTE_NAME
).
count
end
def
emoji_awardable?
true
end
def
awarded_emoji?
(
emoji_name
,
current_user
)
award_emoji
.
where
(
name:
emoji_name
,
user:
current_user
).
exists?
end
def
create_award_emoji
(
name
,
current_user
)
return
unless
emoji_awardable?
award_emoji
.
create
(
name:
name
,
user:
current_user
)
end
def
remove_award_emoji
(
name
,
current_user
)
award_emoji
.
where
(
name:
name
,
user:
current_user
).
destroy_all
end
def
toggle_award_emoji
(
emoji_name
,
current_user
)
if
awarded_emoji?
(
emoji_name
,
current_user
)
remove_award_emoji
(
emoji_name
,
current_user
)
else
create_award_emoji
(
emoji_name
,
current_user
)
end
end
end
app/models/concerns/issuable.rb
View file @
3bdc57f0
...
@@ -10,6 +10,7 @@ module Issuable
...
@@ -10,6 +10,7 @@ module Issuable
include
Mentionable
include
Mentionable
include
Subscribable
include
Subscribable
include
StripAttribute
include
StripAttribute
include
Awardable
included
do
included
do
belongs_to
:author
,
class_name:
"User"
belongs_to
:author
,
class_name:
"User"
...
@@ -99,29 +100,6 @@ module Issuable
...
@@ -99,29 +100,6 @@ module Issuable
order_by
(
method
)
order_by
(
method
)
end
end
end
end
def
order_downvotes_desc
order_votes_desc
(
'thumbsdown'
)
end
def
order_upvotes_desc
order_votes_desc
(
'thumbsup'
)
end
def
order_votes_desc
(
award_emoji_name
)
issuable_table
=
self
.
arel_table
note_table
=
Note
.
arel_table
join_clause
=
issuable_table
.
join
(
note_table
,
Arel
::
Nodes
::
OuterJoin
).
on
(
note_table
[
:noteable_id
].
eq
(
issuable_table
[
:id
]).
and
(
note_table
[
:noteable_type
].
eq
(
self
.
name
).
and
(
note_table
[
:is_award
].
eq
(
true
).
and
(
note_table
[
:note
].
eq
(
award_emoji_name
))
)
)
).
join_sources
joins
(
join_clause
).
group
(
issuable_table
[
:id
]).
reorder
(
"COUNT(notes.id) DESC"
)
end
end
end
def
today?
def
today?
...
@@ -144,14 +122,6 @@ module Issuable
...
@@ -144,14 +122,6 @@ module Issuable
opened?
||
reopened?
opened?
||
reopened?
end
end
def
downvotes
notes
.
awards
.
where
(
note:
"thumbsdown"
).
count
end
def
upvotes
notes
.
awards
.
where
(
note:
"thumbsup"
).
count
end
def
subscribed_without_subscriptions?
(
user
)
def
subscribed_without_subscriptions?
(
user
)
participants
(
user
).
include?
(
user
)
participants
(
user
).
include?
(
user
)
end
end
...
...
app/models/merge_request.rb
View file @
3bdc57f0
...
@@ -36,6 +36,7 @@ class MergeRequest < ActiveRecord::Base
...
@@ -36,6 +36,7 @@ class MergeRequest < ActiveRecord::Base
include
Referable
include
Referable
include
Sortable
include
Sortable
include
Taskable
include
Taskable
include
Awardable
belongs_to
:target_project
,
foreign_key: :target_project_id
,
class_name:
"Project"
belongs_to
:target_project
,
foreign_key: :target_project_id
,
class_name:
"Project"
belongs_to
:source_project
,
foreign_key: :source_project_id
,
class_name:
"Project"
belongs_to
:source_project
,
foreign_key: :source_project_id
,
class_name:
"Project"
...
...
app/models/note.rb
View file @
3bdc57f0
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
# system :boolean default(FALSE), not null
# system :boolean default(FALSE), not null
# st_diff :text
# st_diff :text
# updated_by_id :integer
# updated_by_id :integer
# is_award :boolean default(FALSE), not null
#
#
require
'carrierwave/orm/activerecord'
require
'carrierwave/orm/activerecord'
...
@@ -43,12 +42,9 @@ class Note < ActiveRecord::Base
...
@@ -43,12 +42,9 @@ class Note < ActiveRecord::Base
delegate
:name
,
to: :project
,
prefix:
true
delegate
:name
,
to: :project
,
prefix:
true
delegate
:name
,
:email
,
to: :author
,
prefix:
true
delegate
:name
,
:email
,
to: :author
,
prefix:
true
before_validation
:set_award!
before_validation
:clear_blank_line_code!
before_validation
:clear_blank_line_code!
validates
:note
,
:project
,
presence:
true
validates
:note
,
:project
,
presence:
true
validates
:note
,
uniqueness:
{
scope:
[
:author
,
:noteable_type
,
:noteable_id
]
},
if:
->
(
n
)
{
n
.
is_award
}
validates
:note
,
inclusion:
{
in:
Emoji
.
emojis_names
},
if:
->
(
n
)
{
n
.
is_award
}
validates
:line_code
,
line_code:
true
,
allow_blank:
true
validates
:line_code
,
line_code:
true
,
allow_blank:
true
# Attachments are deprecated and are handled by Markdown uploader
# Attachments are deprecated and are handled by Markdown uploader
validates
:attachment
,
file_size:
{
maximum: :max_attachment_size
}
validates
:attachment
,
file_size:
{
maximum: :max_attachment_size
}
...
@@ -60,8 +56,6 @@ class Note < ActiveRecord::Base
...
@@ -60,8 +56,6 @@ class Note < ActiveRecord::Base
mount_uploader
:attachment
,
AttachmentUploader
mount_uploader
:attachment
,
AttachmentUploader
# Scopes
# Scopes
scope
:awards
,
->
{
where
(
is_award:
true
)
}
scope
:nonawards
,
->
{
where
(
is_award:
false
)
}
scope
:for_commit_id
,
->
(
commit_id
)
{
where
(
noteable_type:
"Commit"
,
commit_id:
commit_id
)
}
scope
:for_commit_id
,
->
(
commit_id
)
{
where
(
noteable_type:
"Commit"
,
commit_id:
commit_id
)
}
scope
:inline
,
->
{
where
(
"line_code IS NOT NULL"
)
}
scope
:inline
,
->
{
where
(
"line_code IS NOT NULL"
)
}
scope
:not_inline
,
->
{
where
(
line_code:
nil
)
}
scope
:not_inline
,
->
{
where
(
line_code:
nil
)
}
...
@@ -119,19 +113,6 @@ class Note < ActiveRecord::Base
...
@@ -119,19 +113,6 @@ class Note < ActiveRecord::Base
where
(
table
[
:note
].
matches
(
pattern
))
where
(
table
[
:note
].
matches
(
pattern
))
end
end
def
grouped_awards
notes
=
{}
awards
.
select
(
:note
).
distinct
.
map
do
|
note
|
notes
[
note
.
note
]
=
where
(
note:
note
.
note
)
end
notes
[
"thumbsup"
]
||=
Note
.
none
notes
[
"thumbsdown"
]
||=
Note
.
none
notes
end
end
end
def
cross_reference?
def
cross_reference?
...
@@ -347,37 +328,25 @@ class Note < ActiveRecord::Base
...
@@ -347,37 +328,25 @@ class Note < ActiveRecord::Base
Event
.
reset_event_cache_for
(
self
)
Event
.
reset_event_cache_for
(
self
)
end
end
def
downvote?
def
system?
is_award
&&
note
==
"thumbsdown"
read_attribute
(
:system
)
end
def
upvote?
is_award
&&
note
==
"thumbsup"
end
end
def
editable?
def
editable?
!
system
?
&&
!
is_award
!
system
?
end
end
def
cross_reference_not_visible_for?
(
user
)
def
cross_reference_not_visible_for?
(
user
)
cross_reference?
&&
referenced_mentionables
(
user
).
empty?
cross_reference?
&&
referenced_mentionables
(
user
).
empty?
end
end
# Checks if note is an award added as a comment
def
award_emoji?
#
award_emoji_supported?
&&
contains_emoji_only?
# If note is an award, this method sets is_award to true
# and changes content of the note to award name.
#
# Method is executed as a before_validation callback.
#
def
set_award!
return
unless
awards_supported?
&&
contains_emoji_only?
self
.
is_award
=
true
self
.
note
=
award_emoji_name
end
end
private
def
create_award_emoji
self
.
noteable
.
award_emoji
(
award_emoji_name
,
author
)
end
def
clear_blank_line_code!
def
clear_blank_line_code!
self
.
line_code
=
nil
if
self
.
line_code
.
blank?
self
.
line_code
=
nil
if
self
.
line_code
.
blank?
...
@@ -389,8 +358,8 @@ class Note < ActiveRecord::Base
...
@@ -389,8 +358,8 @@ class Note < ActiveRecord::Base
diffs
.
find
{
|
d
|
d
.
new_path
==
self
.
diff
.
new_path
}
diffs
.
find
{
|
d
|
d
.
new_path
==
self
.
diff
.
new_path
}
end
end
def
award
s
_supported?
def
award
_emoji
_supported?
(
for_issue?
||
for_merge_request?
)
&&
!
for_diff_line?
noteable
.
is_a?
(
Awardable
)
&&
!
for_diff_line?
end
end
def
contains_emoji_only?
def
contains_emoji_only?
...
@@ -399,6 +368,6 @@ class Note < ActiveRecord::Base
...
@@ -399,6 +368,6 @@ class Note < ActiveRecord::Base
def
award_emoji_name
def
award_emoji_name
original_name
=
note
.
match
(
Banzai
::
Filter
::
EmojiFilter
.
emoji_pattern
)[
1
]
original_name
=
note
.
match
(
Banzai
::
Filter
::
EmojiFilter
.
emoji_pattern
)[
1
]
AwardEmoji
.
normilize_emoji_name
(
original_name
)
Gitlab
::
AwardEmoji
.
normilize_emoji_name
(
original_name
)
end
end
end
end
app/models/user.rb
View file @
3bdc57f0
...
@@ -144,6 +144,7 @@ class User < ActiveRecord::Base
...
@@ -144,6 +144,7 @@ class User < ActiveRecord::Base
has_many
:builds
,
dependent: :nullify
,
class_name:
'Ci::Build'
has_many
:builds
,
dependent: :nullify
,
class_name:
'Ci::Build'
has_many
:todos
,
dependent: :destroy
has_many
:todos
,
dependent: :destroy
has_many
:notification_settings
,
dependent: :destroy
has_many
:notification_settings
,
dependent: :destroy
has_many
:award_emoji
,
as: :awardable
,
dependent: :destroy
#
#
# Validations
# Validations
...
...
app/services/notes/create_service.rb
View file @
3bdc57f0
...
@@ -5,6 +5,11 @@ module Notes
...
@@ -5,6 +5,11 @@ module Notes
note
.
author
=
current_user
note
.
author
=
current_user
note
.
system
=
false
note
.
system
=
false
if
note
.
award_emoji?
return
ToggleAwardEmojiService
.
new
(
project
,
current_user
,
params
).
execute
(
note
.
noteable
,
note
.
note
)
end
if
note
.
save
if
note
.
save
# Finish the harder work in the background
# Finish the harder work in the background
NewNoteWorker
.
perform_in
(
2
.
seconds
,
note
.
id
,
params
)
NewNoteWorker
.
perform_in
(
2
.
seconds
,
note
.
id
,
params
)
...
...
app/services/notes/post_process_service.rb
View file @
3bdc57f0
...
@@ -8,7 +8,7 @@ module Notes
...
@@ -8,7 +8,7 @@ module Notes
def
execute
def
execute
# Skip system notes, like status changes and cross-references and awards
# Skip system notes, like status changes and cross-references and awards
unless
@note
.
system
||
@note
.
is_award
unless
@note
.
system
EventCreateService
.
new
.
leave_note
(
@note
,
@note
.
author
)
EventCreateService
.
new
.
leave_note
(
@note
,
@note
.
author
)
@note
.
create_cross_references!
@note
.
create_cross_references!
execute_note_hooks
execute_note_hooks
...
...
app/services/notification_service.rb
View file @
3bdc57f0
...
@@ -131,7 +131,6 @@ class NotificationService
...
@@ -131,7 +131,6 @@ class NotificationService
# ignore gitlab service messages
# ignore gitlab service messages
return
true
if
note
.
note
.
start_with?
(
'Status changed to closed'
)
return
true
if
note
.
note
.
start_with?
(
'Status changed to closed'
)
return
true
if
note
.
cross_reference?
&&
note
.
system
==
true
return
true
if
note
.
cross_reference?
&&
note
.
system
==
true
return
true
if
note
.
is_award
target
=
note
.
noteable
target
=
note
.
noteable
...
...
app/services/todo_service.rb
View file @
3bdc57f0
...
@@ -98,6 +98,14 @@ class TodoService
...
@@ -98,6 +98,14 @@ class TodoService
handle_note
(
note
,
current_user
)
handle_note
(
note
,
current_user
)
end
end
# When an emoji is awarded we should:
#
# * mark all pending todos related to the awardable for the current user as done
#
def
new_award_emoji
(
awardable
,
current_user
)
mark_pending_todos_as_done
(
awardable
,
current_user
)
end
# When marking pending todos as done we should:
# When marking pending todos as done we should:
#
#
# * mark all pending todos related to the target for the current user as done
# * mark all pending todos related to the target for the current user as done
...
...
app/services/toggle_award_emoji_service.rb
0 → 100644
View file @
3bdc57f0
require_relative
'base_service'
class
ToggleAwardEmojiService
<
BaseService
# For an award emoji being posted we should:
# - Mark the TODO as done for this issuable (skip on snippets)
# - Save the award emoji
def
execute
(
awardable
,
emoji
)
todo_service
.
new_award_emoji
(
awardable
,
current_user
)
# Needed if its posted as a note containing only :+1:
emoji
=
award_emoji_name
(
emoji
)
if
emoji
.
start_with?
':'
awardable
.
toggle_award_emoji
(
emoji
,
current_user
)
end
private
def
award_emoji_name
(
emoji
)
original_name
=
emoji
.
match
(
Banzai
::
Filter
::
EmojiFilter
.
emoji_pattern
)[
1
]
Gitlab
::
AwardEmoji
.
normalize_emoji_name
(
original_name
)
end
end
app/views/award_emoji/_awards_block.html.haml
0 → 100644
View file @
3bdc57f0
-
grouped_awards
=
awardable
.
grouped_awards
(
inline
)
.awards.js-awards-block
{
class:
(
"hidden"
if
!
inline
&&
grouped_emojis
.
size
==
0
),
data:
{
award_url:
url_for
([
:toggle_award_emoji
,
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
awardable
])
}
}
-
awards_sort
(
grouped_awards
).
each
do
|
emoji
,
awards
|
%button
.btn.award-control.js-emoji-btn.has-tooltip
{
type:
"button"
,
class:
(
award_active_class
(
awards
,
current_user
)),
title:
award_user_list
(
awards
,
current_user
),
data:
{
placement:
"bottom"
}
}
=
emoji_icon
(
emoji
)
%span
.award-control-text.js-counter
=
awards
.
count
-
if
current_user
.award-menu-holder.js-award-holder
%button
.btn.award-control.js-add-award
{
type:
"button"
,
data:
{
award_menu_url:
emojis_path
}
}
=
icon
(
'smile-o'
,
{
class:
"award-control-icon award-control-icon-normal"
})
=
icon
(
'spinner spin'
,
{
class:
"award-control-icon award-control-icon-loading"
})
%span
.award-control-text
Add
app/views/emojis/index.html.haml
View file @
3bdc57f0
.emoji-menu
.emoji-menu
.emoji-menu-content
.emoji-menu-content
=
text_field_tag
:emoji_search
,
""
,
class:
"emoji-search search-input form-control"
=
text_field_tag
:emoji_search
,
""
,
class:
"emoji-search search-input form-control"
-
AwardEmoji
.
emoji_by_category
.
each
do
|
category
,
emojis
|
-
Gitlab
::
AwardEmoji
.
emoji_by_category
.
each
do
|
category
,
emojis
|
%h5
.emoji-menu-title
%h5
.emoji-menu-title
=
AwardEmoji
::
CATEGORIES
[
category
]
=
Gitlab
::
AwardEmoji
::
CATEGORIES
[
category
]
%ul
.clearfix.emoji-menu-list
%ul
.clearfix.emoji-menu-list
-
emojis
.
each
do
|
emoji
|
-
emojis
.
each
do
|
emoji
|
%li
.pull-left.text-center.emoji-menu-list-item
%li
.pull-left.text-center.emoji-menu-list-item
...
...
app/views/projects/issues/_issue.html.haml
View file @
3bdc57f0
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
=
icon
(
'thumbs-down'
)
=
icon
(
'thumbs-down'
)
=
downvotes
=
downvotes
-
note_count
=
issue
.
notes
.
user
.
nonawards
.
count
-
note_count
=
issue
.
notes
.
user
.
count
-
if
note_count
>
0
-
if
note_count
>
0
%li
%li
=
link_to
issue_path
(
issue
)
+
"#notes"
do
=
link_to
issue_path
(
issue
)
+
"#notes"
do
...
...
app/views/projects/issues/show.html.haml
View file @
3bdc57f0
...
@@ -72,7 +72,7 @@
...
@@ -72,7 +72,7 @@
.content-block.content-block-small
.content-block.content-block-small
=
render
'new_branch'
=
render
'new_branch'
=
render
'
votes/votes_block'
,
votable:
@iss
ue
=
render
'
award_emoji/awards_block'
,
awardable:
@issue
,
inline:
tr
ue
.row
.row
%section
.col-md-12
%section
.col-md-12
...
...
app/views/projects/merge_requests/_merge_request.html.haml
View file @
3bdc57f0
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
=
icon
(
'thumbs-down'
)
=
icon
(
'thumbs-down'
)
=
downvotes
=
downvotes
-
note_count
=
merge_request
.
mr_and_commit_notes
.
user
.
nonawards
.
count
-
note_count
=
merge_request
.
mr_and_commit_notes
.
user
.
count
-
if
note_count
>
0
-
if
note_count
>
0
%li
%li
=
link_to
merge_request_path
(
merge_request
)
+
"#notes"
do
=
link_to
merge_request_path
(
merge_request
)
+
"#notes"
do
...
...
app/views/projects/merge_requests/_show.html.haml
View file @
3bdc57f0
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
%li
.notes-tab
%li
.notes-tab
=
link_to
namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
data:
{
target:
'div#notes'
,
action:
'notes'
,
toggle:
'tab'
}
do
=
link_to
namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
data:
{
target:
'div#notes'
,
action:
'notes'
,
toggle:
'tab'
}
do
Discussion
Discussion
%span
.badge
=
@merge_request
.
mr_and_commit_notes
.
user
.
nonawards
.
count
%span
.badge
=
@merge_request
.
mr_and_commit_notes
.
user
.
count
%li
.commits-tab
%li
.commits-tab
=
link_to
commits_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
data:
{
target:
'div#commits'
,
action:
'commits'
,
toggle:
'tab'
}
do
=
link_to
commits_namespace_project_merge_request_path
(
@project
.
namespace
,
@project
,
@merge_request
),
data:
{
target:
'div#commits'
,
action:
'commits'
,
toggle:
'tab'
}
do
Commits
Commits
...
@@ -68,7 +68,7 @@
...
@@ -68,7 +68,7 @@
.tab-content
.tab-content
#notes
.notes.tab-pane.voting_notes
#notes
.notes.tab-pane.voting_notes
.content-block.content-block-small.oneline-block
.content-block.content-block-small.oneline-block
=
render
'
votes/votes_block'
,
votable:
@merge_request
=
render
'
award_emoji/awards_block'
,
awardable:
@merge_request
,
inline:
true
.row
.row
%section
.col-md-12
%section
.col-md-12
...
...
app/views/votes/_votes_block.html.haml
View file @
3bdc57f0
.awards.votes-block
.awards.votes-block
{
data:
{
toggle_url:
url_for
([
:toggle_award_emoji
,
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
awardable
])
}}
-
awards_sort
(
votable
.
notes
.
awards
.
grouped_awards
).
each
do
|
emoji
,
note
s
|
-
awards_sort
(
awardable
.
grouped_awards
).
each
do
|
emoji
,
award
s
|
%button
.btn.award-control.js-emoji-btn.has-tooltip
{
class:
(
note_active_class
(
notes
,
current_user
)),
data:
{
placement:
"top"
,
original_title:
emoji_author_list
(
note
s
,
current_user
)}}
%button
.btn.award-control.js-emoji-btn.has-tooltip
{
class:
(
note_active_class
(
awards
,
current_user
)),
data:
{
placement:
"top"
,
original_title:
emoji_author_list
(
award
s
,
current_user
)}}
=
emoji_icon
(
emoji
,
sprite:
false
)
=
emoji_icon
(
emoji
,
sprite:
false
)
%span
.award-control-text.js-counter
%span
.award-control-text.js-counter
=
note
s
.
count
=
award
s
.
count
-
if
current_user
-
if
current_user
%div
.award-menu-holder.js-award-holder
%div
.award-menu-holder.js-award-holder
...
...
config/initializers/inflections.rb
View file @
3bdc57f0
...
@@ -8,3 +8,7 @@
...
@@ -8,3 +8,7 @@
# inflect.irregular 'person', 'people'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# inflect.uncountable %w( fish sheep )
# end
# end
#
ActiveSupport
::
Inflector
.
inflections
do
|
inflect
|
inflect
.
uncountable
%w(award_emoji)
end
config/routes.rb
View file @
3bdc57f0
...
@@ -639,6 +639,7 @@ Rails.application.routes.draw do
...
@@ -639,6 +639,7 @@ Rails.application.routes.draw do
post
:cancel_merge_when_build_succeeds
post
:cancel_merge_when_build_succeeds
get
:ci_status
get
:ci_status
post
:toggle_subscription
post
:toggle_subscription
post
:toggle_award_emoji
post
:remove_wip
post
:remove_wip
end
end
...
@@ -703,6 +704,7 @@ Rails.application.routes.draw do
...
@@ -703,6 +704,7 @@ Rails.application.routes.draw do
resources
:issues
,
constraints:
{
id:
/\d+/
}
do
resources
:issues
,
constraints:
{
id:
/\d+/
}
do
member
do
member
do
post
:toggle_subscription
post
:toggle_subscription
post
:toggle_award_emoji
get
:referenced_merge_requests
get
:referenced_merge_requests
get
:related_branches
get
:related_branches
end
end
...
@@ -731,10 +733,7 @@ Rails.application.routes.draw do
...
@@ -731,10 +733,7 @@ Rails.application.routes.draw do
resources
:notes
,
only:
[
:index
,
:create
,
:destroy
,
:update
],
constraints:
{
id:
/\d+/
}
do
resources
:notes
,
only:
[
:index
,
:create
,
:destroy
,
:update
],
constraints:
{
id:
/\d+/
}
do
member
do
member
do
delete
:delete_attachment
delete
:delete_attachment
end
post
:toggle_award_emoji
collection
do
post
:award_toggle
end
end
end
end
...
...
db/migrate/20160416180807_add_award_emoji.rb
0 → 100644
View file @
3bdc57f0
class
AddAwardEmoji
<
ActiveRecord
::
Migration
def
change
create_table
:award_emoji
do
|
t
|
t
.
string
:name
t
.
references
:user
t
.
references
:awardable
,
polymorphic:
true
t
.
timestamps
end
add_index
:award_emoji
,
:user_id
add_index
:award_emoji
,
:awardable_type
add_index
:award_emoji
,
:awardable_id
end
end
db/migrate/20160416182152_convert_award_note_to_emoji_award.rb
0 → 100644
View file @
3bdc57f0
class
ConvertAwardNoteToEmojiAward
<
ActiveRecord
::
Migration
def
change
def
up
execute
"INSERT INTO award_emoji (awardable_type, awardable_id, user_id, name, created_at, updated_at) (SELECT noteable_type, noteable_id, author_id, note, created_at, updated_at FROM notes WHERE is_award = true)"
end
def
down
execute
<<-
SQL
INSERT INTO notes (noteable_type, noteable_id, author_id, note, created_at, updated_at, is_award)
(SELECT awardable_type, awardable_id, user_id, name, created_at, updated_at, TRUE
FROM award_emoji
WHERE awardable_type IN ('Issue', 'MergeRequest')
)
SQL
end
end
end
db/migrate/20160416190505_remove_note_is_award.rb
0 → 100644
View file @
3bdc57f0
class
RemoveNoteIsAward
<
ActiveRecord
::
Migration
def
change
remove_column
:notes
,
:is_award
,
:boolean
end
end
db/schema.rb
View file @
3bdc57f0
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
2016041
2140240
)
do
ActiveRecord
::
Schema
.
define
(
version:
2016041
6190505
)
do
# These are extensions that must be enabled in order to support this database
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
enable_extension
"plpgsql"
...
@@ -94,6 +94,19 @@ ActiveRecord::Schema.define(version: 20160412140240) do
...
@@ -94,6 +94,19 @@ ActiveRecord::Schema.define(version: 20160412140240) do
add_index
"audit_events"
,
[
"entity_id"
,
"entity_type"
],
name:
"index_audit_events_on_entity_id_and_entity_type"
,
using: :btree
add_index
"audit_events"
,
[
"entity_id"
,
"entity_type"
],
name:
"index_audit_events_on_entity_id_and_entity_type"
,
using: :btree
add_index
"audit_events"
,
[
"type"
],
name:
"index_audit_events_on_type"
,
using: :btree
add_index
"audit_events"
,
[
"type"
],
name:
"index_audit_events_on_type"
,
using: :btree
create_table
"award_emoji"
,
force: :cascade
do
|
t
|
t
.
string
"name"
t
.
integer
"user_id"
t
.
integer
"awardable_id"
t
.
string
"awardable_type"
t
.
datetime
"created_at"
t
.
datetime
"updated_at"
end
add_index
"award_emoji"
,
[
"awardable_id"
],
name:
"index_award_emoji_on_awardable_id"
,
using: :btree
add_index
"award_emoji"
,
[
"awardable_type"
],
name:
"index_award_emoji_on_awardable_type"
,
using: :btree
add_index
"award_emoji"
,
[
"user_id"
],
name:
"index_award_emoji_on_user_id"
,
using: :btree
create_table
"broadcast_messages"
,
force: :cascade
do
|
t
|
create_table
"broadcast_messages"
,
force: :cascade
do
|
t
|
t
.
text
"message"
,
null:
false
t
.
text
"message"
,
null:
false
t
.
datetime
"starts_at"
t
.
datetime
"starts_at"
...
@@ -622,14 +635,12 @@ ActiveRecord::Schema.define(version: 20160412140240) do
...
@@ -622,14 +635,12 @@ ActiveRecord::Schema.define(version: 20160412140240) do
t
.
boolean
"system"
,
default:
false
,
null:
false
t
.
boolean
"system"
,
default:
false
,
null:
false
t
.
text
"st_diff"
t
.
text
"st_diff"
t
.
integer
"updated_by_id"
t
.
integer
"updated_by_id"
t
.
boolean
"is_award"
,
default:
false
,
null:
false
end
end
add_index
"notes"
,
[
"author_id"
],
name:
"index_notes_on_author_id"
,
using: :btree
add_index
"notes"
,
[
"author_id"
],
name:
"index_notes_on_author_id"
,
using: :btree
add_index
"notes"
,
[
"commit_id"
],
name:
"index_notes_on_commit_id"
,
using: :btree
add_index
"notes"
,
[
"commit_id"
],
name:
"index_notes_on_commit_id"
,
using: :btree
add_index
"notes"
,
[
"created_at"
,
"id"
],
name:
"index_notes_on_created_at_and_id"
,
using: :btree
add_index
"notes"
,
[
"created_at"
,
"id"
],
name:
"index_notes_on_created_at_and_id"
,
using: :btree
add_index
"notes"
,
[
"created_at"
],
name:
"index_notes_on_created_at"
,
using: :btree
add_index
"notes"
,
[
"created_at"
],
name:
"index_notes_on_created_at"
,
using: :btree
add_index
"notes"
,
[
"is_award"
],
name:
"index_notes_on_is_award"
,
using: :btree
add_index
"notes"
,
[
"line_code"
],
name:
"index_notes_on_line_code"
,
using: :btree
add_index
"notes"
,
[
"line_code"
],
name:
"index_notes_on_line_code"
,
using: :btree
add_index
"notes"
,
[
"note"
],
name:
"index_notes_on_note_trigram"
,
using: :gin
,
opclasses:
{
"note"
=>
"gin_trgm_ops"
}
add_index
"notes"
,
[
"note"
],
name:
"index_notes_on_note_trigram"
,
using: :gin
,
opclasses:
{
"note"
=>
"gin_trgm_ops"
}
add_index
"notes"
,
[
"noteable_id"
,
"noteable_type"
],
name:
"index_notes_on_noteable_id_and_noteable_type"
,
using: :btree
add_index
"notes"
,
[
"noteable_id"
,
"noteable_type"
],
name:
"index_notes_on_noteable_id_and_noteable_type"
,
using: :btree
...
@@ -716,37 +727,37 @@ ActiveRecord::Schema.define(version: 20160412140240) do
...
@@ -716,37 +727,37 @@ ActiveRecord::Schema.define(version: 20160412140240) do
t
.
datetime
"created_at"
t
.
datetime
"created_at"
t
.
datetime
"updated_at"
t
.
datetime
"updated_at"
t
.
integer
"creator_id"
t
.
integer
"creator_id"
t
.
boolean
"issues_enabled"
,
default:
true
,
null:
false
t
.
boolean
"issues_enabled"
,
default:
true
,
null:
false
t
.
boolean
"wall_enabled"
,
default:
true
,
null:
false
t
.
boolean
"wall_enabled"
,
default:
true
,
null:
false
t
.
boolean
"merge_requests_enabled"
,
default:
true
,
null:
false
t
.
boolean
"merge_requests_enabled"
,
default:
true
,
null:
false
t
.
boolean
"wiki_enabled"
,
default:
true
,
null:
false
t
.
boolean
"wiki_enabled"
,
default:
true
,
null:
false
t
.
integer
"namespace_id"
t
.
integer
"namespace_id"
t
.
string
"issues_tracker"
,
default:
"gitlab"
,
null:
false
t
.
string
"issues_tracker"
,
default:
"gitlab"
,
null:
false
t
.
string
"issues_tracker_id"
t
.
string
"issues_tracker_id"
t
.
boolean
"snippets_enabled"
,
default:
true
,
null:
false
t
.
boolean
"snippets_enabled"
,
default:
true
,
null:
false
t
.
datetime
"last_activity_at"
t
.
datetime
"last_activity_at"
t
.
string
"import_url"
t
.
string
"import_url"
t
.
integer
"visibility_level"
,
default:
0
,
null:
false
t
.
integer
"visibility_level"
,
default:
0
,
null:
false
t
.
boolean
"archived"
,
default:
false
,
null:
false
t
.
boolean
"archived"
,
default:
false
,
null:
false
t
.
string
"avatar"
t
.
string
"avatar"
t
.
string
"import_status"
t
.
string
"import_status"
t
.
float
"repository_size"
,
default:
0.0
t
.
float
"repository_size"
,
default:
0.0
t
.
integer
"star_count"
,
default:
0
,
null:
false
t
.
integer
"star_count"
,
default:
0
,
null:
false
t
.
string
"import_type"
t
.
string
"import_type"
t
.
string
"import_source"
t
.
string
"import_source"
t
.
integer
"commit_count"
,
default:
0
t
.
integer
"commit_count"
,
default:
0
t
.
text
"import_error"
t
.
text
"import_error"
t
.
integer
"ci_id"
t
.
integer
"ci_id"
t
.
boolean
"builds_enabled"
,
default:
true
,
null:
false
t
.
boolean
"builds_enabled"
,
default:
true
,
null:
false
t
.
boolean
"shared_runners_enabled"
,
default:
true
,
null:
false
t
.
boolean
"shared_runners_enabled"
,
default:
true
,
null:
false
t
.
string
"runners_token"
t
.
string
"runners_token"
t
.
string
"build_coverage_regex"
t
.
string
"build_coverage_regex"
t
.
boolean
"build_allow_git_fetch"
,
default:
true
,
null:
false
t
.
boolean
"build_allow_git_fetch"
,
default:
true
,
null:
false
t
.
integer
"build_timeout"
,
default:
3600
,
null:
false
t
.
integer
"build_timeout"
,
default:
3600
,
null:
false
t
.
boolean
"pending_delete"
,
default:
false
t
.
boolean
"pending_delete"
,
default:
false
t
.
boolean
"public_builds"
,
default:
true
,
null:
false
t
.
boolean
"public_builds"
,
default:
true
,
null:
false
t
.
string
"main_language"
t
.
string
"main_language"
t
.
integer
"pushes_since_gc"
,
default:
0
t
.
integer
"pushes_since_gc"
,
default:
0
t
.
boolean
"last_repository_check_failed"
t
.
boolean
"last_repository_check_failed"
t
.
datetime
"last_repository_check_at"
t
.
datetime
"last_repository_check_at"
end
end
...
...
lib/api/entities.rb
View file @
3bdc57f0
...
@@ -170,6 +170,7 @@ module API
...
@@ -170,6 +170,7 @@ module API
expose
:label_names
,
as: :labels
expose
:label_names
,
as: :labels
expose
:milestone
,
using:
Entities
::
Milestone
expose
:milestone
,
using:
Entities
::
Milestone
expose
:assignee
,
:author
,
using:
Entities
::
UserBasic
expose
:assignee
,
:author
,
using:
Entities
::
UserBasic
expose
:upvotes
,
:downvotes
expose
:subscribed
do
|
issue
,
options
|
expose
:subscribed
do
|
issue
,
options
|
issue
.
subscribed?
(
options
[
:current_user
])
issue
.
subscribed?
(
options
[
:current_user
])
...
@@ -178,7 +179,7 @@ module API
...
@@ -178,7 +179,7 @@ module API
class
MergeRequest
<
ProjectEntity
class
MergeRequest
<
ProjectEntity
expose
:target_branch
,
:source_branch
expose
:target_branch
,
:source_branch
expose
:upvotes
,
:downvotes
expose
: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_names
,
as: :labels
expose
:label_names
,
as: :labels
...
@@ -216,8 +217,8 @@ module API
...
@@ -216,8 +217,8 @@ module API
expose
:system?
,
as: :system
expose
:system?
,
as: :system
expose
:noteable_id
,
:noteable_type
expose
:noteable_id
,
:noteable_type
# upvote? and downvote? are deprecated, always return false
# upvote? and downvote? are deprecated, always return false
expose
:upvote?
,
as: :upvote
expose
(
:upvote?
)
{
|
note
|
false
}
expose
:downvote?
,
as: :downvote
expose
(
:downvote?
)
{
|
note
|
false
}
end
end
class
MRNote
<
Grape
::
Entity
class
MRNote
<
Grape
::
Entity
...
...
lib/award_emoji.rb
deleted
100644 → 0
View file @
05920a79
class
AwardEmoji
CATEGORIES
=
{
other:
"Other"
,
objects:
"Objects"
,
places:
"Places"
,
travel_places:
"Travel"
,
emoticons:
"Emoticons"
,
objects_symbols:
"Symbols"
,
nature:
"Nature"
,
celebration:
"Celebration"
,
people:
"People"
,
activity:
"Activity"
,
flags:
"Flags"
,
food_drink:
"Food"
}.
with_indifferent_access
CATEGORY_ALIASES
=
{
symbols:
"objects_symbols"
,
foods:
"food_drink"
,
travel:
"travel_places"
}.
with_indifferent_access
def
self
.
normilize_emoji_name
(
name
)
aliases
[
name
]
||
name
end
def
self
.
emoji_by_category
unless
@emoji_by_category
@emoji_by_category
=
Hash
.
new
{
|
h
,
key
|
h
[
key
]
=
[]
}
emojis
.
each
do
|
emoji_name
,
data
|
data
[
"name"
]
=
emoji_name
# Skip Fitzpatrick(tone) modifiers
next
if
data
[
"category"
]
==
"modifier"
category
=
CATEGORY_ALIASES
[
data
[
"category"
]]
||
data
[
"category"
]
@emoji_by_category
[
category
]
<<
data
end
@emoji_by_category
=
@emoji_by_category
.
sort
.
to_h
end
@emoji_by_category
end
def
self
.
emojis
@emojis
||=
begin
json_path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'index.json'
)
JSON
.
parse
(
File
.
read
(
json_path
))
end
end
def
self
.
aliases
@aliases
||=
begin
json_path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'aliases.json'
)
JSON
.
parse
(
File
.
read
(
json_path
))
end
end
# Returns an Array of Emoji names and their asset URLs.
def
self
.
urls
@urls
||=
begin
path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'digests.json'
)
prefix
=
Gitlab
::
Application
.
config
.
assets
.
prefix
digest
=
Gitlab
::
Application
.
config
.
assets
.
digest
JSON
.
parse
(
File
.
read
(
path
)).
map
do
|
hash
|
if
digest
fname
=
"
#{
hash
[
'unicode'
]
}
-
#{
hash
[
'digest'
]
}
"
else
fname
=
hash
[
'unicode'
]
end
{
name:
hash
[
'name'
],
path:
"
#{
prefix
}
/
#{
fname
}
.png"
}
end
end
end
end
lib/gitlab/award_emoji.rb
0 → 100644
View file @
3bdc57f0
module
Gitlab
class
AwardEmoji
CATEGORIES
=
{
other:
"Other"
,
objects:
"Objects"
,
places:
"Places"
,
travel_places:
"Travel"
,
emoticons:
"Emoticons"
,
objects_symbols:
"Symbols"
,
nature:
"Nature"
,
celebration:
"Celebration"
,
people:
"People"
,
activity:
"Activity"
,
flags:
"Flags"
,
food_drink:
"Food"
}.
with_indifferent_access
CATEGORY_ALIASES
=
{
symbols:
"objects_symbols"
,
foods:
"food_drink"
,
travel:
"travel_places"
}.
with_indifferent_access
def
self
.
normalize_emoji_name
(
name
)
aliases
[
name
]
||
name
end
def
self
.
emoji_by_category
unless
@emoji_by_category
@emoji_by_category
=
Hash
.
new
{
|
h
,
key
|
h
[
key
]
=
[]
}
emojis
.
each
do
|
emoji_name
,
data
|
data
[
"name"
]
=
emoji_name
# Skip Fitzpatrick(tone) modifiers
next
if
data
[
"category"
]
==
"modifier"
category
=
CATEGORY_ALIASES
[
data
[
"category"
]]
||
data
[
"category"
]
@emoji_by_category
[
category
]
<<
data
end
@emoji_by_category
=
@emoji_by_category
.
sort
.
to_h
end
@emoji_by_category
end
def
self
.
emojis
@emojis
||=
begin
json_path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'index.json'
)
JSON
.
parse
(
File
.
read
(
json_path
))
end
end
def
self
.
aliases
@aliases
||=
begin
json_path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'aliases.json'
)
JSON
.
parse
(
File
.
read
(
json_path
))
end
end
# Returns an Array of Emoji names and their asset URLs.
def
self
.
urls
@urls
||=
begin
path
=
File
.
join
(
Rails
.
root
,
'fixtures'
,
'emojis'
,
'digests.json'
)
prefix
=
Gitlab
::
Application
.
config
.
assets
.
prefix
digest
=
Gitlab
::
Application
.
config
.
assets
.
digest
JSON
.
parse
(
File
.
read
(
path
)).
map
do
|
hash
|
if
digest
fname
=
"
#{
hash
[
'unicode'
]
}
-
#{
hash
[
'digest'
]
}
"
else
fname
=
hash
[
'unicode'
]
end
{
name:
hash
[
'name'
],
path:
"
#{
prefix
}
/
#{
fname
}
.png"
}
end
end
end
end
end
spec/controllers/groups_controller_spec.rb
View file @
3bdc57f0
...
@@ -31,9 +31,9 @@ describe GroupsController do
...
@@ -31,9 +31,9 @@ describe GroupsController do
let
(
:issue_2
)
{
create
(
:issue
,
project:
project
)
}
let
(
:issue_2
)
{
create
(
:issue
,
project:
project
)
}
before
do
before
do
create_list
(
:
upvote_note
,
3
,
project:
project
,
note
able:
issue_2
)
create_list
(
:
award_emoji
,
3
,
award
able:
issue_2
)
create_list
(
:
upvote_note
,
2
,
project:
project
,
note
able:
issue_1
)
create_list
(
:
award_emoji
,
2
,
award
able:
issue_1
)
create_list
(
:
downvote_note
,
2
,
project:
project
,
noteable:
issue_2
)
create_list
(
:
award_emoji
,
2
,
awardable:
issue_2
,
name:
"thumbsdown"
)
sign_in
(
user
)
sign_in
(
user
)
end
end
...
@@ -56,9 +56,9 @@ describe GroupsController do
...
@@ -56,9 +56,9 @@ describe GroupsController do
let
(
:merge_request_2
)
{
create
(
:merge_request
,
:simple
,
source_project:
project
)
}
let
(
:merge_request_2
)
{
create
(
:merge_request
,
:simple
,
source_project:
project
)
}
before
do
before
do
create_list
(
:
upvote_note
,
3
,
project:
project
,
note
able:
merge_request_2
)
create_list
(
:
award_emoji
,
3
,
award
able:
merge_request_2
)
create_list
(
:
upvote_note
,
2
,
project:
project
,
note
able:
merge_request_1
)
create_list
(
:
award_emoji
,
2
,
award
able:
merge_request_1
)
create_list
(
:
downvote_note
,
2
,
project:
project
,
noteable:
merge_request_2
)
create_list
(
:
award_emoji
,
2
,
awardable:
merge_request_2
,
name:
"thumbsdown"
)
sign_in
(
user
)
sign_in
(
user
)
end
end
...
...
spec/factories/award_emoji.rb
0 → 100644
View file @
3bdc57f0
FactoryGirl
.
define
do
factory
:award_emoji
do
name
"thumbsup"
user
awardable
factory: :issue
end
end
spec/factories/notes.rb
View file @
3bdc57f0
...
@@ -36,8 +36,6 @@ FactoryGirl.define do
...
@@ -36,8 +36,6 @@ FactoryGirl.define do
factory
:note_on_merge_request_diff
,
traits:
[
:on_merge_request
,
:on_diff
]
factory
:note_on_merge_request_diff
,
traits:
[
:on_merge_request
,
:on_diff
]
factory
:note_on_project_snippet
,
traits:
[
:on_project_snippet
]
factory
:note_on_project_snippet
,
traits:
[
:on_project_snippet
]
factory
:system_note
,
traits:
[
:system
]
factory
:system_note
,
traits:
[
:system
]
factory
:downvote_note
,
traits:
[
:award
,
:downvote
]
factory
:upvote_note
,
traits:
[
:award
,
:upvote
]
trait
:on_commit
do
trait
:on_commit
do
project
project
...
@@ -69,10 +67,6 @@ FactoryGirl.define do
...
@@ -69,10 +67,6 @@ FactoryGirl.define do
system
true
system
true
end
end
trait
:award
do
is_award
true
end
trait
:downvote
do
trait
:downvote
do
note
"thumbsdown"
note
"thumbsdown"
end
end
...
...
spec/helpers/issues_helper_spec.rb
View file @
3bdc57f0
...
@@ -127,18 +127,15 @@ describe IssuesHelper do
...
@@ -127,18 +127,15 @@ describe IssuesHelper do
it
{
is_expected
.
to
eq
(
"!1, !2, or !3"
)
}
it
{
is_expected
.
to
eq
(
"!1, !2, or !3"
)
}
end
end
describe
"note_active_class"
do
describe
'#award_active_class'
do
before
do
let!
(
:upvote
)
{
create
(
:award_emoji
)
}
@note
=
create
:note
@note1
=
create
:note
end
it
"returns empty string for unauthenticated user"
do
it
"returns empty string for unauthenticated user"
do
expect
(
note_active_class
(
Note
.
all
,
nil
)).
to
eq
(
""
)
expect
(
award_active_class
(
AwardEmoji
.
all
,
nil
)).
to
eq
(
""
)
end
end
it
"returns active string for author"
do
it
"returns active string for author"
do
expect
(
note_active_class
(
Note
.
all
,
@note
.
autho
r
)).
to
eq
(
"active"
)
expect
(
award_active_class
(
AwardEmoji
.
all
,
upvote
.
use
r
)).
to
eq
(
"active"
)
end
end
end
end
...
...
spec/lib/award_emoji_spec.rb
→
spec/lib/
gitlab/
award_emoji_spec.rb
View file @
3bdc57f0
require
'spec_helper'
require
'spec_helper'
describe
AwardEmoji
do
describe
Gitlab
::
AwardEmoji
do
describe
'.urls'
do
describe
'.urls'
do
subject
{
AwardEmoji
.
urls
}
subject
{
Gitlab
::
AwardEmoji
.
urls
}
it
{
is_expected
.
to
be_an_instance_of
(
Array
)
}
it
{
is_expected
.
to
be_an_instance_of
(
Array
)
}
it
{
is_expected
.
to_not
be_empty
}
it
{
is_expected
.
to_not
be_empty
}
...
@@ -19,7 +19,7 @@ describe AwardEmoji do
...
@@ -19,7 +19,7 @@ describe AwardEmoji do
describe
'.emoji_by_category'
do
describe
'.emoji_by_category'
do
it
"only contains known categories"
do
it
"only contains known categories"
do
undefined_categories
=
AwardEmoji
.
emoji_by_category
.
keys
-
AwardEmoji
::
CATEGORIES
.
keys
undefined_categories
=
Gitlab
::
AwardEmoji
.
emoji_by_category
.
keys
-
Gitlab
::
AwardEmoji
::
CATEGORIES
.
keys
expect
(
undefined_categories
).
to
be_empty
expect
(
undefined_categories
).
to
be_empty
end
end
end
end
...
...
spec/models/award_emoji_spec.rb
0 → 100644
View file @
3bdc57f0
require
'spec_helper'
describe
AwardEmoji
,
models:
true
do
describe
'Associations'
do
it
{
is_expected
.
to
belong_to
(
:awardable
)
}
it
{
is_expected
.
to
belong_to
(
:user
)
}
end
describe
'modules'
do
it
{
is_expected
.
to
include_module
(
Participable
)
}
end
describe
"validations"
do
it
{
is_expected
.
to
validate_presence_of
(
:awardable
)
}
it
{
is_expected
.
to
validate_presence_of
(
:user
)
}
it
{
is_expected
.
to
validate_presence_of
(
:name
)
}
it
{
is_expected
.
to
validate_presence_of
(
:awardable
)
}
# To circumvent a bug in the shoulda matchers
describe
"scoped uniqueness validation"
do
it
"rejects duplicate award emoji"
do
user
=
create
(
:user
)
issue
=
create
(
:issue
)
create
(
:award_emoji
,
user:
user
,
awardable:
issue
)
new_award
=
AwardEmoji
.
new
(
user:
user
,
awardable:
issue
,
name:
"thumbsup"
)
expect
(
new_award
).
not_to
be_valid
end
end
end
end
spec/models/concerns/issuable_spec.rb
View file @
3bdc57f0
...
@@ -198,18 +198,4 @@ describe Issue, "Issuable" do
...
@@ -198,18 +198,4 @@ describe Issue, "Issuable" do
to
eq
({
'Author'
=>
'Robert'
,
'Assignee'
=>
'Douwe'
})
to
eq
({
'Author'
=>
'Robert'
,
'Assignee'
=>
'Douwe'
})
end
end
end
end
describe
"votes"
do
before
do
author
=
create
:user
project
=
create
:empty_project
issue
.
notes
.
awards
.
create!
(
note:
"thumbsup"
,
author:
author
,
project:
project
)
issue
.
notes
.
awards
.
create!
(
note:
"thumbsdown"
,
author:
author
,
project:
project
)
end
it
"returns correct values"
do
expect
(
issue
.
upvotes
).
to
eq
(
1
)
expect
(
issue
.
downvotes
).
to
eq
(
1
)
end
end
end
end
spec/models/note_spec.rb
View file @
3bdc57f0
...
@@ -152,23 +152,6 @@ describe Note, models: true do
...
@@ -152,23 +152,6 @@ describe Note, models: true do
end
end
end
end
describe
'.grouped_awards'
do
before
do
create
:note
,
note:
"smile"
,
is_award:
true
create
:note
,
note:
"smile"
,
is_award:
true
end
it
"returns grouped hash of notes"
do
expect
(
Note
.
grouped_awards
.
keys
.
size
).
to
eq
(
3
)
expect
(
Note
.
grouped_awards
[
"smile"
]).
to
match_array
(
Note
.
all
)
end
it
"returns thumbsup and thumbsdown always"
do
expect
(
Note
.
grouped_awards
[
"thumbsup"
]).
to
match_array
(
Note
.
none
)
expect
(
Note
.
grouped_awards
[
"thumbsdown"
]).
to
match_array
(
Note
.
none
)
end
end
describe
'#active?'
do
describe
'#active?'
do
it
'is always true when the note has no associated diff'
do
it
'is always true when the note has no associated diff'
do
note
=
build
(
:note
)
note
=
build
(
:note
)
...
@@ -239,11 +222,6 @@ describe Note, models: true do
...
@@ -239,11 +222,6 @@ describe Note, models: true do
note
=
build
(
:note
,
system:
true
)
note
=
build
(
:note
,
system:
true
)
expect
(
note
.
editable?
).
to
be_falsy
expect
(
note
.
editable?
).
to
be_falsy
end
end
it
"returns false"
do
note
=
build
(
:note
,
is_award:
true
,
note:
"smiley"
)
expect
(
note
.
editable?
).
to
be_falsy
end
end
end
describe
"cross_reference_not_visible_for?"
do
describe
"cross_reference_not_visible_for?"
do
...
@@ -270,23 +248,6 @@ describe Note, models: true do
...
@@ -270,23 +248,6 @@ describe Note, models: true do
end
end
end
end
describe
"set_award!"
do
let
(
:merge_request
)
{
create
:merge_request
}
it
"converts aliases to actual name"
do
note
=
create
(
:note
,
note:
":+1:"
,
noteable:
merge_request
)
expect
(
note
.
reload
.
note
).
to
eq
(
"thumbsup"
)
end
it
"is not an award emoji when comment is on a diff"
do
note
=
create
(
:note
,
note:
":blowfish:"
,
noteable:
merge_request
,
line_code:
"11d5d2e667e9da4f7f610f81d86c974b146b13bd_0_2"
)
note
=
note
.
reload
expect
(
note
.
note
).
to
eq
(
":blowfish:"
)
expect
(
note
.
is_award?
).
to
be_falsy
end
end
describe
'clear_blank_line_code!'
do
describe
'clear_blank_line_code!'
do
it
'clears a blank line code before validation'
do
it
'clears a blank line code before validation'
do
note
=
build
(
:note
,
line_code:
' '
)
note
=
build
(
:note
,
line_code:
' '
)
...
...
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