mirror of
https://github.com/discourse/discourse.git
synced 2025-01-22 11:40:06 +08:00
Added method for testing ember stuff
Collapse user actions in UI so it stops looking crazy Removed dud dupe user action TOPIC_RESPONSE Always show the owner of a post on the user page, actions by others at the bottom
This commit is contained in:
parent
4e9d9138d6
commit
161420fac0
|
@ -220,7 +220,6 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus)
|
||||
Discourse.insertProbes()
|
||||
|
||||
|
||||
# subscribe to any site customizations that are loaded
|
||||
$('link.custom-css').each ->
|
||||
split = @href.split("/")
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
RESPONSE = "6"
|
||||
MENTION = "7"
|
||||
TOPIC_RESPONSE = "8"
|
||||
QUOTE = "9"
|
||||
NEW_PRIVATE_MESSAGE = "12"
|
||||
GOT_PRIVATE_MESSAGE = "13"
|
||||
|
||||
window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
||||
|
||||
avatarLarge: (->
|
||||
|
@ -68,7 +61,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
callback(message)
|
||||
|
||||
filterStream: (filter)->
|
||||
filter = Discourse.User.statGroups[filter].join(",") if Discourse.User.statGroups[filter]
|
||||
filter = Discourse.UserAction.statGroups[filter].join(",") if Discourse.UserAction.statGroups[filter]
|
||||
@set('streamFilter', filter)
|
||||
@set('stream', Em.A())
|
||||
@loadMoreUserActions()
|
||||
|
@ -97,6 +90,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
if result and result.user_actions and result.user_actions.each
|
||||
result.user_actions.each (i)=>
|
||||
stream.pushObject(Discourse.UserAction.create(i))
|
||||
stream = Discourse.UserAction.collapseStream(stream)
|
||||
@set('stream', stream)
|
||||
callback() if callback
|
||||
|
||||
|
@ -104,7 +98,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
total=0
|
||||
return 0 unless stats = @get('stats')
|
||||
@get('stats').each (s)->
|
||||
total+= parseInt(s.count) unless s.action_type is NEW_PRIVATE_MESSAGE || s.action_type is GOT_PRIVATE_MESSAGE
|
||||
total+= parseInt(s.count) unless s.get("isPM")
|
||||
total
|
||||
).property('stats.@each')
|
||||
|
||||
|
@ -112,7 +106,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
r = []
|
||||
return r if @blank('stats')
|
||||
@get('stats').each (s)->
|
||||
r.push s unless (s.action_type == NEW_PRIVATE_MESSAGE || s.action_type == GOT_PRIVATE_MESSAGE)
|
||||
r.push s unless s.get('isPM')
|
||||
r
|
||||
).property('stats.@each')
|
||||
|
||||
|
@ -120,14 +114,14 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
r = []
|
||||
return r if @blank('stats')
|
||||
@get('stats').each (s)->
|
||||
r.push s if (s.action_type is NEW_PRIVATE_MESSAGE or s.action_type is GOT_PRIVATE_MESSAGE)
|
||||
r.push s if s.get('isPM')
|
||||
r
|
||||
).property('stats.@each')
|
||||
|
||||
inboxCount: (->
|
||||
r = 0
|
||||
@get('stats').each (s)->
|
||||
if s.action_type is GOT_PRIVATE_MESSAGE
|
||||
if s.action_type == Discourse.UserAction.GOT_PRIVATE_MESSAGE
|
||||
r = s.count
|
||||
return false
|
||||
return r
|
||||
|
@ -136,7 +130,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
sentItemsCount: (->
|
||||
r = 0
|
||||
@get('stats').each (s)->
|
||||
if s.action_type is NEW_PRIVATE_MESSAGE
|
||||
if s.action_type == Discourse.UserAction.NEW_PRIVATE_MESSAGE
|
||||
r = s.count
|
||||
return false
|
||||
return r
|
||||
|
@ -155,10 +149,13 @@ window.Discourse.User.reopenClass
|
|||
g = {}
|
||||
stats.each (s) =>
|
||||
found = false
|
||||
for k,v of @statGroups
|
||||
for k,v of Discourse.UserAction.statGroups
|
||||
if v.contains(s.action_type)
|
||||
found = true
|
||||
g[k] = {count: 0} unless g[k]
|
||||
g[k] = Em.Object.create(
|
||||
description: Em.String.i18n("user_action_descriptions.#{k}")
|
||||
count: 0
|
||||
action_type: parseInt(k,10)) unless g[k]
|
||||
g[k].count += parseInt(s.count)
|
||||
c = g[k].count
|
||||
if s.action_type == k
|
||||
|
@ -172,24 +169,26 @@ window.Discourse.User.reopenClass
|
|||
).exclude (s)->
|
||||
!s
|
||||
|
||||
statGroups: (->
|
||||
g = {}
|
||||
g[RESPONSE] = [RESPONSE,MENTION,TOPIC_RESPONSE,QUOTE]
|
||||
g
|
||||
)()
|
||||
|
||||
find: (username) ->
|
||||
promise = new RSVP.Promise()
|
||||
$.ajax
|
||||
url: "/users/" + username + '.json',
|
||||
success: (json) =>
|
||||
json.user.stats = @groupStats(json.user.stats)
|
||||
json.user.stream = json.user.stream.map (ua) -> Discourse.UserAction.create(ua) if json.user.stream
|
||||
# todo: decompose to object
|
||||
json.user.stats = @groupStats(json.user.stats.map (s)->
|
||||
obj = Em.Object.create(s)
|
||||
obj.isPM = obj.action_type == Discourse.UserAction.NEW_PRIVATE_MESSAGE ||
|
||||
obj.action_type == Discourse.UserAction.GOT_PRIVATE_MESSAGE
|
||||
obj
|
||||
)
|
||||
json.user.stream = Discourse.UserAction.collapseStream(json.user.stream.map (ua) ->
|
||||
Discourse.UserAction.create(ua)) if json.user.stream
|
||||
user = Discourse.User.create(json.user)
|
||||
promise.resolve(user)
|
||||
error: (xhr) -> promise.reject(xhr)
|
||||
promise
|
||||
|
||||
|
||||
createAccount: (name, email, password, username, passwordConfirm, challenge) ->
|
||||
$.ajax
|
||||
url: '/users'
|
||||
|
|
|
@ -2,3 +2,104 @@ window.Discourse.UserAction = Discourse.Model.extend
|
|||
postUrl:(->
|
||||
Discourse.Utilities.postUrl(@get('slug'), @get('topic_id'), @get('post_number'))
|
||||
).property()
|
||||
|
||||
isPM: (->
|
||||
a = @get('action_type')
|
||||
a == UserAction.NEW_PRIVATE_MESSAGE || UserAction.GOT_PRIVATE_MESSAGE
|
||||
).property()
|
||||
|
||||
addChild: (action)->
|
||||
groups = @get("childGroups")
|
||||
unless groups
|
||||
groups =
|
||||
likes: Discourse.UserActionGroup.create(icon: "icon-heart")
|
||||
stars: Discourse.UserActionGroup.create(icon: "icon-star")
|
||||
edits: Discourse.UserActionGroup.create(icon: "icon-pencil")
|
||||
bookmarks: Discourse.UserActionGroup.create(icon: "icon-bookmark")
|
||||
|
||||
@set("childGroups", groups)
|
||||
|
||||
ua = Discourse.UserAction
|
||||
bucket = switch action.action_type
|
||||
when ua.LIKE,ua.WAS_LIKED then "likes"
|
||||
when ua.STAR then "stars"
|
||||
when ua.EDIT then "edits"
|
||||
when ua.BOOKMARK then "bookmarks"
|
||||
|
||||
current = groups[bucket]
|
||||
current.push(action) if current
|
||||
return
|
||||
|
||||
children:(->
|
||||
g = @get("childGroups")
|
||||
rval = []
|
||||
if g
|
||||
rval = [g.likes, g.stars, g.edits, g.bookmarks].filter((i) -> i.get("items") && i.get("items").length > 0)
|
||||
rval
|
||||
).property("childGroups")
|
||||
|
||||
switchToActing: ->
|
||||
@set('username', @get('acting_username'))
|
||||
@set('avatar_template', @get('acting_avatar_template'))
|
||||
@set('name', @get('acting_name'))
|
||||
|
||||
window.Discourse.UserAction.reopenClass
|
||||
collapseStream: (stream) ->
|
||||
collapse = [@LIKE, @WAS_LIKED, @STAR, @EDIT, @BOOKMARK]
|
||||
uniq = {}
|
||||
collapsed = Em.A()
|
||||
pos = 0
|
||||
stream.each (item)->
|
||||
key = "#{item.topic_id}-#{item.post_number}"
|
||||
|
||||
found = uniq[key]
|
||||
|
||||
if found == undefined
|
||||
if collapse.indexOf(item.action_type) >= 0
|
||||
current = Discourse.UserAction.create(item)
|
||||
current.set('action_type',null)
|
||||
current.set('description',null)
|
||||
item.switchToActing()
|
||||
current.addChild(item)
|
||||
else
|
||||
current = item
|
||||
uniq[key] = pos
|
||||
collapsed[pos] = current
|
||||
pos += 1
|
||||
else
|
||||
if collapse.indexOf(item.action_type) >= 0
|
||||
item.switchToActing()
|
||||
collapsed[found].addChild(item)
|
||||
else
|
||||
collapsed[found].set('action_type', item.get('action_type'))
|
||||
collapsed[found].set('description', item.get('description'))
|
||||
|
||||
|
||||
collapsed
|
||||
|
||||
|
||||
# in future we should be sending this through from the server
|
||||
LIKE: 1
|
||||
WAS_LIKED: 2
|
||||
BOOKMARK: 3
|
||||
NEW_TOPIC: 4
|
||||
POST: 5
|
||||
RESPONSE: 6
|
||||
MENTION: 7
|
||||
QUOTE: 9
|
||||
STAR: 10
|
||||
EDIT: 11
|
||||
NEW_PRIVATE_MESSAGE: 12
|
||||
GOT_PRIVATE_MESSAGE: 13
|
||||
|
||||
window.Discourse.UserAction.reopenClass
|
||||
statGroups: (->
|
||||
g = {}
|
||||
g[Discourse.UserAction.RESPONSE] = [
|
||||
Discourse.UserAction.RESPONSE,
|
||||
Discourse.UserAction.MENTION,
|
||||
Discourse.UserAction.QUOTE
|
||||
]
|
||||
g
|
||||
)()
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
window.Discourse.UserActionGroup = Discourse.Model.extend
|
||||
push: (item)->
|
||||
@items = [] unless @items
|
||||
@items.push(item)
|
|
@ -12,6 +12,14 @@
|
|||
<p class='excerpt'>
|
||||
{{{unbound excerpt}}}
|
||||
</p>
|
||||
{{#each children}}
|
||||
<div class='child-actions'>
|
||||
<i class="icon {{unbound icon}}"></i>
|
||||
{{#each items}}
|
||||
<a href="/users/{{unbound username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" avatarTemplatePath="avatar_template" ignoreTitle="true"}}</div></a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
{{/with}}
|
||||
{{/collection}}
|
||||
</div>
|
||||
|
|
|
@ -268,6 +268,27 @@
|
|||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
// styling of bottom section
|
||||
#user-stream .child-actions {
|
||||
margin-top: 8px;
|
||||
.avatar-link {
|
||||
float: none;
|
||||
}
|
||||
.icon {
|
||||
width: 15px;
|
||||
display: inline-block;
|
||||
color: #777;
|
||||
}
|
||||
.avatar-wrapper {
|
||||
border: none;
|
||||
}
|
||||
.avatar-link {
|
||||
margin-right: 3px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@include medium-width {
|
||||
#user-stream {
|
||||
width: 725px;
|
||||
|
@ -277,4 +298,4 @@
|
|||
#user-stream {
|
||||
width: 680px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,6 @@ class PostAlertObserver < ActiveRecord::Observer
|
|||
exclude_user_ids << extract_mentioned_users(post).map{|u| u.id}
|
||||
exclude_user_ids << extract_quoted_users(post).map{|u| u.id}
|
||||
exclude_user_ids.flatten!
|
||||
|
||||
TopicUser.where(topic_id: post.topic_id, notification_level: TopicUser::NotificationLevel::WATCHING).includes(:user).each do |tu|
|
||||
create_notification(tu.user, Notification.Types[:posted], post) unless exclude_user_ids.include?(tu.user_id)
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ class TopicUser < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.auto_track(user_id, topic_id, reason)
|
||||
if exec_sql("select 1 from topic_users where user_id = ? and topic_id = ? and notifications_reason_id is null", user_id, topic_id).count == 1
|
||||
if TopicUser.where(user_id: user_id, topic_id: topic_id, notifications_reason_id: nil).exists?
|
||||
self.change(user_id, topic_id,
|
||||
notification_level: NotificationLevel::TRACKING,
|
||||
notifications_reason_id: reason
|
||||
|
|
|
@ -3,6 +3,7 @@ require_dependency 'sql_builder'
|
|||
|
||||
class UserAction < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :target_post, :class_name => "Post"
|
||||
attr_accessible :acting_user_id, :action_type, :target_topic_id, :target_post_id, :target_user_id, :user_id
|
||||
|
||||
validates_presence_of :action_type
|
||||
|
@ -15,7 +16,6 @@ class UserAction < ActiveRecord::Base
|
|||
POST = 5
|
||||
RESPONSE= 6
|
||||
MENTION = 7
|
||||
TOPIC_RESPONSE = 8
|
||||
QUOTE = 9
|
||||
STAR = 10
|
||||
EDIT = 11
|
||||
|
@ -29,7 +29,6 @@ class UserAction < ActiveRecord::Base
|
|||
NEW_TOPIC,
|
||||
POST,
|
||||
RESPONSE,
|
||||
TOPIC_RESPONSE,
|
||||
LIKE,
|
||||
WAS_LIKED,
|
||||
MENTION,
|
||||
|
@ -39,23 +38,19 @@ class UserAction < ActiveRecord::Base
|
|||
].each_with_index.to_a.flatten]
|
||||
|
||||
def self.stats(user_id, guardian)
|
||||
sql = <<SQL
|
||||
select action_type, count(*) count
|
||||
from user_actions
|
||||
where user_id = ?
|
||||
group by action_type
|
||||
SQL
|
||||
|
||||
results = self.exec_sql(sql, user_id).to_a
|
||||
results = UserAction.select("action_type, COUNT(*) count, '' description")
|
||||
.where(user_id: user_id)
|
||||
.group('action_type')
|
||||
.to_a
|
||||
|
||||
# should push this into the sql at some point, but its simple enough for now
|
||||
unless guardian.can_see_private_messages?(user_id)
|
||||
results.reject!{|a| [GOT_PRIVATE_MESSAGE, NEW_PRIVATE_MESSAGE].include?(a["action_type"].to_i)}
|
||||
results.reject!{|a| [GOT_PRIVATE_MESSAGE, NEW_PRIVATE_MESSAGE].include?(a.action_type)}
|
||||
end
|
||||
|
||||
results.sort!{|a,b| ORDER[a["action_type"].to_i] <=> ORDER[b["action_type"].to_i]}
|
||||
results.sort!{|a,b| ORDER[a.action_type] <=> ORDER[b.action_type]}
|
||||
results.each do |row|
|
||||
row["description"] = self.description(row["action_type"], detailed: true)
|
||||
row.description = self.description(row.action_type, detailed: true)
|
||||
end
|
||||
|
||||
results
|
||||
|
@ -74,14 +69,22 @@ SQL
|
|||
guardian = opts[:guardian]
|
||||
ignore_private_messages = opts[:ignore_private_messages]
|
||||
|
||||
# The weird thing is that target_post_id can be null, so it makes everything
|
||||
# ever so more complex. Should we allow this, not sure.
|
||||
|
||||
builder = SqlBuilder.new("
|
||||
select t.title, a.action_type, a.created_at,
|
||||
t.id topic_id, coalesce(p.post_number, 1) post_number, u.email ,u.username, u.name, u.id user_id, coalesce(p.cooked, p2.cooked) cooked
|
||||
from user_actions as a
|
||||
join topics t on t.id = a.target_topic_id
|
||||
left join posts p on p.id = a.target_post_id
|
||||
left join users u on u.id = a.acting_user_id
|
||||
left join posts p2 on p2.topic_id = a.target_topic_id and p2.post_number = 1
|
||||
SELECT
|
||||
t.title, a.action_type, a.created_at, t.id topic_id,
|
||||
coalesce(p.post_number, 1) post_number,
|
||||
pu.email ,pu.username, pu.name, pu.id user_id,
|
||||
u.email acting_email, u.username acting_username, u.name acting_name, u.id acting_user_id,
|
||||
coalesce(p.cooked, p2.cooked) cooked
|
||||
FROM user_actions as a
|
||||
JOIN topics t on t.id = a.target_topic_id
|
||||
LEFT JOIN posts p on p.id = a.target_post_id
|
||||
JOIN posts p2 on p2.topic_id = a.target_topic_id and p2.post_number = 1
|
||||
JOIN users u on u.id = a.acting_user_id
|
||||
JOIN users pu on pu.id = COALESCE(p.user_id, t.user_id)
|
||||
/*where*/
|
||||
/*order_by*/
|
||||
/*offset*/
|
||||
|
@ -109,13 +112,16 @@ left join posts p2 on p2.topic_id = a.target_topic_id and p2.post_number = 1
|
|||
end
|
||||
|
||||
data.each do |row|
|
||||
row["action_type"] = row["action_type"].to_i
|
||||
row["description"] = self.description(row["action_type"])
|
||||
row["created_at"] = DateTime.parse(row["created_at"])
|
||||
# we should probably cache the excerpts in the db at some point
|
||||
row["excerpt"] = PrettyText.excerpt(row["cooked"],300) if row["cooked"]
|
||||
row["cooked"] = nil
|
||||
row["avatar_template"] = User.avatar_template(row["email"])
|
||||
row["acting_avatar_template"] = User.avatar_template(row["acting_email"])
|
||||
row.delete("email")
|
||||
row.delete("acting_email")
|
||||
row["slug"] = Slug.for(row["title"])
|
||||
end
|
||||
|
||||
|
@ -137,8 +143,6 @@ left join posts p2 on p2.topic_id = a.target_topic_id and p2.post_number = 1
|
|||
t[:likes_given]
|
||||
when RESPONSE
|
||||
t[:responses]
|
||||
when TOPIC_RESPONSE
|
||||
t[:topic_responses]
|
||||
when POST
|
||||
t[:posts]
|
||||
when MENTION
|
||||
|
@ -161,7 +165,7 @@ left join posts p2 on p2.topic_id = a.target_topic_id and p2.post_number = 1
|
|||
then t[:posted]
|
||||
when LIKE,WAS_LIKED
|
||||
then t[:liked]
|
||||
when RESPONSE, TOPIC_RESPONSE,POST
|
||||
when RESPONSE,POST
|
||||
then t[:responded_to]
|
||||
when BOOKMARK
|
||||
then t[:bookmarked]
|
||||
|
|
|
@ -110,21 +110,6 @@ class UserActionObserver < ActiveRecord::Observer
|
|||
UserAction.remove_action!(row)
|
||||
end
|
||||
end
|
||||
|
||||
return if model.topic.private_message?
|
||||
|
||||
# a bit odd but we may have stray records
|
||||
if model.topic and model.topic.user_id != model.user_id
|
||||
row[:action_type] = UserAction::TOPIC_RESPONSE
|
||||
row[:user_id] = model.topic.user_id
|
||||
|
||||
if model.deleted_at.nil?
|
||||
UserAction.log_action!(row)
|
||||
else
|
||||
UserAction.remove_action!(row)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def log_topic(model)
|
||||
|
|
|
@ -460,6 +460,8 @@ en:
|
|||
saving: "Saving..."
|
||||
saved: "Saved!"
|
||||
|
||||
user_action_descriptions:
|
||||
"6": "Responses"
|
||||
user:
|
||||
information: "User Information"
|
||||
profile: Profile
|
||||
|
|
14
db/migrate/20130213021450_remove_topic_response_actions.rb
Normal file
14
db/migrate/20130213021450_remove_topic_response_actions.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
class RemoveTopicResponseActions < ActiveRecord::Migration
|
||||
def up
|
||||
# 2 notes:
|
||||
# migrations should never use the object model to run sql, otherwise they are a time bomb
|
||||
# this action type is not valid, we log a "response" action type anyway due to the watch implementation, its a relic.
|
||||
#
|
||||
# There is an open question about we should keep stuff in the user stream on the user page, even if a topic is unwatched
|
||||
# Eg: I am not watching a topic I created, when somebody responds to the topic should I be notified on the user page?
|
||||
execute 'delete from user_actions where action_type = 8'
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
end
|
2072
db/structure.sql
2072
db/structure.sql
File diff suppressed because it is too large
Load Diff
21
spec/javascripts/hacks.js
Normal file
21
spec/javascripts/hacks.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
// hacks for ember, this sets up our app for testing
|
||||
|
||||
(function(){
|
||||
|
||||
var currentWindowOnload = window.onload;
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
|
||||
$('<div id="main"><div class="rootElement"></div></div>').appendTo($('body')).hide();
|
||||
|
||||
Discourse.SiteSettings = {}
|
||||
|
||||
Discourse.Router.map(function() {
|
||||
this.route("jasmine",{path: "/jasmine"});
|
||||
Discourse.routeBuilder.apply(this)
|
||||
});
|
||||
}
|
||||
|
||||
})()
|
|
@ -1,6 +1,6 @@
|
|||
describe "Discourse.MessageBus", ->
|
||||
|
||||
describe "Web Sockets", ->
|
||||
describe "Long polling", ->
|
||||
|
||||
bus = Discourse.MessageBus
|
||||
bus.start()
|
||||
|
|
|
@ -9,7 +9,7 @@ describe "PreloadStore", ->
|
|||
expect(PreloadStore.contains('joker')).toBe(false)
|
||||
|
||||
it "returns true for a stored key", ->
|
||||
expect(PreloadStore.contains('bane')).toBe(true)
|
||||
expect(PreloadStore.contains('bane')).toBe(true)
|
||||
|
||||
describe 'getStatic', ->
|
||||
|
||||
|
@ -17,7 +17,7 @@ describe "PreloadStore", ->
|
|||
expect(PreloadStore.getStatic('joker')).toBe(undefined)
|
||||
|
||||
it "returns the the key if it exists", ->
|
||||
expect(PreloadStore.getStatic('bane')).toBe('evil')
|
||||
expect(PreloadStore.getStatic('bane')).toBe('evil')
|
||||
|
||||
it "removes the key after being called", ->
|
||||
PreloadStore.getStatic('bane')
|
||||
|
|
|
@ -1,11 +1,46 @@
|
|||
//= require env
|
||||
//= require jquery
|
||||
|
||||
//= require external/jquery.ui.widget.js
|
||||
//= require external/handlebars-1.0.rc.2.js
|
||||
//= require ../../app/assets/javascripts/preload_store.js
|
||||
|
||||
//= require preload_store
|
||||
// probe framework first
|
||||
//= require ../../app/assets/javascripts/discourse/components/probes.js
|
||||
|
||||
// Externals we need to load first
|
||||
//= require ../../app/assets/javascripts/external/jquery-1.8.2.js
|
||||
|
||||
//= require ../../app/assets/javascripts/external/jquery.ui.widget.js
|
||||
//= require ../../app/assets/javascripts/external/handlebars-1.0.rc.2.js
|
||||
//= require ../../app/assets/javascripts/external/ember.js
|
||||
|
||||
// Pagedown customizations
|
||||
//= require ../../app/assets/javascripts/pagedown_custom.js
|
||||
|
||||
// The rest of the externals
|
||||
//= require_tree ../../app/assets/javascripts/external
|
||||
//= require i18n
|
||||
//= require ../../app/assets/javascripts/discourse/translations
|
||||
|
||||
//= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers
|
||||
//= require ../../app/assets/javascripts/discourse
|
||||
|
||||
// Stuff we need to load first
|
||||
//= require_tree ../../app/assets/javascripts/discourse/mixins
|
||||
//= require ../../app/assets/javascripts/discourse/components/debounce
|
||||
//= require ../../app/assets/javascripts/discourse/views/view
|
||||
//= require ../../app/assets/javascripts/discourse/controllers/controller
|
||||
//= require ../../app/assets/javascripts/discourse/views/modal/modal_body_view
|
||||
//= require ../../app/assets/javascripts/discourse/models/model
|
||||
//= require ../../app/assets/javascripts/discourse/routes/discourse_route
|
||||
|
||||
//= require_tree ../../app/assets/javascripts/discourse/controllers
|
||||
//= require_tree ../../app/assets/javascripts/discourse/components
|
||||
//= require_tree ../../app/assets/javascripts/discourse/models
|
||||
//= require_tree ../../app/assets/javascripts/discourse/views
|
||||
//= require_tree ../../app/assets/javascripts/discourse/helpers
|
||||
//= require_tree ../../app/assets/javascripts/discourse/templates
|
||||
//= require_tree ../../app/assets/javascripts/discourse/routes
|
||||
|
||||
|
||||
//= require_tree .
|
||||
|
||||
//= require hacks
|
||||
|
|
16
spec/javascripts/user_action_spec.js.coffee
Normal file
16
spec/javascripts/user_action_spec.js.coffee
Normal file
|
@ -0,0 +1,16 @@
|
|||
describe "Discourse.UserAction", ->
|
||||
|
||||
describe "collapseStream", ->
|
||||
it "collapses all likes", ->
|
||||
actions = [
|
||||
Discourse.UserAction.create(action_type: Discourse.UserAction.LIKE, topic_id:1, user_id:1, post_number:1)
|
||||
Discourse.UserAction.create(action_type: Discourse.UserAction.EDIT, topic_id:2, user_id:1, post_number:1)
|
||||
Discourse.UserAction.create(action_type: Discourse.UserAction.LIKE, topic_id:1, user_id:2, post_number:1)
|
||||
]
|
||||
|
||||
actions = Discourse.UserAction.collapseStream(actions)
|
||||
expect(actions.length).toBe(2)
|
||||
|
||||
expect(actions[0].get("children").length).toBe(1)
|
||||
expect(actions[0].get("children")[0].items.length).toBe(2)
|
||||
|
|
@ -111,7 +111,6 @@ describe UserAction do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
it 'should not log a post user action' do
|
||||
@post.user.user_actions.where(action_type: UserAction::POST).first.should be_nil
|
||||
end
|
||||
|
@ -121,7 +120,7 @@ describe UserAction do
|
|||
before do
|
||||
@other_user = Fabricate(:coding_horror)
|
||||
@mentioned = Fabricate(:admin)
|
||||
@response = Fabricate(:post, topic: @post.topic, user: @other_user, raw: "perhaps @#{@mentioned.username} knows how this works?")
|
||||
@response = Fabricate(:post, reply_to_post_number: 1, topic: @post.topic, user: @other_user, raw: "perhaps @#{@mentioned.username} knows how this works?")
|
||||
end
|
||||
|
||||
it 'should log a post action for the poster' do
|
||||
|
@ -129,7 +128,7 @@ describe UserAction do
|
|||
end
|
||||
|
||||
it 'should log a post action for the original poster' do
|
||||
@post.user.user_actions.where(action_type: UserAction::TOPIC_RESPONSE).first.should_not be_nil
|
||||
@post.user.user_actions.where(action_type: UserAction::RESPONSE).first.should_not be_nil
|
||||
end
|
||||
|
||||
it 'should log a mention for the mentioned' do
|
||||
|
@ -142,6 +141,10 @@ describe UserAction do
|
|||
@response.user.user_actions.where(action_type: UserAction::POST).count.should == 1
|
||||
end
|
||||
|
||||
it 'should not log topic reply and reply for a single post' do
|
||||
@post.user.user_actions.joins(:target_post).where('posts.post_number = 2').count.should == 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user