@@ -5,36 +5,105 @@ defmodule PlausibleWeb.Live.Dashboard.Pages do
55
66 use PlausibleWeb , :live_component
77
8- alias PlausibleWeb.Components.Dashboard.Base
8+ alias PlausibleWeb.Components.Dashboard.ReportList
99 alias PlausibleWeb.Components.Dashboard.Tile
1010
11+ alias Plausible.Stats
12+ alias Plausible.Stats.Filters
13+
1114 @ tabs [
1215 { "pages" , "Top Pages" } ,
1316 { "entry-pages" , "Entry Pages" } ,
1417 { "exit-pages" , "Exit Pages" }
1518 ]
1619
17- @ tab_labels Map . new ( @ tabs )
20+ @ key_labels % {
21+ "pages" => "Page" ,
22+ "entry-pages" => "Entry page" ,
23+ "exit-pages" => "Exit page"
24+ }
25+
26+ @ max_items 9
27+ @ pagination_params { @ max_items , 1 }
28+
29+ @ metrics % {
30+ "pages" => % {
31+ visitors: % {
32+ width: "w-24" ,
33+ key: :visitors ,
34+ label: "Visitors" ,
35+ sortable: true ,
36+ plot: true
37+ } ,
38+ conversion_rate: % {
39+ width: "w-24" ,
40+ key: :conversion_rate ,
41+ label: "CR" ,
42+ sortable: true
43+ }
44+ } ,
45+ "entry-pages" => % {
46+ visitors: % {
47+ width: "w-24" ,
48+ key: :visitors ,
49+ label: "Unique Entrances" ,
50+ sortable: true ,
51+ plot: true
52+ } ,
53+ conversion_rate: % {
54+ width: "w-24" ,
55+ key: :conversion_rate ,
56+ label: "CR" ,
57+ sortable: true
58+ }
59+ } ,
60+ "exit-pages" => % {
61+ visitors: % {
62+ width: "w-24" ,
63+ key: :visitors ,
64+ label: "Unique Exits" ,
65+ sortable: true ,
66+ plot: true
67+ } ,
68+ conversion_rate: % {
69+ width: "w-24" ,
70+ key: :conversion_rate ,
71+ label: "CR" ,
72+ sortable: true
73+ }
74+ }
75+ }
76+
77+ @ filter_dimensions % {
78+ "pages" => "event:page" ,
79+ "entry-pages" => "visit:entry_page" ,
80+ "exit-pages" => "visit:exit_page"
81+ }
1882
1983 def update ( assigns , socket ) do
2084 active_tab = assigns . user_prefs [ "pages_tab" ] || "pages"
2185
2286 socket =
2387 assign ( socket ,
2488 site: assigns . site ,
89+ params: assigns . params ,
90+ query: assigns . query ,
2591 tabs: @ tabs ,
26- tab_labels: @ tab_labels ,
92+ key_labels: @ key_labels ,
93+ filter_dimensions: @ filter_dimensions ,
2794 active_tab: active_tab ,
2895 connected?: assigns . connected?
2996 )
97+ |> load_metrics ( )
3098
3199 { :ok , socket }
32100 end
33101
34102 def render ( assigns ) do
103+ assigns = assign ( assigns , :external_link_fn , & external_link / 1 )
35104 ~H"""
36105 < div >
37- < Tile . tile id = "breakdown-tile-pages " title = { @ tab_labels [ @ active_tab ] } connected? = { @ connected? } >
106+ < Tile . tile id = "breakdown-tile-pages " title = { @ key_labels [ @ active_tab ] } connected? = { @ connected? } >
38107 <: tabs >
39108 < Tile . tab
40109 :for = { { value , label } <- @ tabs }
@@ -45,23 +114,113 @@ defmodule PlausibleWeb.Live.Dashboard.Pages do
45114 />
46115 </: tabs >
47116
48- < div class = "mx-auto font-medium text-gray-500 dark:text-gray-400 " >
49- < Base . dashboard_link site = { @ site } href = "?f=is,source,Direct / None " >
50- Filter by source Direct / None
51- </ Base . dashboard_link >
52- </ div >
117+ < ReportList . report
118+ site = { @ site }
119+ key_label = { @ key_labels [ @ active_tab ] }
120+ filter_dimension = { @ filter_dimensions [ @ active_tab ] }
121+ params = { @ params }
122+ results = { @ results }
123+ meta = { @ meta }
124+ metrics = { @ metrics }
125+ external_link_fn = { @ external_link_fn }
126+ />
53127 </ Tile . tile >
54128 </ div >
55129 """
56130 end
57131
58132 def handle_event ( "set-tab" , % { "tab" => tab } , socket ) do
59133 if tab != socket . assigns . active_tab do
60- socket = assign ( socket , :active_tab , tab )
134+ socket =
135+ socket
136+ |> assign ( :active_tab , tab )
137+ |> load_metrics ( )
61138
62139 { :noreply , socket }
63140 else
64141 { :noreply , socket }
65142 end
66143 end
144+
145+ defp external_link ( _item ) do
146+ "https://example.com"
147+ end
148+
149+ defp load_metrics ( socket ) do
150+ % { results: pages , meta: meta , metrics: metrics } =
151+ metrics_for_tab ( socket . assigns . active_tab , socket . assigns . site , socket . assigns . query )
152+
153+ assign (
154+ socket ,
155+ metrics: Enum . map ( metrics , & Map . fetch! ( @ metrics [ socket . assigns . active_tab ] , & 1 ) ) ,
156+ results: Enum . take ( pages , @ max_items ) ,
157+ meta: Map . merge ( meta , Stats.Breakdown . formatted_date_ranges ( socket . assigns . query ) ) ,
158+ skip_imported_reason: meta [ :imports_skip_reason ]
159+ )
160+ end
161+
162+ defp metrics_for_tab ( "pages" , site , query ) do
163+ query = struct! ( query , dimensions: [ "event:page" ] )
164+
165+ metrics = breakdown_metrics ( query )
166+
167+ % { results: results , meta: meta } = Stats . breakdown ( site , query , metrics , @ pagination_params )
168+
169+ pages =
170+ results
171+ |> transform_keys ( % { page: :name } )
172+
173+ % { results: pages , meta: meta , metrics: metrics }
174+ end
175+
176+ defp metrics_for_tab ( "entry-pages" , site , query ) do
177+ query = struct! ( query , dimensions: [ "visit:entry_page" ] )
178+
179+ metrics = breakdown_metrics ( query )
180+
181+ % { results: results , meta: meta } = Stats . breakdown ( site , query , metrics , @ pagination_params )
182+
183+ pages =
184+ results
185+ |> transform_keys ( % { entry_page: :name } )
186+
187+ % { results: pages , meta: meta , metrics: metrics }
188+ end
189+
190+ defp metrics_for_tab ( "exit-pages" , site , query ) do
191+ query = struct! ( query , dimensions: [ "visit:exit_page" ] )
192+
193+ metrics = breakdown_metrics ( query )
194+
195+ % { results: results , meta: meta } = Stats . breakdown ( site , query , metrics , @ pagination_params )
196+
197+ pages =
198+ results
199+ |> transform_keys ( % { exit_page: :name } )
200+
201+ % { results: pages , meta: meta , metrics: metrics }
202+ end
203+
204+ defp breakdown_metrics ( query ) do
205+ if toplevel_goal_filter? ( query ) do
206+ [ :visitors , :conversion_rate ]
207+ else
208+ [ :visitors ]
209+ end
210+ end
211+
212+ defp transform_keys ( result , keys_to_replace ) when is_map ( result ) do
213+ for { key , val } <- result , do: { Map . get ( keys_to_replace , key , key ) , val } , into: % { }
214+ end
215+
216+ defp transform_keys ( results , keys_to_replace ) when is_list ( results ) do
217+ Enum . map ( results , & transform_keys ( & 1 , keys_to_replace ) )
218+ end
219+
220+ defp toplevel_goal_filter? ( query ) do
221+ Filters . filtering_on_dimension? ( query , "event:goal" ,
222+ max_depth: 0 ,
223+ behavioral_filters: :ignore
224+ )
225+ end
67226end
0 commit comments