-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Create Update Feed #117
base: master
Are you sure you want to change the base?
Changes from all commits
29a28ca
5e49de5
4c90eb3
7b195b2
535cc1e
094f399
a9e44c1
212aece
2c8b3f2
267b290
29738fc
2391d72
2a4e099
e20ee34
6040002
962eeda
ab657c7
a9206c5
19c4ef4
8517657
d5707fa
11e7091
1840b30
fac47c3
cecbecf
20f9167
6bd7539
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import Flow from require "lapis.flow" | ||
|
||
import Events, Followings, TimelineEvents, Users from require "models" | ||
|
||
import assert_error from require "lapis.application" | ||
|
||
class EventsFlow extends Flow | ||
expose_assigns: true | ||
|
||
new: (...) => | ||
super ... | ||
assert_error @current_user, "must be logged in" | ||
|
||
create_event_and_deliver: (object, event_type) => | ||
import preload from require "lapis.db.model" | ||
|
||
-- Creates the primary event | ||
event = Events\create({ | ||
user: @current_user | ||
object: object | ||
event_type: Events.event_types\for_db event_type | ||
}) | ||
|
||
-- Adds the new event to the timeline of every subscriber of @current_user | ||
do | ||
user_followers = Followings\select "where object_type = ? and object_id = ? and type = ?", Followings\object_type_for_object(@current_user), @current_user.id, Followings.types.subscription | ||
preload user_followers, "source_user" | ||
|
||
for user in *user_followers | ||
follower_user = user.source_user | ||
|
||
TimelineEvents\create({ | ||
user_id: follower_user.id | ||
event_id: event.id | ||
}) | ||
|
||
-- If the event is a update, then every follower of the module should see the event | ||
if Events.event_types.update == Events.event_types\for_db(event_type) | ||
followers = Followings\select "where object_id = ? and object_type = ? and type = ?", event.object_id, event.object_type, Followings.types.subscription | ||
|
||
preload followers, "source_user" | ||
|
||
for users in *followers | ||
follower_user = users.source_user | ||
TimelineEvents\create({ | ||
user_id: follower_user.id | ||
event_id: event.id | ||
}) | ||
|
||
remove_from_timeline: (object, event_type) => | ||
db = require "lapis.db" | ||
timeline_events = if Events\object_type_for_object(object) == Events\object_type_for_model(Users) | ||
-- If we are removing the subscription from an use | ||
db.select "user_id, event_id from timeline_events join events on timeline_events.event_id = events.id and events.source_user_id = ?", object.id | ||
else | ||
-- If we are removing the subscription from Module | ||
db.select "user_id, event_id from timeline_events join events on timeline_events.event_id = events.id and events.source_user_id = ? and events.object_type = ? and object_id = ?", object.user_id, Events\object_type_for_object(object), object.id | ||
|
||
for timeline_entry in *timeline_events | ||
TimelineEvents\delete(timeline_entry.user_id, timeline_entry.event_id) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
db = require "lapis.db" | ||
|
||
import Model, enum from require "lapis.db.model" | ||
import safe_insert from require "helpers.models" | ||
|
||
class Events extends Model | ||
@timestamp: true | ||
|
||
@event_types: enum { | ||
subscription: 1 | ||
bookmark: 2 | ||
update: 3 | ||
} | ||
|
||
@relations: { | ||
{"source_user", belongs_to: "Users"} | ||
{"object", polymorphic_belongs_to: { | ||
[1]: {"module", "Modules"} | ||
[2]: {"user", "Users"} | ||
}} | ||
} | ||
|
||
@create: (opts={}) => | ||
assert opts.user, "missing event's user" | ||
assert opts.object, "missing event's object" | ||
assert opts.event_type, "missing event_type, events must have a type" | ||
|
||
event_opts = { | ||
event_type: opts.event_type | ||
source_user_id: opts.user.id | ||
object_id: opts.object.id | ||
object_type: @@object_type_for_object opts.object | ||
} | ||
|
||
event = safe_insert @, event_opts | ||
|
||
return event | ||
|
||
delete: () => | ||
import TimelineEvents from require "models" | ||
|
||
db.delete @@table_name!, { id: @id } | ||
db.delete TimelineEvents\table_name!, { event_id: @id} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
db = require "lapis.db" | ||
import Model from require "lapis.db.model" | ||
|
||
|
||
class TimelineEvents extends Model | ||
@primary_key: { "user_id", "event_id" } | ||
|
||
@relations: { | ||
{"user", belongs_to: "Users"} | ||
{"event", belongs_to: "Events"} | ||
} | ||
|
||
@create: (opts={}) => | ||
assert opts.user_id, "user id not specified" | ||
assert opts.event_id, "event id not specified" | ||
|
||
super { | ||
user_id: opts.user_id | ||
event_id: opts.event_id | ||
} | ||
|
||
@delete: (user_id, event_id) => | ||
db.delete @table_name!, { user_id: user_id, event_id: event_id } | ||
|
||
@user_timeline: (user) => | ||
import preload from require "lapis.db.model" | ||
timeline = @@select "where user_id = ? limit 50", user.id | ||
preload timeline, "user" | ||
preload timeline, event: "object" | ||
return timeline |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,13 +6,13 @@ import request_as from require "spec.helpers" | |
factory = require "spec.factory" | ||
|
||
|
||
import Modules, Versions, Followings, Users, Notifications, NotificationObjects from require "models" | ||
|
||
|
||
describe "applications.modules", -> | ||
import Modules, Versions, Events, Followings, Users, Notifications, NotificationObjects from require "spec.models" | ||
use_test_server! | ||
|
||
before_each -> | ||
truncate_tables Modules, Versions, Followings, Users, Notifications, NotificationObjects | ||
|
||
it "follows module", -> | ||
current_user = factory.Users! | ||
|
@@ -21,8 +21,12 @@ describe "applications.modules", -> | |
assert.same 302, status | ||
|
||
followings = Followings\select! | ||
events = Events\select! | ||
user_timeline = current_user\timeline! | ||
|
||
assert.same 1, #followings | ||
assert.same 1, #events | ||
|
||
following = unpack followings | ||
|
||
assert.same current_user.id, following.source_user_id | ||
|
@@ -44,7 +48,10 @@ describe "applications.modules", -> | |
assert.same 302, status | ||
|
||
followings = Followings\select! | ||
events = Events\select! | ||
|
||
assert.same 0, #followings | ||
assert.same 0, #events | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fails because of the comment mentioned above in flows/followings.moon There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently "only" in tests the event created in |
||
|
||
current_user\refresh! | ||
mod\refresh! | ||
|
@@ -114,4 +121,3 @@ describe "applications.modules", -> | |
|
||
assert.same 0, Notifications\count! | ||
assert.same 0, NotificationObjects\count! | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import use_test_env from require "lapis.spec" | ||
|
||
factory = require "spec.factory" | ||
|
||
describe "models.events", -> | ||
import Events, Modules, Users, TimelineEvents from require "spec.models" | ||
|
||
use_test_env! | ||
|
||
it "creates an event of user following user", -> | ||
user = factory.Users! | ||
followed_user = factory.Users! | ||
|
||
event = Events\create({ | ||
user: user | ||
object: followed_user | ||
event_type: Events.event_types.subscription | ||
}) | ||
|
||
user_timeline = user\timeline! | ||
|
||
assert.same user.id, event.source_user_id | ||
assert.same followed_user.id, event.object_id | ||
assert.same event.event_type, Events.event_types.subscription | ||
|
||
assert.same, #user_timeline, 1 | ||
|
||
it "creates an event of user following a module", -> | ||
user = factory.Users! | ||
module = factory.Modules! | ||
|
||
event = Events\create({ | ||
user: user | ||
object: module | ||
event_type: Events.event_types.subscription | ||
}) | ||
|
||
user_timeline = user\timeline! | ||
|
||
assert.same user.id, event.source_user_id | ||
assert.same module.id, event.object_id | ||
assert.same event.event_type, Events.event_types.subscription | ||
|
||
assert.same, #user_timeline, 1 | ||
|
||
it "creates an event of user starring a module", -> | ||
user = factory.Users! | ||
module = factory.Modules! | ||
|
||
event = Events\create({ | ||
user: user | ||
object: module | ||
event_type: Events.event_types.bookmark | ||
}) | ||
|
||
user_timeline = user\timeline! | ||
|
||
assert.same user.id, event.source_user_id | ||
assert.same module.id, event.object_id | ||
assert.same event.event_type, Events.event_types.bookmark | ||
|
||
assert.same, #user_timeline, 1 | ||
|
||
it "deletes an event", -> | ||
user = factory.Users! | ||
module = factory.Modules! | ||
|
||
event = Events\create({ | ||
user: user | ||
object: module | ||
event_type: Events.event_types.bookmark | ||
}) | ||
|
||
event_id = event.id | ||
|
||
event\delete! | ||
|
||
assert.same Events\find(event_id), nil | ||
assert.same 0, #user\timeline! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
TimelineEvents = require "widgets.timeline_events" | ||
|
||
class Timeline extends require "widgets.page" | ||
inner_content: => | ||
h2 -> | ||
text "Timeline" | ||
widget TimelineEvents! | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you probably want to either paginate this, or limit to something reasonable like 50 for the time being
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm limiting by 50 but I plan to add pagination soon.