@@ -5,6 +5,8 @@ defmodule Algora.Activities do
5
5
alias Algora.Accounts.Identity
6
6
alias Algora.Accounts.User
7
7
alias Algora.Activities.Activity
8
+ alias Algora.Activities.Router
9
+ alias Algora.Activities.Views
8
10
alias Algora.Bounties.Bounty
9
11
alias Algora.Repo
10
12
@@ -199,48 +201,130 @@ defmodule Algora.Activities do
199
201
assoc_id: a . assoc_id ,
200
202
assoc_name: ^ table ,
201
203
assoc: t ,
202
- inserted_at: a . inserted_at
204
+ notify_users: a . notify_users ,
205
+ visibility: a . visibility ,
206
+ template: a . template ,
207
+ meta: a . meta ,
208
+ changes: a . changes ,
209
+ trace_id: a . trace_id ,
210
+ previous_event_id: a . previous_event_id ,
211
+ inserted_at: a . inserted_at ,
212
+ updated_at: a . updated_at
203
213
}
204
214
215
+ struct ( Activity , Algora.Repo . one ( query ) )
216
+ end
217
+
218
+ def get_with_preloaded_assoc ( table , id ) do
219
+ schema = schema_from_table ( table )
220
+
221
+ with % { assoc_id: assoc_id } = activity <- get ( table , id ) ,
222
+ assoc when is_map ( assoc ) <- get_preloaded_assoc ( schema , assoc_id ) do
223
+ Map . put ( activity , :assoc , assoc )
224
+ end
225
+ end
226
+
227
+ def get_preloaded_assoc ( schema , assoc_id ) do
228
+ query =
229
+ if Kernel . function_exported? ( schema , :query , 1 ) do
230
+ schema . query ( assoc_id )
231
+ else
232
+ from a in schema , where: a . id == ^ assoc_id
233
+ end
234
+
205
235
Algora.Repo . one ( query )
206
236
end
207
237
208
- def get_assoc ( prefix , assoc_id ) when prefix in [ "bounty_activities" ] do
209
- get_assoc ( prefix , assoc_id , [ :owner ] )
238
+ def assoc_url ( table , id ) do
239
+ table |> get ( id ) |> Router . route ( )
210
240
end
211
241
212
- def get_assoc ( prefix , assoc_id ) when prefix in [ "identity_activities" ] do
213
- get_assoc ( prefix , assoc_id , [ :user ] )
242
+ def subscribe do
243
+ Phoenix.PubSub . subscribe ( Algora.PubSub , "activities" )
214
244
end
215
245
216
- def get_assoc ( prefix , assoc_id , preload ) do
217
- assoc_table = schema_from_table ( prefix )
246
+ def subscribe ( schema ) when is_atom ( schema ) do
247
+ schema |> schema_from_table ( ) |> subscribe ( )
248
+ end
218
249
219
- query =
220
- from a in assoc_table ,
221
- preload: ^ preload ,
222
- where: a . id == ^ assoc_id
250
+ def subscribe_table ( table ) when is_binary ( table ) do
251
+ Phoenix.PubSub . subscribe ( Algora.PubSub , "activity:table:#{ table } " )
252
+ end
223
253
224
- Algora.Repo . one ( query )
254
+ def subscribe_user ( user_id ) when is_binary ( user_id ) do
255
+ Phoenix.PubSub . subscribe ( Algora.PubSub , "activity:users:#{ user_id } " )
225
256
end
226
257
227
- def get_with_assoc ( table , id ) do
228
- with % { assoc_id: assoc_id } = activity <- get ( table , id ) ,
229
- assoc when is_map ( assoc ) <- get_assoc ( table , assoc_id ) do
230
- Map . put ( activity , :assoc , assoc )
231
- end
258
+ def broadcast ( % { notify_users: [ ] } ) , do: [ ]
259
+
260
+ def broadcast ( % { notify_users: user_ids } = activity ) do
261
+ :ok = Phoenix.PubSub . broadcast ( Algora.PubSub , "activities" , activity )
262
+ :ok = Phoenix.PubSub . broadcast ( Algora.PubSub , "activity:table:#{ activity . assoc_name } " , activity )
263
+
264
+ users_query =
265
+ from u in Algora.Accounts.User ,
266
+ where: u . id in ^ user_ids ,
267
+ select: u
268
+
269
+ users_query
270
+ |> Algora.Repo . all ( )
271
+ |> Enum . reduce ( [ ] , fn user , not_online ->
272
+ # TODO setup notification preferences
273
+ :ok = Phoenix.PubSub . broadcast ( Algora.PubSub , "activity:users:#{ user . id } " , activity )
274
+ [ user | not_online ]
275
+ end )
232
276
end
233
277
234
- def assoc_url ( table , id ) do
235
- activity = get_with_assoc ( table , id )
236
- build_url ( activity )
278
+ def notify_users ( _activity , [ ] ) , do: :ok
279
+
280
+ def notify_users ( activity , users_to_notify ) do
281
+ title = activity_email_title ( activity )
282
+ body = activity_email_body ( activity )
283
+
284
+ users_to_notify
285
+ |> Enum . reduce ( [ ] , fn
286
+ % { name: display_name , email: email , id: id } , acc ->
287
+ changeset =
288
+ Algora.Activities.SendEmail . changeset ( % {
289
+ title: title ,
290
+ body: body ,
291
+ user_id: id ,
292
+ activity_id: activity . id ,
293
+ activity_type: activity . type ,
294
+ activity_table: activity . assoc_name ,
295
+ name: display_name ,
296
+ email: email
297
+ } )
298
+
299
+ [ changeset | acc ]
300
+
301
+ _user , acc ->
302
+ acc
303
+ end )
304
+ |> Oban . insert_all ( )
305
+ end
306
+
307
+ def activity_email_title ( activity ) do
308
+ apply ( Views , :"#{ activity . type } _title" , [ activity , activity . assoc ] )
237
309
end
238
310
239
- def build_url ( % { assoc: % Bounty { owner: user } } ) , do: { :ok , "/org/#{ user . handle } /bounties" }
240
- def build_url ( % { assoc: % Identity { user: % { type: :individual } = user } } ) , do: { :ok , "/@/#{ user . handle } " }
241
- def build_url ( % { assoc: % Identity { user: % { type: :organization } = user } } ) , do: { :ok , "/org/#{ user . handle } " }
311
+ def activity_email_body ( activity ) do
312
+ apply ( Views , :"#{ activity . type } _txt" , [ activity , activity . assoc ] )
313
+ end
314
+
315
+ def redirect_url_for_activity ( activity ) do
316
+ slug =
317
+ activity . assoc_name
318
+ |> to_string ( )
319
+ |> String . replace ( "_activities" , "" )
320
+
321
+ "/a/#{ slug } /#{ activity . id } "
322
+ end
242
323
243
- def build_url ( _activity ) do
244
- { :error , :not_found }
324
+ def activity_type_to_name ( type ) do
325
+ type
326
+ |> to_string ( )
327
+ |> String . split ( "_" )
328
+ |> Enum . map_join ( " " , & String . capitalize ( & 1 ) )
245
329
end
246
330
end
0 commit comments