ahoy_captain 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +23 -2
- data/app/assets/javascript/ahoy_captain/controllers/application_controller.js +12 -0
- data/app/assets/javascript/ahoy_captain/controllers/combobox_controller.js +50 -20
- data/app/assets/javascript/ahoy_captain/controllers/frame_link_controller.js +20 -0
- data/app/assets/javascript/ahoy_captain/controllers/line_chart_controller.js +67 -4
- data/app/assets/javascript/ahoy_captain/controllers/map_controller.js +47 -0
- data/app/assets/javascript/ahoy_captain/controllers/predicate_select_controller.js +1 -0
- data/app/assets/javascript/ahoy_captain/helpers/countries.js +2261 -0
- data/app/components/ahoy_captain/combobox_component.html.erb +2 -2
- data/app/components/ahoy_captain/combobox_component.rb +1 -1
- data/app/components/ahoy_captain/dropdown_link_component.html.erb +2 -4
- data/app/components/ahoy_captain/dropdown_link_component.rb +4 -0
- data/app/components/ahoy_captain/previous_next_component.html.erb +8 -0
- data/app/components/ahoy_captain/previous_next_component.rb +11 -0
- data/app/components/ahoy_captain/stats/comparable_container_component.html.erb +1 -1
- data/app/components/ahoy_captain/stats/container_component.html.erb +1 -1
- data/app/components/ahoy_captain/sticky_nav_component.html.erb +26 -22
- data/app/components/ahoy_captain/sticky_nav_component.rb +8 -0
- data/app/components/ahoy_captain/tile_component.rb +7 -0
- data/app/controllers/ahoy_captain/locations/cities_controller.rb +22 -0
- data/app/controllers/ahoy_captain/locations/countries_controller.rb +22 -0
- data/app/controllers/ahoy_captain/locations/maps_controller.rb +24 -0
- data/app/controllers/ahoy_captain/locations/regions_controller.rb +22 -0
- data/app/helpers/ahoy_captain/application_helper.rb +0 -2
- data/app/models/ahoy_captain/range_from_params.rb +4 -0
- data/app/views/ahoy_captain/locations/maps/show.html.erb +3 -0
- data/app/views/ahoy_captain/properties/_form.html.erb +1 -1
- data/app/views/ahoy_captain/roots/show.html.erb +46 -54
- data/app/views/ahoy_captain/stats/base/index.html.erb +1 -0
- data/app/views/ahoy_captain/stats/show.html.erb +11 -6
- data/config/routes.rb +7 -3
- data/lib/ahoy_captain/filters_configuration.rb +5 -5
- data/lib/ahoy_captain/version.rb +1 -1
- data/lib/ahoy_captain.rb +1 -0
- metadata +102 -12
- data/app/assets/javascript/ahoy_captain/controllers/active_links_controller.js +0 -30
- data/app/controllers/ahoy_captain/cities_controller.rb +0 -20
- data/app/controllers/ahoy_captain/countries_controller.rb +0 -20
- data/app/controllers/ahoy_captain/regions_controller.rb +0 -20
- /data/app/views/ahoy_captain/{cities → locations/cities}/index.html+details.erb +0 -0
- /data/app/views/ahoy_captain/{cities → locations/cities}/index.html.erb +0 -0
- /data/app/views/ahoy_captain/{countries → locations/countries}/index.html+details.erb +0 -0
- /data/app/views/ahoy_captain/{countries → locations/countries}/index.html.erb +0 -0
- /data/app/views/ahoy_captain/{regions → locations/regions}/index.html+details.erb +0 -0
- /data/app/views/ahoy_captain/{regions → locations/regions}/index.html.erb +0 -0
@@ -10,7 +10,7 @@
|
|
10
10
|
>
|
11
11
|
<div data-action="click->combobox#toggleOpen" data-combobox-target="box"
|
12
12
|
class="
|
13
|
-
bg-gray-900 ring-0 focus-within:ring-0 focus-within:ring-0 focus:ring-0 focus:outline-none w-full rounded-md
|
13
|
+
bg-gray-900 ring-0 focus-within:ring-0 focus-within:ring-0 focus:ring-0 focus:outline-none w-full rounded-md py-2 text-sm
|
14
14
|
w-full"
|
15
15
|
data-combobox-box-open-class="border-secondary-500 ring-1 ring-secondary-500">
|
16
16
|
<select data-combobox-target="select" style="display:none;"
|
@@ -19,7 +19,7 @@
|
|
19
19
|
id="<%= @select_html[:id] || "filter_#{@name}" %>"
|
20
20
|
<% @select_html.each do |k,v| %><%=k %>="<%=v %>"<% end %>
|
21
21
|
><% @value.each do |value| %><option value="<%= value %>" selected><%= value %></option><% end %></select>
|
22
|
-
<div data-combobox-target="selected" class="" style="display:none;"></div>
|
22
|
+
<div data-combobox-target="selected" class="px-2" style="display:none;"></div>
|
23
23
|
<input data-combobox-target="input"
|
24
24
|
data-action="input->combobox#onInput"
|
25
25
|
class="input input-sm input-ghost w-full inline-block rounded-md focus:outline-none focus:ring-0 focus:bg-gray-900"
|
@@ -1,13 +1,11 @@
|
|
1
|
-
<div class="dropdown dropdown-end
|
1
|
+
<div class="dropdown dropdown-end" data-controller='dropdown-label'>
|
2
2
|
<label
|
3
3
|
tabindex="0"
|
4
4
|
class="cursor-pointer flex <%= classes %>"
|
5
5
|
data-action='click->dropdown-label#removeHidden'
|
6
6
|
>
|
7
7
|
<span data-dropdown-label-target="label"><%= title %></span>
|
8
|
-
|
9
|
-
<path fill="currentColor" d="M16.53 8.97a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06 0l-4-4a.75.75 0 1 1 1.06-1.06L12 12.44l3.47-3.47a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" />
|
10
|
-
</svg>
|
8
|
+
|
11
9
|
</label>
|
12
10
|
<ul class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52" data-dropdown-label-target="close">
|
13
11
|
<% options.each do |option| %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="rounded shadow bg-white cursor-pointer dark:bg-gray-800 flex h-8">
|
2
|
+
<button class="flex items-center px-1 sm:px-2 border-r border-gray-300 rounded-l dark:border-gray-500 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-900" type="button">
|
3
|
+
<svg class="feather h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
4
|
+
</button>
|
5
|
+
<button class="flex items-center px-1 sm:px-2 rounded-r dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-900" type="button">
|
6
|
+
<svg class="feather h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
7
|
+
</button>
|
8
|
+
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<a href="<%= @url %>" class="relative px-4 md:px-6 w-1/2 my-4 w-auto group cursor-pointer"
|
1
|
+
<a href="<%= @url %>" class="relative px-4 md:px-6 w-1/2 my-4 w-auto group cursor-pointer" data-controller="frame-link" data-turbo-frame="chart">
|
2
2
|
<div>
|
3
3
|
<h5 class="text-sm font-bold uppercase whitespace-nowrap flex w-content border-transparent tooltip tooltip-bottom "
|
4
4
|
data-active-links-target="link" data-tip="<%= tooltip %>">
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<a href="<%= @url %>" class="relative px-4 md:px-6 w-1/2 my-4 lg:w-auto group cursor-pointer"
|
1
|
+
<a href="<%= @url %>" class="relative px-4 md:px-6 w-1/2 my-4 lg:w-auto group cursor-pointer" data-controller="frame-link" data-turbo-frame="chart">
|
2
2
|
<div>
|
3
3
|
<h5 class="text-sm font-bold uppercase whitespace-nowrap flex w-content border-transparent tooltip tooltip-bottom "
|
4
4
|
data-active-links-target="link">
|
@@ -1,28 +1,32 @@
|
|
1
|
-
<div class="
|
2
|
-
<div class="flex
|
3
|
-
<
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<div class=" sticky top-0 min-h-sm z-[99999] py-4 bg-base-100 pb-4">
|
2
|
+
<div class="max-w-6xl mx-auto max-w-6xl flex justify-between ">
|
3
|
+
<div class="flex items-center">
|
4
|
+
<a href="/">
|
5
|
+
<img src="<%= image_path "ahoy_captain/logo.png" %>" alt="AhoyCaptainLogo" class='max-h-20 md:h-16 rounded-full'>
|
6
|
+
</a>
|
7
|
+
<% if tag_list_hidden? %>
|
8
|
+
<%= render AhoyCaptain::Filter::TagContainerComponent.new %>
|
9
|
+
<% else %>
|
10
|
+
<%= realtime_update %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
<div class="flex flex-row-reverse col-span-2 items-center gap-3">
|
14
|
+
<%= render AhoyCaptain::ComparisonLinkComponent.new %>
|
15
|
+
<%= render AhoyCaptain::PreviousNextComponent.new(range) %>
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
<%= render AhoyCaptain::DropdownLinkComponent.new(title: params[:start_date] ? custom_range_label : (AhoyCaptain.config.ranges.find(params[:period] || AhoyCaptain.config.ranges.default).try(:label) || "Period"), classes: 'btn btn-sm btn-base-100 no-underline hover:bg-base-100') do |dropdown| %>
|
18
|
+
<% dropdown.with_option do %>
|
19
|
+
<% AhoyCaptain.config.ranges.each do |param, range| %>
|
20
|
+
<a class='link no-underline' href="<%= request.path %>?<%= request.query_parameters.except("start_date", "end_date", "date", "compare_to_start_date", "compare_to_end_date").merge("period" => param).to_query %>"><%= range.label %></a>
|
21
|
+
<% end %>
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
<a class='link no-underline ' href='#' onclick="event.preventDefault(); customRangeModal.showModal()">Custom Range</a>
|
24
|
+
<a class='link no-underline ' href='<%= AhoyCaptain::Engine.routes.url_helpers.root_path(**helpers.search_params.merge(comparison: !compare_mode?)) %>'><%= compare_mode? ? "Disable Comparison" : "Compare" %></a>
|
25
|
+
<% end %>
|
23
26
|
<% end %>
|
24
|
-
<% end %>
|
25
27
|
|
26
|
-
|
28
|
+
<%= render AhoyCaptain::Filter::DropdownComponent.new(filters: filters) %>
|
29
|
+
</div>
|
27
30
|
</div>
|
31
|
+
|
28
32
|
</div>
|
@@ -10,6 +10,14 @@ class AhoyCaptain::StickyNavComponent < ViewComponent::Base
|
|
10
10
|
@filters ||= ::AhoyCaptain::FilterParser.parse(request)
|
11
11
|
end
|
12
12
|
|
13
|
+
def custom_range_label
|
14
|
+
if range.custom?
|
15
|
+
[range.starts_at, range.ends_at].map { |date| date.strftime('%b %d, %Y') }.join("-")
|
16
|
+
else
|
17
|
+
"Custom Range"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
13
21
|
def tag_list_hidden?
|
14
22
|
filters.values.map(&:values).flatten.size < ::AhoyCaptain::FilterParser::FILTER_MENU_MAX_SIZE
|
15
23
|
end
|
@@ -11,6 +11,13 @@ class AhoyCaptain::TileComponent < ViewComponent::Base
|
|
11
11
|
@wide = wide
|
12
12
|
end
|
13
13
|
|
14
|
+
def link_to(name, url, **options)
|
15
|
+
options[:class] = "inline-block h-5 font-semibold"
|
16
|
+
options[:data] ||= {}
|
17
|
+
options[:data].merge!(controller: "frame-link")
|
18
|
+
view_context.link_to name, url, **options
|
19
|
+
end
|
20
|
+
|
14
21
|
private
|
15
22
|
|
16
23
|
attr_reader :title, :wide
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AhoyCaptain
|
2
|
+
module Locations
|
3
|
+
class CitiesController < ApplicationController
|
4
|
+
include AhoyCaptain::Limitable
|
5
|
+
|
6
|
+
before_action do
|
7
|
+
if Widget.disabled?(:locations, :cities)
|
8
|
+
raise Widget::WidgetDisabled.new("Widget disabled", :geography)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
results = cached(:cities) do
|
14
|
+
CityQuery.call(params)
|
15
|
+
.limit(limit)
|
16
|
+
end
|
17
|
+
|
18
|
+
@cities = paginate(results).map { |city| CityDecorator.new(city, self) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AhoyCaptain
|
2
|
+
module Locations
|
3
|
+
class CountriesController < ApplicationController
|
4
|
+
include Limitable
|
5
|
+
|
6
|
+
before_action do
|
7
|
+
if Widget.disabled?(:locations, :countries)
|
8
|
+
raise Widget::WidgetDisabled.new("Widget disabled", :geography)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
results = cached(:countries) do
|
14
|
+
CountryQuery.call(params)
|
15
|
+
.limit(limit)
|
16
|
+
end
|
17
|
+
|
18
|
+
@countries = paginate(results).map { |country| CountryDecorator.new(country, self) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module AhoyCaptain
|
2
|
+
module Locations
|
3
|
+
class MapsController < ApplicationController
|
4
|
+
include Limitable
|
5
|
+
|
6
|
+
before_action do
|
7
|
+
if Widget.disabled?(:locations, :map)
|
8
|
+
raise Widget::WidgetDisabled.new("Widget disabled", :geography)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def show
|
13
|
+
if request.variant.include?(:details)
|
14
|
+
results = CountryQuery.call(params)
|
15
|
+
results = results.limit(limit)
|
16
|
+
@countries = paginate(results).map { |country| CountryDecorator.new(country, self) }
|
17
|
+
render template: 'ahoy_captain/locations/countries/index'
|
18
|
+
else
|
19
|
+
@countries = visit_query.group("country").count
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AhoyCaptain
|
2
|
+
module Locations
|
3
|
+
class RegionsController < ApplicationController
|
4
|
+
include Limitable
|
5
|
+
|
6
|
+
before_action do
|
7
|
+
if Widget.disabled?(:locations, :regions)
|
8
|
+
raise Widget::WidgetDisabled.new("Widget disabled", :geography)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
results = cached(:regions) do
|
14
|
+
RegionQuery.call(params)
|
15
|
+
.limit(limit)
|
16
|
+
end
|
17
|
+
|
18
|
+
@regions = paginate(results).map { |region| RegionDecorator.new(region, self) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<select class="select text-accent-
|
1
|
+
<select class="select text-accent select-sm w-full max-w-sm" data-controller="properties" data-action="change->properties#handleChange">
|
2
2
|
<option></option>
|
3
3
|
<% @options.each do |key, value| %>
|
4
4
|
<option value="<%= property_path(id: key) %>" <%= 'selected' if local_assigns[:selected] == value %>><%= value %></option>
|
@@ -1,15 +1,14 @@
|
|
1
|
-
<main class='
|
1
|
+
<main class='w-screen overflow-hidden' data-action="combobox:init@window->application#comboboxInit">
|
2
2
|
<%= render AhoyCaptain::StickyNavComponent.new do |nav| %>
|
3
3
|
<% nav.with_realtime_update do %>
|
4
4
|
<%= turbo_frame_tag :realtime, src: realtime_path, data: { controller: "realtime", "realtime-interval-value" => AhoyCaptain.config.realtime_interval.to_i }, loading: :lazy %>
|
5
5
|
<% end %>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
-
<div class="grid grid-cols-1 lg:grid-cols-2 grid-flow-row gap-4">
|
8
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 grid-flow-row gap-4 min-h-screen pb-4 max-w-6xl mx-auto">
|
9
9
|
<%= render AhoyCaptain::TileComponent.new(wide: true, classes: "p-4 m-2") do |component| %>
|
10
10
|
<% component.with_statistic_display do %>
|
11
11
|
<%= turbo_frame_tag :stats, src: stats_path(search_params), loading: :lazy %>
|
12
|
-
|
13
12
|
<%= turbo_frame_tag :chart, src: stats_unique_visitors_path(search_params) do %>
|
14
13
|
<% end %>
|
15
14
|
<% end %>
|
@@ -17,21 +16,19 @@
|
|
17
16
|
<% end %>
|
18
17
|
|
19
18
|
<%= render AhoyCaptain::TileComponent.new(title: 'Top Sources') do |component| %>
|
20
|
-
<% component.with_display_links do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
data-active-links-target="link">
|
29
|
-
<%= source.titleize.gsub("Utm", "UTM") %>
|
30
|
-
</a>
|
19
|
+
<% component.with_display_links do %>
|
20
|
+
<div class="flex text-xs font-medium text-gray-400 space-x-2">
|
21
|
+
<div class="relative inline-block text-left">
|
22
|
+
<%= component.link_to "All", sources_path(search_params), data: { turbo_frame: "sources" } %>
|
23
|
+
<%= render AhoyCaptain::DropdownLinkComponent.new(title: "Campaign") do |dropdown| %>
|
24
|
+
<% %w{utm_source utm_medium utm_term utm_content utm_campaign}.each do |source| %>
|
25
|
+
<%= dropdown.link_to source.titleize.gsub("Utm", "UTM"), public_send("campaign_#{source}_path".to_sym, **search_params), data: { turbo_frame: "sources" } %>
|
26
|
+
<% end %>
|
31
27
|
<% end %>
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
|
35
32
|
<% end %>
|
36
33
|
<% component.with_statistic_display do %>
|
37
34
|
<%= turbo_frame_tag :sources, src: sources_path(search_params), loading: :lazy %>
|
@@ -44,14 +41,10 @@
|
|
44
41
|
<%= render AhoyCaptain::TileComponent.new(title: 'Top Pages') do |component| %>
|
45
42
|
<% component.with_display_links do %>
|
46
43
|
<div class="flex text-xs font-medium text-gray-400 space-x-2">
|
47
|
-
<div class="relative inline-block text-left"
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
data-active-links-target="link"
|
52
|
-
data-action="click->tile#setTitle">Top Pages</a>
|
53
|
-
<a href="<%= entry_pages_path(search_params) %>" data-turbo-frame="pages" class="inline-block h-5 font-semibold" data-active-links-target="link" data-action="click->tile#setTitle">Entry Pages</a>
|
54
|
-
<a href="<%= exit_pages_path(search_params) %>" data-turbo-frame="pages" class="inline-block h-5 font-semibold" data-active-links-target="link" data-action="click->tile#setTitle">Exit Pages</a>
|
44
|
+
<div class="relative inline-block text-left"><div>
|
45
|
+
<%= component.link_to "Top Pages", top_pages_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "pages" } %>
|
46
|
+
<%= component.link_to "Entry Pages", entry_pages_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "pages" } %>
|
47
|
+
<%= component.link_to "Exit Pages", exit_pages_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "pages" } %>
|
55
48
|
</div>
|
56
49
|
</div>
|
57
50
|
</div>
|
@@ -65,33 +58,32 @@
|
|
65
58
|
<% end %>
|
66
59
|
<% end %>
|
67
60
|
|
68
|
-
<%= render AhoyCaptain::TileComponent.new(title: '
|
61
|
+
<%= render AhoyCaptain::TileComponent.new(title: 'Map') do |component| %>
|
69
62
|
<% component.with_display_links do %>
|
70
63
|
<div class="flex text-xs font-medium text-gray-400 space-x-2">
|
71
|
-
<div class="relative inline-block text-left"
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
64
|
+
<div class="relative inline-block text-left">
|
65
|
+
<%= component.link_to "Map", locations_map_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "geography" } %>
|
66
|
+
<%= component.link_to "Countries", locations_countries_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "geography" } %>
|
67
|
+
<%= component.link_to "Regions", locations_regions_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "geography" } %>
|
68
|
+
<%= component.link_to "Cities", locations_cities_path(search_params), data: { action: "click->tile#setTitle", turbo_frame: "geography" } %>
|
76
69
|
</div>
|
77
70
|
</div>
|
78
71
|
<% end %>
|
79
72
|
<% component.with_statistic_display do %>
|
80
|
-
<%= turbo_frame_tag :geography, src:
|
73
|
+
<%= turbo_frame_tag :geography, src: locations_map_path(search_params), loading: :lazy %>
|
81
74
|
<% end %>
|
82
75
|
<% component.with_details_cta do %>
|
83
|
-
<button data-action="click->details-modal#openModal" data-controller="details-modal"
|
76
|
+
<button data-action="click->details-modal#openModal" data-controller="details-modal" data-details-modal-target-value="#geography" class="link no-underline ">Details</button>
|
84
77
|
<% end %>
|
85
78
|
<% end %>
|
86
79
|
|
87
80
|
<%= render AhoyCaptain::TileComponent.new(title: 'Devices') do |component| %>
|
88
81
|
<% component.with_display_links do %>
|
89
82
|
<div class="flex text-xs font-medium text-gray-400 space-x-2">
|
90
|
-
<div class="relative inline-block text-left"
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
<a href="<%= devices_device_types_path(search_params) %>" data-turbo-frame="devices" class="inline-block h-5 font-semibold" data-active-links-target="link">Size</a>
|
83
|
+
<div class="relative inline-block text-left">
|
84
|
+
<%= component.link_to "Browser", devices_browsers_path(search_params), data: { turbo_frame: "devices" } %>
|
85
|
+
<%= component.link_to "OS", devices_operating_systems_path(search_params), data: { turbo_frame: "devices" } %>
|
86
|
+
<%= component.link_to "Size", devices_device_types_path(search_params), data: { turbo_frame: "devices" } %>
|
95
87
|
</div>
|
96
88
|
</div>
|
97
89
|
<% end %>
|
@@ -105,23 +97,23 @@
|
|
105
97
|
<%= render AhoyCaptain::TileComponent.new(title: "Goals and Funnels", wide: true, classes: "p-4 m-2") do |component| %>
|
106
98
|
<% component.with_display_links do %>
|
107
99
|
<div>
|
108
|
-
<div
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
</a>
|
100
|
+
<div >
|
101
|
+
<div class="flex text-xs font-medium text-gray-400 space-x-2">
|
102
|
+
<div class="relative inline-block text-left">
|
103
|
+
<a href="<%= goals_path(search_params) %>" data-turbo-frame="goals" class="inline-block h-5 font-semibold" data-controller="frame-link" data-action="click->tile#setTitle">Goals</a>
|
104
|
+
<a href="<%= properties_path(search_params) %>" data-turbo-frame="goals" class="inline-block h-5 font-semibold" data-controller="frame-link" data-action="click->tile#setTitle">Properties</a>
|
105
|
+
<%= render AhoyCaptain::DropdownLinkComponent.new(title: "Funnels") do |dropdown| %>
|
106
|
+
<% AhoyCaptain.config.funnels.each do |id, funnel| %>
|
107
|
+
<% dropdown.with_option do %>
|
108
|
+
<a href="<%= funnel_path(id, search_params) %>" data-turbo-frame="goals" class="link " data-action="click->tile#setTitle" title="<%= funnel.title %> Funnel">
|
109
|
+
<%= funnel.title %>
|
110
|
+
</a>
|
111
|
+
<% end %>
|
112
|
+
<% end %>
|
122
113
|
<% end %>
|
123
|
-
|
124
|
-
|
114
|
+
</div>
|
115
|
+
</div>
|
116
|
+
|
125
117
|
</div>
|
126
118
|
</div>
|
127
119
|
<% end %>
|
@@ -1,10 +1,15 @@
|
|
1
1
|
<%= turbo_frame_tag :stats, data: { controller: "active-frame-link" } do %>
|
2
2
|
<dl class="grid grid-cols-1 divide-y divide-base-200 overflow-hidden rounded-lg grid-cols-2 md:grid-cols-6 md:divide-y-0" data-controller="active-links" data-active-links-classes-value='["text-primary"]'>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
<% if @presenter.send(:range).realtime? %>
|
4
|
+
<%= render stats_container(@presenter.unique_visitors, stats_unique_visitors_url(search_params), "Unique Visits (30 min)", :number_with_delimiter, true) %>
|
5
|
+
<%= render stats_container(@presenter.total_pageviews, stats_total_pageviews_path(search_params), "Total Pageviews (30 min)", :number_with_delimiter) %>
|
6
|
+
<% else %>
|
7
|
+
<%= render stats_container(@presenter.unique_visitors, stats_unique_visitors_url(search_params), "Unique Visits", :number_with_delimiter, true) %>
|
8
|
+
<%= render stats_container(@presenter.total_visits, stats_total_visits_path(search_params), "Total Visits", :number_with_delimiter) %>
|
9
|
+
<%= render stats_container(@presenter.total_pageviews, stats_total_pageviews_path(search_params), "Total Pageviews", :number_with_delimiter) %>
|
10
|
+
<%= render stats_container(@presenter.views_per_visit, stats_views_per_visits_path(search_params), "Views per Visit", :number_with_delimiter) %>
|
11
|
+
<%= render stats_container(@presenter.bounce_rate, stats_bounce_rates_path(search_params), "Bounce Rate", :number_with_delimiter) %>
|
12
|
+
<%= render stats_container(@presenter.visit_duration, stats_visit_durations_url(search_params), "Visit Duration", :number_to_duration) %>
|
13
|
+
<% end %>
|
9
14
|
</dl>
|
10
15
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -12,15 +12,19 @@ AhoyCaptain::Engine.routes.draw do
|
|
12
12
|
get "/devices/#{k}" => 'devices#index', defaults: { devices_type: v }, as: "devices_#{k}"
|
13
13
|
end
|
14
14
|
|
15
|
+
namespace :locations do
|
16
|
+
resource :map, only: [:show]
|
17
|
+
resources :countries, only: [:index]
|
18
|
+
resources :regions, only: [:index]
|
19
|
+
resources :cities, only: [:index]
|
20
|
+
end
|
21
|
+
|
15
22
|
resources :properties, only: [:index, :show]
|
16
23
|
resource :export, only: [:show]
|
17
24
|
resource :realtime, only: [:show]
|
18
25
|
resources :funnels, only: [:show]
|
19
26
|
resources :goals, only: [:index]
|
20
27
|
resource :stats, only: [:show]
|
21
|
-
resources :countries, only: [:index]
|
22
|
-
resources :regions, only: [:index]
|
23
|
-
resources :cities, only: [:index]
|
24
28
|
resources :campaigns, only: [:index]
|
25
29
|
resources :sources, only: [:index]
|
26
30
|
resources :exit_pages, only: [:index]
|
@@ -31,11 +31,11 @@ module AhoyCaptain
|
|
31
31
|
end
|
32
32
|
|
33
33
|
config.register("UTM Tags") do
|
34
|
-
filter column: :utm_medium, label: "UTM Medium", url: :filters_utm_mediums_path, predicates: [:in, :not_in]
|
35
|
-
filter column: :utm_source, label: "UTM Source", url: :filters_utm_sources_path, predicates: [:in, :not_in]
|
36
|
-
filter column: :utm_campaign, label: "UTM Campaign", url: :filters_utm_campaigns_path, predicates: [:in, :not_in]
|
37
|
-
filter column: :utm_term, label: "UTM Term", url: :filters_utm_terms_path, predicates: [:in, :not_in]
|
38
|
-
filter column: :utm_content, label: "UTM Content", url: :filters_utm_contents_path, predicates: [:in, :not_in]
|
34
|
+
filter column: :utm_medium, label: "UTM Medium", url: :filters_utm_mediums_path, predicates: [:in, :not_in, :cont]
|
35
|
+
filter column: :utm_source, label: "UTM Source", url: :filters_utm_sources_path, predicates: [:in, :not_in, :cont]
|
36
|
+
filter column: :utm_campaign, label: "UTM Campaign", url: :filters_utm_campaigns_path, predicates: [:in, :not_in, :cont]
|
37
|
+
filter column: :utm_term, label: "UTM Term", url: :filters_utm_terms_path, predicates: [:in, :not_in, :cont]
|
38
|
+
filter column: :utm_content, label: "UTM Content", url: :filters_utm_contents_path, predicates: [:in, :not_in, :cont]
|
39
39
|
end
|
40
40
|
|
41
41
|
config.register("Goal") do
|
data/lib/ahoy_captain/version.rb
CHANGED
data/lib/ahoy_captain.rb
CHANGED
@@ -32,6 +32,7 @@ module AhoyCaptain
|
|
32
32
|
pin "Chart.bundle", to: "Chart.bundle.js"
|
33
33
|
pin "chartjs-plugin-datalabels", to: "https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2", preload: true
|
34
34
|
pin "classnames", to: "https://cdnjs.cloudflare.com/ajax/libs/classnames/2.3.2/index.min.js", preload: true
|
35
|
+
pin "chartjs-chart-geo", to: "https://unpkg.com/chartjs-chart-geo@4", preload: true
|
35
36
|
pin_all_from AhoyCaptain::Engine.root.join("app/assets/javascript/ahoy_captain/controllers"), under: "controllers", to: "ahoy_captain/controllers"
|
36
37
|
pin_all_from AhoyCaptain::Engine.root.join("app/assets/javascript/ahoy_captain/helpers"), under: "helpers", to: "ahoy_captain/helpers"
|
37
38
|
end
|