@@ -10,6 +10,7 @@ defmodule AlgoraWeb.Admin.AdminLive do
1010 alias Algora.Analytics
1111 alias Algora.Markdown
1212
13+ @ impl true
1314 def mount ( _params , _session , socket ) do
1415 { :ok , analytics } = Analytics . get_company_analytics ( )
1516 funnel_data = Analytics . get_funnel_data ( )
@@ -49,121 +50,7 @@ defmodule AlgoraWeb.Admin.AdminLive do
4950 |> start_async ( :get_activities , fn -> Activities . all ( ) end ) }
5051 end
5152
52- def cell ( % { value: % NaiveDateTime { } = value } = assigns ) do
53- ~H"""
54- < span :if = { @ timezone } class = "tabular-nums whitespace-nowrap text-sm " >
55- { Calendar . strftime (
56- DateTime . from_naive! ( value , "Etc/UTC" ) |> DateTime . shift_zone! ( @ timezone ) ,
57- "%Y/%m/%d, %H:%M:%S"
58- ) }
59- </ span >
60- """
61- end
62-
63- def cell ( % { value: value } = assigns ) when is_binary ( value ) do
64- cond do
65- String . starts_with? ( value , "https://github.com/" ) ->
66- ~H"""
67- < div class = "flex items-center gap-2 text-sm " >
68- < . link
69- href = { @ value }
70- rel = "noopener "
71- target = "_blank "
72- class = "h-8 w-8 rounded-lg bg-muted flex items-center justify-center hover:bg-muted-foreground/40 "
73- >
74- < . icon name = "github " class = "h-4 w-4 " />
75- </ . link >
76- { @ value |> String . replace ( "https://github.com/" , "" ) }
77- </ div >
78- """
79-
80- String . starts_with? ( value , "https://algora-console.fly.storage.tigris.dev" ) or
81- String . starts_with? ( value , "https://avatars.githubusercontent.com" ) or
82- String . starts_with? ( value , "https://app.algora.io/asset" ) or
83- String . starts_with? ( value , "https://console.algora.io/asset" ) or
84- String . starts_with? ( value , "https://algora.io/asset" ) or
85- String . starts_with? ( value , "https://www.gravatar.com" ) or
86- String . starts_with? ( value , "https://media.licdn.com" ) or
87- String . starts_with? ( value , "https://pbs.twimg.com" ) or
88- String . starts_with? ( value , "https://gravatar.com" ) ->
89- ~H"""
90- < div class = "flex justify-center " >
91- < img src = { @ value } class = "h-6 w-6 rounded-full " />
92- </ div >
93- """
94-
95- String . match? ( value , ~r/ ^[^\s ]+@[^\s ]+$/ ) && assigns . posthog_project_id ->
96- ~H"""
97- < div class = "flex items-center gap-2 text-sm " >
98- < . link
99- href = { "https://us.posthog.com/project/#{ @ posthog_project_id } /person/#{ @ value } #activeTab=sessionRecordings" }
100- rel = "noopener "
101- target = "_blank "
102- class = "h-8 w-8 rounded-lg bg-muted flex items-center justify-center hover:bg-muted-foreground/40 "
103- >
104- < . icon name = "tabler-video " class = "h-4 w-4 " />
105- </ . link >
106- { @ value }
107- </ div >
108- """
109-
110- String . match? ( value , ~r/ ^[^\s ]+@[^\s ]+$/ ) ->
111- ~H"""
112- { @ value }
113- """
114-
115- String . length ( value ) == 2 ->
116- country_emoji = Algora.Misc.CountryEmojis . get ( value )
117-
118- ~H"""
119- < div class = "flex justify-center " >
120- { if country_emoji , do: country_emoji , else: @ value }
121- </ div >
122- """
123-
124- true ->
125- ~H"""
126- < span class = "text-sm " >
127- { @ value }
128- </ span >
129- """
130- end
131- end
132-
133- def cell ( % { value: value } = assigns ) when is_list ( value ) do
134- ~H"""
135- < div class = "flex gap-2 whitespace-nowrap " >
136- <%= for item <- @ value do %>
137- < . badge > { item } </ . badge >
138- <% end %>
139- </ div >
140- """
141- end
142-
143- def cell ( % { value: value } = assigns ) when is_map ( value ) do
144- ~H"""
145- < pre class = "flex gap-2 whitespace-pre-wrap font-mono " >
146- { Jason . encode! ( @ value , pretty: true ) }
147- </ pre >
148- """
149- end
150-
151- def cell ( % { value: { currency , amount } } = assigns ) do
152- ~H"""
153- < div class = "font-display font-medium text-base text-emerald-400 tabular-nums text-right " >
154- { Money . new! ( currency , amount ) }
155- </ div >
156- """
157- end
158-
159- def cell ( assigns ) do
160- ~H"""
161- < span class = "text-sm " >
162- { @ value }
163- </ span >
164- """
165- end
166-
53+ @ impl true
16754 def render ( assigns ) do
16855 ~H"""
16956 < div class = "space-y-8 p-8 " >
@@ -423,10 +310,7 @@ defmodule AlgoraWeb.Admin.AdminLive do
423310 """
424311 end
425312
426- def status_color ( :active ) , do: "success"
427- def status_color ( :pending ) , do: "warning"
428- def status_color ( _ ) , do: "secondary"
429-
313+ @ impl true
430314 def handle_event ( "select_period" , % { "period" => period } , socket ) do
431315 { :ok , analytics } = Analytics . get_company_analytics ( period )
432316 funnel_data = Analytics . get_funnel_data ( period )
@@ -438,6 +322,7 @@ defmodule AlgoraWeb.Admin.AdminLive do
438322 |> assign ( :selected_period , period ) }
439323 end
440324
325+ @ impl true
441326 def handle_event ( "validate_notes" , % { "mainthing" => % { "content" => content } } , socket ) do
442327 changeset =
443328 % Mainthing { }
@@ -450,6 +335,7 @@ defmodule AlgoraWeb.Admin.AdminLive do
450335 |> assign ( :notes_preview , Markdown . render_unsafe ( content ) ) }
451336 end
452337
338+ @ impl true
453339 def handle_event ( "save_notes" , % { "mainthing" => params } , socket ) do
454340 case_result =
455341 case socket . assigns . mainthing do
@@ -474,44 +360,171 @@ defmodule AlgoraWeb.Admin.AdminLive do
474360 end
475361 end
476362
363+ @ impl true
477364 def handle_event ( "notes-toggle" , _ , socket ) do
478365 { :noreply , assign ( socket , :notes_edit_mode , ! socket . assigns . notes_edit_mode ) }
479366 end
480367
368+ @ impl true
481369 def handle_event ( "notes-fullscreen-toggle" , _ , socket ) do
482370 { :noreply , assign ( socket , :notes_full_screen , ! socket . assigns . notes_full_screen ) }
483371 end
484372
373+ @ impl true
485374 def handle_event ( "validate_query" , % { "query" => query } , socket ) do
486375 { :noreply , assign ( socket , :sql_query , query ) }
487376 end
488377
378+ @ impl true
489379 def handle_event ( "execute_query" , % { "query" => query } , socket ) do
490380 results = execute_sql_query ( query )
491381 { :noreply , socket |> assign ( :sql_query , query ) |> assign ( :query_results , results ) }
492382 end
493383
384+ @ impl true
494385 def handle_event ( "save_query" , % { "query_name" => name } , socket ) when byte_size ( name ) > 0 do
495386 save_query ( name , socket . assigns . sql_query )
496387 saved_queries = get_saved_queries ( )
497388
498389 { :noreply , assign ( socket , :saved_queries , saved_queries ) }
499390 end
500391
392+ @ impl true
501393 def handle_event ( "load_query" , % { "name" => name } , socket ) do
502394 queries = get_saved_queries ( )
503395 query = Map . get ( queries , name )
504396 { :noreply , assign ( socket , sql_query: query , new_query_name: name ) }
505397 end
506398
399+ @ impl true
507400 def handle_info ( % Activities.Activity { } = activity , socket ) do
508401 { :noreply , stream_insert ( socket , :activities , activity , at: 0 ) }
509402 end
510403
404+ @ impl true
511405 def handle_async ( :get_activities , { :ok , fetched } , socket ) do
512406 { :noreply , stream ( socket , :activities , fetched ) }
513407 end
514408
409+ defp cell ( % { value: % NaiveDateTime { } = value } = assigns ) do
410+ ~H"""
411+ < span :if = { @ timezone } class = "tabular-nums whitespace-nowrap text-sm " >
412+ { Calendar . strftime (
413+ DateTime . from_naive! ( value , "Etc/UTC" ) |> DateTime . shift_zone! ( @ timezone ) ,
414+ "%Y/%m/%d, %H:%M:%S"
415+ ) }
416+ </ span >
417+ """
418+ end
419+
420+ defp cell ( % { value: value } = assigns ) when is_binary ( value ) do
421+ cond do
422+ String . starts_with? ( value , "https://github.com/" ) ->
423+ ~H"""
424+ < div class = "flex items-center gap-2 text-sm " >
425+ < . link
426+ href = { @ value }
427+ rel = "noopener "
428+ target = "_blank "
429+ class = "h-8 w-8 rounded-lg bg-muted flex items-center justify-center hover:bg-muted-foreground/40 "
430+ >
431+ < . icon name = "github " class = "h-4 w-4 " />
432+ </ . link >
433+ { @ value |> String . replace ( "https://github.com/" , "" ) }
434+ </ div >
435+ """
436+
437+ String . starts_with? ( value , "https://algora-console.fly.storage.tigris.dev" ) or
438+ String . starts_with? ( value , "https://avatars.githubusercontent.com" ) or
439+ String . starts_with? ( value , "https://app.algora.io/asset" ) or
440+ String . starts_with? ( value , "https://console.algora.io/asset" ) or
441+ String . starts_with? ( value , "https://algora.io/asset" ) or
442+ String . starts_with? ( value , "https://www.gravatar.com" ) or
443+ String . starts_with? ( value , "https://media.licdn.com" ) or
444+ String . starts_with? ( value , "https://pbs.twimg.com" ) or
445+ String . starts_with? ( value , "https://gravatar.com" ) ->
446+ ~H"""
447+ < div class = "flex justify-center " >
448+ < img src = { @ value } class = "h-6 w-6 rounded-full " />
449+ </ div >
450+ """
451+
452+ String . match? ( value , ~r/ ^[^\s ]+@[^\s ]+$/ ) && assigns . posthog_project_id ->
453+ ~H"""
454+ < div class = "flex items-center gap-2 text-sm " >
455+ < . link
456+ href = { "https://us.posthog.com/project/#{ @ posthog_project_id } /person/#{ @ value } #activeTab=sessionRecordings" }
457+ rel = "noopener "
458+ target = "_blank "
459+ class = "h-8 w-8 rounded-lg bg-muted flex items-center justify-center hover:bg-muted-foreground/40 "
460+ >
461+ < . icon name = "tabler-video " class = "h-4 w-4 " />
462+ </ . link >
463+ { @ value }
464+ </ div >
465+ """
466+
467+ String . match? ( value , ~r/ ^[^\s ]+@[^\s ]+$/ ) ->
468+ ~H"""
469+ { @ value }
470+ """
471+
472+ String . length ( value ) == 2 ->
473+ country_emoji = Algora.Misc.CountryEmojis . get ( value )
474+
475+ ~H"""
476+ < div class = "flex justify-center " >
477+ { if country_emoji , do: country_emoji , else: @ value }
478+ </ div >
479+ """
480+
481+ true ->
482+ ~H"""
483+ < span class = "text-sm " >
484+ { @ value }
485+ </ span >
486+ """
487+ end
488+ end
489+
490+ defp cell ( % { value: value } = assigns ) when is_list ( value ) do
491+ ~H"""
492+ < div class = "flex gap-2 whitespace-nowrap " >
493+ <%= for item <- @ value do %>
494+ < . badge > { item } </ . badge >
495+ <% end %>
496+ </ div >
497+ """
498+ end
499+
500+ defp cell ( % { value: value } = assigns ) when is_map ( value ) do
501+ ~H"""
502+ < pre class = "flex gap-2 whitespace-pre-wrap font-mono " >
503+ { Jason . encode! ( @ value , pretty: true ) }
504+ </ pre >
505+ """
506+ end
507+
508+ defp cell ( % { value: { currency , amount } } = assigns ) do
509+ ~H"""
510+ < div class = "font-display font-medium text-base text-emerald-400 tabular-nums text-right " >
511+ { Money . new! ( currency , amount ) }
512+ </ div >
513+ """
514+ end
515+
516+ defp cell ( assigns ) do
517+ ~H"""
518+ < span class = "text-sm " >
519+ { @ value }
520+ </ span >
521+ """
522+ end
523+
524+ defp status_color ( :active ) , do: "success"
525+ defp status_color ( :pending ) , do: "warning"
526+ defp status_color ( _ ) , do: "secondary"
527+
515528 defp execute_sql_query ( query ) do
516529 output =
517530 Algora.Repo . transaction ( fn ->
0 commit comments