@@ -82,6 +82,10 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
8282
8383 @ impl true
8484 def handle_params ( params , _uri , socket ) do
85+ previous_registrations_window = socket . assigns . registrations_window
86+ previous_games_window = socket . assigns . games_window
87+ previous_active_users_window = socket . assigns . active_users_window
88+
8589 registrations_window = normalize_chart_window ( params [ "registrations_window" ] )
8690 games_window = normalize_chart_window ( params [ "games_window" ] )
8791 active_users_window = normalize_chart_window ( params [ "active_users_window" ] )
@@ -91,9 +95,45 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
9195 |> assign ( :registrations_window , registrations_window )
9296 |> assign ( :games_window , games_window )
9397 |> assign ( :active_users_window , active_users_window )
94- |> assign_registrations_chart_data_async ( registrations_window )
95- |> assign_games_chart_data_async ( games_window )
96- |> assign_active_users_chart_data_async ( active_users_window ) }
98+ |> maybe_assign_registrations_chart_data_async (
99+ registrations_window ,
100+ previous_registrations_window
101+ )
102+ |> maybe_assign_games_chart_data_async ( games_window , previous_games_window )
103+ |> maybe_assign_active_users_chart_data_async (
104+ active_users_window ,
105+ previous_active_users_window
106+ ) }
107+ end
108+
109+ defp maybe_assign_registrations_chart_data_async ( socket , chart_window , previous_window ) do
110+ should_refresh = previous_window != chart_window or not socket . assigns . registrations_chart . ok?
111+
112+ if should_refresh do
113+ assign_registrations_chart_data_async ( socket , chart_window )
114+ else
115+ socket
116+ end
117+ end
118+
119+ defp maybe_assign_games_chart_data_async ( socket , chart_window , previous_window ) do
120+ should_refresh = previous_window != chart_window or not socket . assigns . games_chart . ok?
121+
122+ if should_refresh do
123+ assign_games_chart_data_async ( socket , chart_window )
124+ else
125+ socket
126+ end
127+ end
128+
129+ defp maybe_assign_active_users_chart_data_async ( socket , chart_window , previous_window ) do
130+ should_refresh = previous_window != chart_window or not socket . assigns . active_users_chart . ok?
131+
132+ if should_refresh do
133+ assign_active_users_chart_data_async ( socket , chart_window )
134+ else
135+ socket
136+ end
97137 end
98138
99139 defp assign_registrations_chart_data_async ( socket , chart_window ) do
@@ -422,7 +462,7 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
422462 defp format_chart_datetime ( datetime , :week ) , do: Calendar . strftime ( datetime , "%Y-%m-%d" )
423463 defp format_chart_datetime ( datetime , :month ) , do: Calendar . strftime ( datetime , "%Y-%m" )
424464
425- defp format_axis_datetime ( datetime , :hour ) , do: Calendar . strftime ( datetime , "%b %d %H:%M " )
465+ defp format_axis_datetime ( datetime , :hour ) , do: Calendar . strftime ( datetime , "%b %d" )
426466 defp format_axis_datetime ( datetime , :day ) , do: Calendar . strftime ( datetime , "%b %d" )
427467 defp format_axis_datetime ( datetime , :week ) , do: Calendar . strftime ( datetime , "%b %d" )
428468 defp format_axis_datetime ( datetime , :month ) , do: Calendar . strftime ( datetime , "%b %Y" )
@@ -539,6 +579,34 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
539579 defp chart_plot_width , do: chart_width ( ) - chart_left_padding ( ) - chart_right_padding ( )
540580 defp chart_plot_height , do: chart_height ( ) - chart_top_padding ( ) - chart_bottom_padding ( )
541581 defp chart_plot_end_x , do: chart_width ( ) - chart_right_padding ( )
582+ defp chart_plot_end_y , do: chart_height ( ) - chart_bottom_padding ( )
583+ defp chart_x_ticks_count , do: 11
584+
585+ defp chart_x_axis_ticks ( from_datetime , to_datetime , granularity ) do
586+ total_seconds =
587+ to_datetime
588+ |> NaiveDateTime . diff ( from_datetime , :second )
589+ |> max ( 0 )
590+
591+ ticks_count = chart_x_ticks_count ( )
592+ max_index = max ( ticks_count - 1 , 1 )
593+
594+ Enum . map ( 0 .. ( ticks_count - 1 ) , fn index ->
595+ ratio = index / max_index
596+ seconds_offset = round ( total_seconds * ratio )
597+ tick_datetime = NaiveDateTime . add ( from_datetime , seconds_offset , :second )
598+ x = Float . round ( chart_left_padding ( ) + ratio * chart_plot_width ( ) , 2 )
599+
600+ anchor =
601+ cond do
602+ index == 0 -> "start"
603+ index == max_index -> "end"
604+ true -> "middle"
605+ end
606+
607+ % { x: x , anchor: anchor , label: format_axis_datetime ( tick_datetime , granularity ) }
608+ end )
609+ end
542610
543611 @ impl true
544612 def render ( assigns ) do
@@ -638,24 +706,43 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
638706 stroke-linecap = "round "
639707 >
640708 </ path >
709+ < line
710+ x1 = { chart_left_padding ( ) }
711+ y1 = { chart_plot_end_y ( ) }
712+ x2 = { chart_plot_end_x ( ) }
713+ y2 = { chart_plot_end_y ( ) }
714+ stroke = { chart_axis_text_color ( ) }
715+ stroke-width = "1 "
716+ >
717+ </ line >
718+ <%= for tick <- chart_x_axis_ticks (
719+ @ registrations_chart . result . joins_from ,
720+ @ registrations_chart . result . joins_to ,
721+ @ registrations_chart . result . granularity
722+ ) do %>
723+ < line
724+ x1 = { tick . x }
725+ y1 = { chart_plot_end_y ( ) }
726+ x2 = { tick . x }
727+ y2 = { chart_plot_end_y ( ) + 4 }
728+ stroke = { chart_axis_text_color ( ) }
729+ stroke-width = "1 "
730+ >
731+ </ line >
732+ < text
733+ x = { tick . x }
734+ y = { chart_height ( ) - 6 }
735+ fill = { chart_axis_text_color ( ) }
736+ font-size = "11 "
737+ text-anchor = { tick . anchor }
738+ >
739+ { tick . label }
740+ </ text >
741+ <% end %>
641742 </ svg >
642743
643- < div class = "d-flex justify-content-between cb-text mt-1 " >
644- < span >
645- { format_axis_datetime (
646- @ registrations_chart . result . joins_from ,
647- @ registrations_chart . result . granularity
648- ) }
649- </ span >
650- < span >
651- { peak_label ( @ registrations_chart . result . granularity ) } : { @ registrations_chart . result . max_joins }
652- </ span >
653- < span >
654- { format_axis_datetime (
655- @ registrations_chart . result . joins_to ,
656- @ registrations_chart . result . granularity
657- ) }
658- </ span >
744+ < div class = "text-center cb-text mt-1 " >
745+ { peak_label ( @ registrations_chart . result . granularity ) } : { @ registrations_chart . result . max_joins }
659746 </ div >
660747 <% else %>
661748 < div class = "text-center py-5 " style = { "color: #{ chart_secondary_text_color ( ) } ;" } >
@@ -730,18 +817,43 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
730817 stroke-linecap = "round "
731818 >
732819 </ path >
820+ < line
821+ x1 = { chart_left_padding ( ) }
822+ y1 = { chart_plot_end_y ( ) }
823+ x2 = { chart_plot_end_x ( ) }
824+ y2 = { chart_plot_end_y ( ) }
825+ stroke = { chart_axis_text_color ( ) }
826+ stroke-width = "1 "
827+ >
828+ </ line >
829+ <%= for tick <- chart_x_axis_ticks (
830+ @ games_chart . result . games_from ,
831+ @ games_chart . result . games_to ,
832+ @ games_chart . result . granularity
833+ ) do %>
834+ < line
835+ x1 = { tick . x }
836+ y1 = { chart_plot_end_y ( ) }
837+ x2 = { tick . x }
838+ y2 = { chart_plot_end_y ( ) + 4 }
839+ stroke = { chart_axis_text_color ( ) }
840+ stroke-width = "1 "
841+ >
842+ </ line >
843+ < text
844+ x = { tick . x }
845+ y = { chart_height ( ) - 6 }
846+ fill = { chart_axis_text_color ( ) }
847+ font-size = "11 "
848+ text-anchor = { tick . anchor }
849+ >
850+ { tick . label }
851+ </ text >
852+ <% end %>
733853 </ svg >
734854
735- < div class = "d-flex justify-content-between cb-text mt-1 " >
736- < span >
737- { format_axis_datetime ( @ games_chart . result . games_from , @ games_chart . result . granularity ) }
738- </ span >
739- < span >
740- { peak_label ( @ games_chart . result . granularity ) } : { @ games_chart . result . max_games }
741- </ span >
742- < span >
743- { format_axis_datetime ( @ games_chart . result . games_to , @ games_chart . result . granularity ) }
744- </ span >
855+ < div class = "text-center cb-text mt-1 " >
856+ { peak_label ( @ games_chart . result . granularity ) } : { @ games_chart . result . max_games }
745857 </ div >
746858 <% else %>
747859 < div class = "text-center py-5 " style = { "color: #{ chart_secondary_text_color ( ) } ;" } >
@@ -822,24 +934,43 @@ defmodule CodebattleWeb.Live.Admin.IndexView do
822934 stroke-linecap = "round "
823935 >
824936 </ path >
937+ < line
938+ x1 = { chart_left_padding ( ) }
939+ y1 = { chart_plot_end_y ( ) }
940+ x2 = { chart_plot_end_x ( ) }
941+ y2 = { chart_plot_end_y ( ) }
942+ stroke = { chart_axis_text_color ( ) }
943+ stroke-width = "1 "
944+ >
945+ </ line >
946+ <%= for tick <- chart_x_axis_ticks (
947+ @ active_users_chart . result . active_users_from ,
948+ @ active_users_chart . result . active_users_to ,
949+ @ active_users_chart . result . granularity
950+ ) do %>
951+ < line
952+ x1 = { tick . x }
953+ y1 = { chart_plot_end_y ( ) }
954+ x2 = { tick . x }
955+ y2 = { chart_plot_end_y ( ) + 4 }
956+ stroke = { chart_axis_text_color ( ) }
957+ stroke-width = "1 "
958+ >
959+ </ line >
960+ < text
961+ x = { tick . x }
962+ y = { chart_height ( ) - 6 }
963+ fill = { chart_axis_text_color ( ) }
964+ font-size = "11 "
965+ text-anchor = { tick . anchor }
966+ >
967+ { tick . label }
968+ </ text >
969+ <% end %>
825970 </ svg >
826971
827- < div class = "d-flex justify-content-between cb-text mt-1 " >
828- < span >
829- { format_axis_datetime (
830- @ active_users_chart . result . active_users_from ,
831- @ active_users_chart . result . granularity
832- ) }
833- </ span >
834- < span >
835- { peak_label ( @ active_users_chart . result . granularity ) } : { @ active_users_chart . result . max_active_users }
836- </ span >
837- < span >
838- { format_axis_datetime (
839- @ active_users_chart . result . active_users_to ,
840- @ active_users_chart . result . granularity
841- ) }
842- </ span >
972+ < div class = "text-center cb-text mt-1 " >
973+ { peak_label ( @ active_users_chart . result . granularity ) } : { @ active_users_chart . result . max_active_users }
843974 </ div >
844975 <% else %>
845976 < div class = "text-center py-5 " style = { "color: #{ chart_secondary_text_color ( ) } ;" } >
0 commit comments