ahoy_captain 0.11.1 → 0.76

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -25
  3. data/Rakefile +2 -23
  4. data/app/assets/javascript/ahoy_captain/application.js +4 -4
  5. data/app/assets/javascript/ahoy_captain/controllers/application.js +5 -5
  6. data/app/assets/javascript/ahoy_captain/controllers/application_controller.js +8 -27
  7. data/app/assets/javascript/ahoy_captain/controllers/details_modal_controller.js +5 -5
  8. data/app/assets/javascript/ahoy_captain/controllers/dropdown_label_controller.js +2 -2
  9. data/app/assets/javascript/ahoy_captain/controllers/filter_controller.js +145 -0
  10. data/app/assets/javascript/ahoy_captain/controllers/filter_tag_controller.js +17 -0
  11. data/app/assets/javascript/ahoy_captain/controllers/funnel_chart_controller.js +127 -113
  12. data/app/assets/javascript/ahoy_captain/controllers/index.js +3 -4
  13. data/app/assets/javascript/ahoy_captain/controllers/link_controller.js +43 -0
  14. data/app/assets/javascript/ahoy_captain/controllers/navigation_controller.js +25 -0
  15. data/app/assets/javascript/ahoy_captain/controllers/realtime_controller.js +9 -12
  16. data/app/components/ahoy_captain/dropdown_button_component.html.erb +5 -5
  17. data/app/components/ahoy_captain/dropdown_link_component.html.erb +7 -5
  18. data/app/components/ahoy_captain/dropdown_link_component.rb +0 -4
  19. data/app/components/ahoy_captain/filter/modal_component.html.erb +9 -12
  20. data/app/components/ahoy_captain/filter/select_component.html.erb +19 -23
  21. data/app/components/ahoy_captain/filter/select_component.rb +9 -41
  22. data/app/components/ahoy_captain/filter/tag_component.html.erb +4 -8
  23. data/app/components/ahoy_captain/filter/tag_component.rb +30 -6
  24. data/app/components/ahoy_captain/filter/tag_container_component.html.erb +3 -2
  25. data/app/components/ahoy_captain/filter/tag_container_component.rb +8 -1
  26. data/app/components/ahoy_captain/sticky_nav_component.html.erb +33 -28
  27. data/app/components/ahoy_captain/sticky_nav_component.rb +0 -19
  28. data/app/components/ahoy_captain/table_component.html.erb +37 -4
  29. data/app/components/ahoy_captain/table_component.rb +5 -25
  30. data/app/components/ahoy_captain/tile_component.html.erb +10 -21
  31. data/app/components/ahoy_captain/tile_component.rb +2 -10
  32. data/app/components/ahoy_captain/tooltip_component.html.erb +2 -2
  33. data/app/controllers/ahoy_captain/application_controller.rb +30 -23
  34. data/app/controllers/ahoy_captain/campaigns_controller.rb +10 -2
  35. data/app/controllers/ahoy_captain/cities_controller.rb +24 -0
  36. data/app/controllers/ahoy_captain/countries_controller.rb +24 -0
  37. data/app/controllers/ahoy_captain/devices_controller.rb +6 -3
  38. data/app/controllers/ahoy_captain/entry_pages_controller.rb +4 -2
  39. data/app/controllers/ahoy_captain/exit_pages_controller.rb +4 -3
  40. data/app/controllers/ahoy_captain/filters/base_controller.rb +3 -1
  41. data/app/controllers/ahoy_captain/filters/pages/actions_controller.rb +1 -1
  42. data/app/controllers/ahoy_captain/filters/pages/entry_pages_controller.rb +3 -3
  43. data/app/controllers/ahoy_captain/filters/pages/exit_pages_controller.rb +3 -2
  44. data/app/controllers/ahoy_captain/filters/sources_controller.rb +1 -1
  45. data/app/controllers/ahoy_captain/filters/utms_controller.rb +1 -1
  46. data/app/controllers/ahoy_captain/realtimes_controller.rb +1 -1
  47. data/app/controllers/ahoy_captain/regions_controller.rb +24 -0
  48. data/app/controllers/ahoy_captain/sources_controller.rb +5 -2
  49. data/app/controllers/ahoy_captain/stats/base_controller.rb +0 -142
  50. data/app/controllers/ahoy_captain/stats/bounce_rates_controller.rb +2 -4
  51. data/app/controllers/ahoy_captain/stats/total_pageviews_controller.rb +1 -2
  52. data/app/controllers/ahoy_captain/stats/total_visits_controller.rb +1 -2
  53. data/app/controllers/ahoy_captain/stats/unique_visitors_controller.rb +1 -3
  54. data/app/controllers/ahoy_captain/stats/views_per_visits_controller.rb +8 -3
  55. data/app/controllers/ahoy_captain/stats/visit_durations_controller.rb +1 -2
  56. data/app/controllers/ahoy_captain/top_pages_controller.rb +8 -2
  57. data/app/decorators/ahoy_captain/application_decorator.rb +3 -27
  58. data/app/decorators/ahoy_captain/campaign_decorator.rb +0 -8
  59. data/app/decorators/ahoy_captain/city_decorator.rb +0 -12
  60. data/app/decorators/ahoy_captain/country_decorator.rb +0 -10
  61. data/app/decorators/ahoy_captain/device_decorator.rb +2 -13
  62. data/app/decorators/ahoy_captain/page_decorator.rb +0 -11
  63. data/app/decorators/ahoy_captain/region_decorator.rb +0 -16
  64. data/app/decorators/ahoy_captain/source_decorator.rb +0 -7
  65. data/app/helpers/ahoy_captain/application_helper.rb +3 -60
  66. data/app/models/ahoy_captain/current.rb +9 -0
  67. data/app/models/ahoy_captain/rangeable.rb +3 -0
  68. data/app/models/ahoy_captain/url_helpers.rb +6 -0
  69. data/app/models/concerns/ahoy_captain/range_options.rb +14 -1
  70. data/app/presenters/ahoy_captain/dashboard_presenter.rb +46 -18
  71. data/app/presenters/ahoy_captain/funnel_presenter.rb +29 -32
  72. data/app/presenters/ahoy_captain/goals_presenter.rb +23 -33
  73. data/app/queries/ahoy_captain/application_query.rb +13 -81
  74. data/app/queries/ahoy_captain/entry_pages_query.rb +2 -3
  75. data/app/queries/ahoy_captain/event_query.rb +8 -30
  76. data/app/queries/ahoy_captain/exit_pages_query.rb +4 -6
  77. data/app/queries/ahoy_captain/stats/average_views_per_visit_query.rb +4 -11
  78. data/app/queries/ahoy_captain/stats/average_visit_duration_query.rb +7 -15
  79. data/app/queries/ahoy_captain/stats/bounce_rates_query.rb +7 -24
  80. data/app/queries/ahoy_captain/stats/total_pageviews_query.rb +2 -2
  81. data/app/queries/ahoy_captain/stats/total_visitors_query.rb +2 -2
  82. data/app/queries/ahoy_captain/stats/unique_visitors_query.rb +2 -2
  83. data/app/queries/ahoy_captain/stats/views_per_visit_query.rb +3 -3
  84. data/app/queries/ahoy_captain/stats/visit_duration_query.rb +5 -5
  85. data/app/queries/ahoy_captain/visit_query.rb +13 -12
  86. data/app/views/ahoy_captain/devices/index.html+details.erb +1 -1
  87. data/app/views/ahoy_captain/devices/index.html.erb +2 -2
  88. data/app/views/ahoy_captain/funnels/show.html.erb +2 -5
  89. data/app/views/ahoy_captain/goals/index.html.erb +37 -2
  90. data/app/views/ahoy_captain/layouts/application.html.erb +4 -3
  91. data/app/views/ahoy_captain/realtimes/show.html.erb +1 -1
  92. data/app/views/ahoy_captain/roots/show.html.erb +118 -117
  93. data/app/views/ahoy_captain/stats/base/index.html.erb +1 -38
  94. data/app/views/ahoy_captain/stats/show.html.erb +56 -14
  95. data/config/routes.rb +3 -16
  96. data/lib/ahoy_captain/ahoy/event_methods.rb +75 -36
  97. data/lib/ahoy_captain/ahoy/visit_methods.rb +1 -1
  98. data/lib/ahoy_captain/configuration.rb +7 -18
  99. data/lib/ahoy_captain/engine.rb +0 -22
  100. data/lib/ahoy_captain/goals.rb +4 -16
  101. data/lib/ahoy_captain/period_collection.rb +1 -1
  102. data/lib/ahoy_captain/version.rb +1 -1
  103. data/lib/ahoy_captain.rb +1 -8
  104. data/lib/generators/ahoy_captain/templates/config.rb.tt +3 -50
  105. metadata +17 -185
  106. data/app/assets/javascript/ahoy_captain/controllers/combobox_controller.js +0 -371
  107. data/app/assets/javascript/ahoy_captain/controllers/filter/item_controller.js +0 -12
  108. data/app/assets/javascript/ahoy_captain/controllers/filter_form_controller.js +0 -13
  109. data/app/assets/javascript/ahoy_captain/controllers/filter_modal_controller.js +0 -45
  110. data/app/assets/javascript/ahoy_captain/controllers/frame_link_controller.js +0 -20
  111. data/app/assets/javascript/ahoy_captain/controllers/interval_controller.js +0 -15
  112. data/app/assets/javascript/ahoy_captain/controllers/line_chart_controller.js +0 -251
  113. data/app/assets/javascript/ahoy_captain/controllers/map_controller.js +0 -47
  114. data/app/assets/javascript/ahoy_captain/controllers/predicate_select_controller.js +0 -10
  115. data/app/assets/javascript/ahoy_captain/controllers/properties_controller.js +0 -8
  116. data/app/assets/javascript/ahoy_captain/controllers/property_filter_controller.js +0 -45
  117. data/app/assets/javascript/ahoy_captain/controllers/tile_controller.js +0 -33
  118. data/app/assets/javascript/ahoy_captain/controllers/toggle_controller.js +0 -17
  119. data/app/assets/javascript/ahoy_captain/helpers/chart_utils.js +0 -156
  120. data/app/assets/javascript/ahoy_captain/helpers/countries.js +0 -2261
  121. data/app/assets/javascript/ahoy_captain/helpers/number_formatters.js +0 -55
  122. data/app/components/ahoy_captain/combobox_component.html.erb +0 -33
  123. data/app/components/ahoy_captain/combobox_component.rb +0 -13
  124. data/app/components/ahoy_captain/comparison_link_component.html.erb +0 -17
  125. data/app/components/ahoy_captain/comparison_link_component.rb +0 -44
  126. data/app/components/ahoy_captain/filter/dropdown_component.html.erb +0 -50
  127. data/app/components/ahoy_captain/filter/dropdown_component.rb +0 -51
  128. data/app/components/ahoy_captain/previous_next_component.html.erb +0 -8
  129. data/app/components/ahoy_captain/previous_next_component.rb +0 -11
  130. data/app/components/ahoy_captain/stats/comparable_container_component.html.erb +0 -25
  131. data/app/components/ahoy_captain/stats/comparable_container_component.rb +0 -86
  132. data/app/components/ahoy_captain/stats/container_component.html.erb +0 -15
  133. data/app/components/ahoy_captain/stats/container_component.rb +0 -26
  134. data/app/components/ahoy_captain/tables/devices_table_component.rb +0 -11
  135. data/app/components/ahoy_captain/tables/dynamic_table.rb +0 -13
  136. data/app/components/ahoy_captain/tables/dynamic_table_component.rb +0 -204
  137. data/app/components/ahoy_captain/tables/goals_table_component.rb +0 -17
  138. data/app/components/ahoy_captain/tables/header_component.html.erb +0 -5
  139. data/app/components/ahoy_captain/tables/header_component.rb +0 -18
  140. data/app/components/ahoy_captain/tables/headers/header_component.html.erb +0 -5
  141. data/app/components/ahoy_captain/tables/headers/header_component.rb +0 -16
  142. data/app/components/ahoy_captain/tables/properties_table_component.rb +0 -27
  143. data/app/components/ahoy_captain/tables/row_component.html.erb +0 -4
  144. data/app/components/ahoy_captain/tables/rows/row_component.html.erb +0 -6
  145. data/app/components/ahoy_captain/tables/rows/row_component.rb +0 -40
  146. data/app/controllers/ahoy_captain/exports_controller.rb +0 -14
  147. data/app/controllers/ahoy_captain/filters/goals_controller.rb +0 -9
  148. data/app/controllers/ahoy_captain/filters/properties/names_controller.rb +0 -11
  149. data/app/controllers/ahoy_captain/filters/properties/values_controller.rb +0 -15
  150. data/app/controllers/ahoy_captain/locations/cities_controller.rb +0 -22
  151. data/app/controllers/ahoy_captain/locations/countries_controller.rb +0 -22
  152. data/app/controllers/ahoy_captain/locations/maps_controller.rb +0 -24
  153. data/app/controllers/ahoy_captain/locations/regions_controller.rb +0 -22
  154. data/app/controllers/ahoy_captain/properties_controller.rb +0 -41
  155. data/app/models/ahoy_captain/comparison_mode.rb +0 -72
  156. data/app/models/ahoy_captain/export.rb +0 -48
  157. data/app/models/ahoy_captain/filter_parser.rb +0 -82
  158. data/app/models/ahoy_captain/range_from_params.rb +0 -78
  159. data/app/models/concerns/ahoy_captain/compare_mode.rb +0 -19
  160. data/app/models/concerns/ahoy_captain/limitable.rb +0 -17
  161. data/app/queries/ahoy_captain/campaign_query.rb +0 -14
  162. data/app/queries/ahoy_captain/city_query.rb +0 -11
  163. data/app/queries/ahoy_captain/country_query.rb +0 -10
  164. data/app/queries/ahoy_captain/device_query.rb +0 -10
  165. data/app/queries/ahoy_captain/region_query.rb +0 -11
  166. data/app/queries/ahoy_captain/source_query.rb +0 -10
  167. data/app/queries/ahoy_captain/stats/base_query.rb +0 -18
  168. data/app/queries/ahoy_captain/top_page_query.rb +0 -13
  169. data/app/queries/concerns/ahoy_captain/comparable_queries.rb +0 -25
  170. data/app/queries/concerns/ahoy_captain/comparable_query.rb +0 -138
  171. data/app/queries/concerns/ahoy_captain/lazy_comparable_query.rb +0 -42
  172. data/app/views/ahoy_captain/devices/_table.html.erb +0 -2
  173. data/app/views/ahoy_captain/layouts/shared/_tile_loader.html.erb +0 -12
  174. data/app/views/ahoy_captain/locations/maps/show.html.erb +0 -3
  175. data/app/views/ahoy_captain/properties/_form.html.erb +0 -6
  176. data/app/views/ahoy_captain/properties/index.html.erb +0 -3
  177. data/app/views/ahoy_captain/properties/show.html.erb +0 -6
  178. data/app/views/ahoy_captain/roots/_filters.html.erb +0 -80
  179. data/lib/ahoy_captain/filter_configuration/filter.rb +0 -16
  180. data/lib/ahoy_captain/filter_configuration/filter_collection.rb +0 -48
  181. data/lib/ahoy_captain/filters_configuration.rb +0 -77
  182. data/lib/ahoy_captain/predicate_label.rb +0 -7
  183. data/lib/generators/ahoy_captain/migration_generator.rb +0 -21
  184. data/lib/generators/ahoy_captain/templates/migration.rb.tt +0 -7
  185. /data/app/views/ahoy_captain/{locations/cities → cities}/index.html+details.erb +0 -0
  186. /data/app/views/ahoy_captain/{locations/cities → cities}/index.html.erb +0 -0
  187. /data/app/views/ahoy_captain/{locations/countries → countries}/index.html+details.erb +0 -0
  188. /data/app/views/ahoy_captain/{locations/countries → countries}/index.html.erb +0 -0
  189. /data/app/views/ahoy_captain/{locations/regions → regions}/index.html+details.erb +0 -0
  190. /data/app/views/ahoy_captain/{locations/regions → regions}/index.html.erb +0 -0
@@ -1,11 +0,0 @@
1
- module AhoyCaptain
2
- class CityQuery < ApplicationQuery
3
- def build
4
- visit_query
5
- .select("city, country, count(concat(city, region, country)) as count, sum(count(concat(city, region, country))) over() as total_count")
6
- .where.not(city: nil)
7
- .group("city, region, country")
8
- .order(Arel.sql "count(concat(city, region, country)) desc")
9
- end
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- module AhoyCaptain
2
- class CountryQuery < ApplicationQuery
3
- def build
4
- visit_query
5
- .reselect("country as label, count(country) as count, sum(count(country)) OVER() as total_count")
6
- .group("country")
7
- .order("count(country) desc")
8
- end
9
- end
10
- end
@@ -1,10 +0,0 @@
1
- module AhoyCaptain
2
- class DeviceQuery < ApplicationQuery
3
- def build
4
- visit_query
5
- .select("#{params[:devices_type]} as label", "count(#{params[:devices_type]}) as count", "sum(count(#{params[:devices_type]})) over() as total_count")
6
- .group(params[:devices_type])
7
- .order("count(#{params[:devices_type]}) desc")
8
- end
9
- end
10
- end
@@ -1,11 +0,0 @@
1
- module AhoyCaptain
2
- class RegionQuery < ApplicationQuery
3
- def build
4
- visit_query
5
- .reselect("region, country, count(concat(region, country)) as count, sum(count(region)) over() as total_count")
6
- .where.not(region: nil)
7
- .group("region, country")
8
- .order(Arel.sql "count(concat(region, country)) desc")
9
- end
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- module AhoyCaptain
2
- class SourceQuery < ApplicationQuery
3
- def build
4
- visit_query.select("substring(referring_domain from '(?:.*://)?(?:www\.)?([^/?]*)') as referring_domain, count(substring(referring_domain from '(?:.*://)?(?:www\.)?([^/?]*)')) as count, sum(count(substring(referring_domain from '(?:.*://)?(?:www\.)?([^/?]*)'))) OVER() as total_count")
5
- .where.not(referring_domain: nil)
6
- .group("substring(referring_domain from '(?:.*://)?(?:www\.)?([^/?]*)')")
7
- .order(Arel.sql "count(substring(referring_domain from '(?:.*://)?(?:www\.)?([^/?]*)')) desc")
8
- end
9
- end
10
- end
@@ -1,18 +0,0 @@
1
- module AhoyCaptain
2
- module Stats
3
- class BaseQuery < ApplicationQuery
4
- include ComparableQuery
5
- include LazyComparableQuery
6
-
7
- protected
8
-
9
- def self.cast_type(column)
10
- ActiveRecord::Type.lookup(::Ahoy::Visit.columns_hash[column.to_s].type)
11
- end
12
-
13
- def self.cast_value(type, value)
14
- type.cast(value)
15
- end
16
- end
17
- end
18
- end
@@ -1,13 +0,0 @@
1
- module AhoyCaptain
2
- class TopPageQuery < ApplicationQuery
3
- def build
4
- event_query.with_routes
5
- .select(
6
- "#{AhoyCaptain.config.event[:url_column]} as url",
7
- "count(*) as count",
8
- "sum(count(*)) over() as total_count"
9
- ).group(Arel.sql ("(#{AhoyCaptain.config.event[:url_column]})"))
10
- .order(Arel.sql("count(#{AhoyCaptain.config.event[:url_column]}) desc"))
11
- end
12
- end
13
- end
@@ -1,25 +0,0 @@
1
- module AhoyCaptain
2
- module ComparableQueries
3
- def compare_range
4
- @compare_range ||= begin
5
- ComparisonMode.new(@params).compared_to_range
6
- end
7
- end
8
-
9
- def range
10
- @range ||= @query.send(:range)
11
- end
12
-
13
- def comparison_params
14
- params = @params.deep_dup
15
- params.delete("period")
16
-
17
- params[:start_date] = compare_range[0]
18
- params[:end_date] = compare_range[1]
19
- params
20
- end
21
- end
22
- end
23
-
24
- require_relative './lazy_comparable_query'
25
- require_relative './comparable_query'
@@ -1,138 +0,0 @@
1
- module AhoyCaptain
2
- module ComparableQuery
3
- class Comparison
4
- class ComparisonResult
5
- attr_reader :current, :compared_to
6
- def initialize(current, compared_to)
7
- @current = current
8
- @compared_to = compared_to
9
- end
10
- end
11
-
12
- def initialize(query)
13
- @query = query
14
- @params = @query.params.deep_dup
15
- @compare = @query.class.call(comparison_params)
16
- @model = @query.all.klass
17
- @query_class = @query.class
18
- end
19
-
20
- def count(column_name = :id)
21
- @operation = :count
22
- @column = column_name
23
- perform_calculations(:count, column_name)
24
-
25
- self
26
- end
27
-
28
- def average(column_name)
29
- @operation = :average
30
- @column = column_name
31
-
32
- perform_calculations(:average, column_name)
33
-
34
- self
35
- end
36
-
37
- def perform_calculations(operation, column_name)
38
- @query = perform_calculation(@query, operation, column_name)
39
- @compare = perform_calculation(@compare, operation, column_name)
40
- end
41
-
42
- def perform_calculation(q, operation, column_name)
43
- operation = operation.to_s.downcase
44
- # If #count is used with #distinct (i.e. `relation.distinct.count`) it is
45
- # considered distinct.
46
- distinct = q.send(:distinct_value)
47
-
48
- if operation == "count"
49
- column_name ||= q.send(:select_for_count)
50
- if column_name == :all
51
- if !distinct
52
- distinct = q.send(:distinct_select?, :select_for_count) if q.group_values.empty?
53
- elsif q.send(:group_values).any? || q.send(:select_values).empty? && q.order_values.empty?
54
- column_name = q.primary_key
55
- end
56
- elsif q.all.send(:distinct_select?, column_name)
57
- distinct = nil
58
- end
59
- end
60
-
61
- if q.group_values.any?
62
- raise "use a subquery"
63
- else
64
- execute_simple_calculation(q, operation, column_name, distinct)
65
- end
66
- end
67
-
68
- def result
69
- result = @model.with(
70
- current: @query.to_sql,
71
- compare: @compare.to_sql
72
- ).select("current, compare").from("current, compare")[0]
73
- type = @query_class.cast_type(@column)
74
-
75
- if result
76
- current = @query_class.cast_value(type, result.current[1...-1])
77
- compare = @query_class.cast_value(type, result.compare[1...-1])
78
- else
79
- current = @query_class.cast_value(type, '0')
80
- compare = @query_class.cast_value(type, '0')
81
- end
82
-
83
- @result = ComparisonResult.new((current), (compare))
84
- end
85
-
86
- def compare_range
87
- @compare_range ||= begin
88
- og_range = range
89
- [og_range[0] - (og_range[1] - og_range[0]), og_range[0]]
90
- end
91
-
92
- end
93
-
94
- def range
95
- @range ||= @query.send(:range)
96
- end
97
-
98
- private
99
-
100
- def execute_simple_calculation(q, operation, column_name, distinct) # :nodoc:
101
- if operation == "count" && (column_name == :all && distinct || q.has_limit_or_offset?)
102
- # Shortcut when limit is zero.
103
- return 0 if q.limit_value == 0
104
-
105
- q.send(:build_count_subquery, q.spawn, column_name, distinct)
106
- else
107
- # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
108
- relation = q.all.unscope(:order).distinct!(false)
109
-
110
- column = q.all.send(:aggregate_column, column_name)
111
- select_value = q.all.send(:operation_over_aggregate_column, column, operation, distinct)
112
- select_value.distinct = true if operation == "sum" && distinct
113
-
114
- relation.select_values = [select_value]
115
-
116
- relation.arel
117
- end
118
- end
119
-
120
- def comparison_params
121
- params = @params.deep_dup
122
- params.delete("period")
123
-
124
- params[:start_date] = compare_range[0]
125
- params[:end_date] = compare_range[1]
126
- params
127
- end
128
- end
129
-
130
- def with_comparison(enabled = false)
131
- if enabled
132
- Comparison.new(self)
133
- else
134
- self
135
- end
136
- end
137
- end
138
- end
@@ -1,42 +0,0 @@
1
- module AhoyCaptain
2
- module LazyComparableQuery
3
- class LazyComparison
4
- class LazyComparisonResult
5
- attr_accessor :current, :compared_to
6
- end
7
-
8
- include ::AhoyCaptain::ComparableQueries
9
-
10
- def initialize(query)
11
- @query = query
12
- @params = @query.params.deep_dup
13
- @compare = @query.class.call(comparison_params)
14
- end
15
-
16
- def method_missing(name, *args)
17
- perform_operations(name, *args)
18
- end
19
-
20
- def perform_operations(name, *args)
21
- @query = @query.public_send(name, *args)
22
- @compare = @compare.public_send(name, *args)
23
-
24
- self
25
- end
26
-
27
- def result
28
- return @result if @result
29
-
30
- @result = LazyComparisonResult.new.tap { |comparison| comparison.current = @query; comparison.compared_to = @compare }
31
- end
32
- end
33
-
34
- def with_lazy_comparison(enabled = false)
35
- if enabled
36
- LazyComparison.new(self)
37
- else
38
- self
39
- end
40
- end
41
- end
42
- end
@@ -1,2 +0,0 @@
1
- <%= render AhoyCaptain::TableComponent.new(items: @devices,
2
- table: ::AhoyCaptain::Tables::DevicesTableComponent) %>
@@ -1,12 +0,0 @@
1
- <div class="mt-5" >
2
- <div role="status" class="animate-pulse">
3
- <div class="flex justify-between w-full mb-2">
4
- <div class="h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-32"></div>
5
- <div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24"></div>
6
- </div>
7
- <% 10.times do |i| %>
8
- <div class="h-6 bg-gray-200 dark:bg-gray-700 max-w-[<%= 100 - (i * 10) %>%] mb-2.5"></div>
9
- <% end %>
10
- <span class="sr-only">Loading...</span>
11
- </div>
12
- </div>
@@ -1,3 +0,0 @@
1
- <%= turbo_frame_tag :geography do %>
2
- <canvas style="position: relative; width: 500px; height: 300px;" data-controller="map" data-map-data-value="<%= @countries.to_json %>"></canvas>
3
- <% end %>
@@ -1,6 +0,0 @@
1
- <select class="select text-accent select-sm w-full max-w-sm" data-controller="properties" data-action="change->properties#handleChange">
2
- <option></option>
3
- <% @options.each do |key, value| %>
4
- <option value="<%= property_path(id: key) %>" <%= 'selected' if local_assigns[:selected] == value %>><%= value %></option>
5
- <% end %>
6
- </select>
@@ -1,3 +0,0 @@
1
- <%= turbo_frame_tag :goals do %>
2
- <%= render 'ahoy_captain/properties/form' %>
3
- <% end %>
@@ -1,6 +0,0 @@
1
- <%= turbo_frame_tag :goals do %>
2
- <%= render 'ahoy_captain/properties/form', selected: Base64.strict_decode64(params[:id]) %>
3
-
4
- <%= render AhoyCaptain::TableComponent.new(items: @properties,
5
- table: ::AhoyCaptain::Tables::PropertiesTableComponent) %>
6
- <% end %>
@@ -1,80 +0,0 @@
1
- <%= form_with url: url_for(params.permit!.except(:q)), method: :get, data: { turbo_frame: "_top", controller: "filter-form", action: "reset->filter-form#handleReset" } do |form| %>
2
- <% non_filter_ransack_params.each do |k,v| %>
3
- <%= form.hidden_field k, value: v %>
4
- <% end %>
5
- <% AhoyCaptain.config.filters.each do |name, filters| %>
6
- <%= render AhoyCaptain::Filter::ModalComponent.new(title: "Filter by #{name}", id: "#{filters.modal_name}") do |modal| %>
7
- <% modal.with_modal_display do %>
8
- <% filters.each do |filter| %>
9
- <%= render AhoyCaptain::Filter::SelectComponent.new(label: filter.label, column: filter.column, url: public_send(filter.url), predicates: filter.predicates, multiple: filter.multiple, form: form) %>
10
- <% end %>
11
- <% end %>
12
- <% end %>
13
- <% end %>
14
-
15
- <%= render AhoyCaptain::Filter::ModalComponent.new(title: "Filter by Custom Property", id: "customPropertyFilterModal") do |modal| %>
16
- <% modal.with_modal_display do %>
17
- <div data-controller="property-filter">
18
- <fieldset class="flex space-x-4 items-end">
19
- <% if current_property_filter %>
20
- <%= render ::AhoyCaptain::ComboboxComponent.new(name: "", multiple: false, column: "", url: filters_properties_names_path, value: [current_property_filter[:key].delete_prefix("properties.")], select_html: { "data-property-filter-target" => 'name', id: "property-name" }) %>
21
- <% else %>
22
- <%= render ::AhoyCaptain::ComboboxComponent.new(name: "", multiple: false, column: "", url: filters_properties_names_path, select_html: { "data-property-filter-target" => 'name', id: "property-name" } ) %>
23
- <% end %>
24
-
25
- <div class="flex flex-col w-[20%]">
26
- <select class='select select-primary bg-gray-900 ring-0 focus-within:ring-0 focus-within:ring-0 focus:ring-0 focus:outline-none inline-flex justify-between items-center w-full rounded-md border px-4 py-2 text-sm'>
27
- <option value="in">in</option>
28
- </select>
29
- </div>
30
-
31
- <% if current_property_filter %>
32
- <%= render ::AhoyCaptain::ComboboxComponent.new(name: "q[#{current_property_filter[:key]}_in]", multiple: false, column: "", url: filters_properties_values_path, value: [current_property_filter[:value]], select_html: { "data-property-filter-target" => 'value', id: "property-value" } ) %>
33
- <% else %>
34
- <%= render ::AhoyCaptain::ComboboxComponent.new(name: "", multiple: false, column: "", url: filters_properties_values_path, select_html: { "data-property-filter-target" => 'value', id: "property-value" }, disabled: true) %>
35
- <% end %>
36
-
37
- </fieldset>
38
-
39
- </div>
40
- <% end %>
41
- <% end %>
42
-
43
- <%= render AhoyCaptain::Filter::ModalComponent.new(title: "Custom Range", id: "customRangeModal") do |modal| %>
44
- <% modal.with_modal_display do %>
45
- <div class="flex gap-2 w-full">
46
- <div class="form-control w-full max-w-xs">
47
- <label class="label" for="start_date">
48
- <span class="label-text">Start Date</span>
49
- </label>
50
- <input type="datetime-local" id="start_date" name="start_date" class="input input-bordered w-full" value="<%= params[:start_date] %>" />
51
- </div>
52
- <div class="form-control w-full max-w-xs">
53
- <label class="label" for="end_date">
54
- <span class="label-text">End Date</span>
55
- </label>
56
- <input type="datetime-local" id="end_date" name="end_date" class="input input-bordered w-full" value="<%= params[:end_date] %>" />
57
- </div>
58
- </div>
59
- <% end %>
60
- <% end %>
61
-
62
- <%= render AhoyCaptain::Filter::ModalComponent.new(title: "Custom Comparison", id: "customComparisonModal") do |modal| %>
63
- <% modal.with_modal_display do %>
64
- <div class="flex gap-2 w-full">
65
- <div class="form-control w-full max-w-xs">
66
- <label class="label" for="start_date">
67
- <span class="label-text">Start Date</span>
68
- </label>
69
- <input type="datetime-local" id="start_date" name="compare_to_start_date" class="input input-bordered w-full" value="<%= params[:compare_to_start_date] %>" />
70
- </div>
71
- <div class="form-control w-full max-w-xs">
72
- <label class="label" for="end_date">
73
- <span class="label-text">End Date</span>
74
- </label>
75
- <input type="datetime-local" id="end_date" name="compare_to_end_date" class="input input-bordered w-full" value="<%= params[:compare_to_end_date] %>" />
76
- </div>
77
- </div>
78
- <% end %>
79
- <% end %>
80
- <% end %>
@@ -1,16 +0,0 @@
1
- module AhoyCaptain
2
- class FilterConfiguration
3
- class Filter
4
- attr_reader :column, :label, :url, :predicates, :multiple, :position
5
-
6
- def initialize(label:, column:, url:, predicates: [:in, :not_in], multiple: true, position: nil)
7
- @column = column
8
- @label = label
9
- @url = url
10
- @predicates = predicates
11
- @multiple = multiple
12
- @position = position
13
- end
14
- end
15
- end
16
- end
@@ -1,48 +0,0 @@
1
- module AhoyCaptain
2
- class FilterConfiguration
3
- class FilterCollection
4
- def initialize(label)
5
- @label = label
6
- @registry = []
7
- end
8
-
9
- def filter(label:, column:, url:, predicates: [:in, :not_in], multiple: true, position: nil)
10
- position ||= @registry.size
11
- if item = find(column)
12
- @registry.delete(item)
13
- end
14
-
15
- @registry << FilterConfiguration::Filter.new(label: label, column: column, url: url, predicates: predicates, multiple: multiple, position: position)
16
- @registry = @registry.sort_by { |filter| filter.position }
17
- end
18
-
19
- def each(&block)
20
- @registry.each(&block)
21
- end
22
-
23
- def modal_name
24
- "#{@label.parameterize.underscore}Modal"
25
- end
26
-
27
- def find(column)
28
- @registry.find { |filter| filter.column == column.to_sym }
29
- end
30
-
31
- def delete(name)
32
- @registry.delete_if { |filter| filter.column == name }
33
- end
34
-
35
- def filters
36
- @registry
37
- end
38
-
39
- def [](name)
40
- find(name)
41
- end
42
-
43
- def include?(name)
44
- find(name).present?
45
- end
46
- end
47
- end
48
- end
@@ -1,77 +0,0 @@
1
- require 'ahoy_captain/filter_configuration/filter'
2
- require 'ahoy_captain/filter_configuration/filter_collection'
3
-
4
- module AhoyCaptain
5
- class FiltersConfiguration
6
- def self.load_default
7
- new.tap do |config|
8
- config.register("Page") do
9
- filter column: :route, label: "Route", url: :filters_actions_path, predicates: [:in, :not_in]
10
- filter column: :entry_page, label: "Entry Page", url: :filters_entry_pages_path, predicates: [:in, :not_in]
11
- filter column: :exit_page, label: "Exit Page", url: :filters_exit_pages_path, predicates: [:in, :not_in]
12
- end
13
-
14
- config.register("Geography") do
15
- filter column: :country, label: "Country", url: :filters_locations_countries_path, predicates: [:in, :not_in]
16
- filter column: :region, label: "Region", url: :filters_locations_regions_path, predicates: [:in, :not_in]
17
- filter column: :city, label: "City", url: :filters_locations_cities_path, predicates: [:in, :not_in]
18
- end
19
-
20
- config.register("Source") do
21
- filter column: :referring_domain, label: "Source", url: :filters_sources_path, predicates: [:in, :not_in]
22
- end
23
-
24
- config.register("Screen size") do
25
- filter column: :device_type, label: "Screen size", url: :filters_screens_path, predicates: [:in, :not_in]
26
- end
27
-
28
- config.register("Operating System") do
29
- filter column: :os, label: "OS Name", url: :filters_names_path, predicates: [:in, :not_in]
30
- filter column: :os_version, label: "OS Version", url: :filters_versions_path, predicates: [:in, :not_in]
31
- end
32
-
33
- config.register("UTM Tags") do
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
- end
40
-
41
- config.register("Goal") do
42
- filter column: :goal, label: "Goal", url: :filters_goals_path, predicates: [:in]
43
- end
44
- end
45
- end
46
-
47
- def initialize
48
- @registry = {}
49
- end
50
-
51
- def register(label, &block)
52
- item = FilterConfiguration::FilterCollection.new(label)
53
- item.instance_exec(&block)
54
- @registry[label] = item
55
- end
56
-
57
- def [](val)
58
- @registry[val]
59
- end
60
-
61
- def delete(name)
62
- @registry.delete(name)
63
- end
64
-
65
- def reset
66
- @registry = {}
67
- end
68
-
69
- def each(&block)
70
- @registry.each(&block)
71
- end
72
-
73
- def detect(&block)
74
- @registry.detect(&block)
75
- end
76
- end
77
- end
@@ -1,7 +0,0 @@
1
- module AhoyCaptain
2
- class PredicateLabel
3
- def self.[](value)
4
- AhoyCaptain.config.predicate_labels[value.to_sym] || value.to_s.titleize
5
- end
6
- end
7
- end
@@ -1,21 +0,0 @@
1
- require "rails/generators"
2
- require "rails/generators/active_record"
3
-
4
- module AhoyCaptain
5
- module Generators
6
- class MigrationGenerator < Rails::Generators::Base
7
- include ActiveRecord::Generators::Migration
8
- source_root File.join(__dir__, "templates")
9
-
10
- def copy_templates
11
- migration_template "migration.rb", "db/migrate/create_ahoy_captain_indexes.rb", migration_version: migration_version
12
- end
13
-
14
- private
15
-
16
- def migration_version
17
- "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
18
- end
19
- end
20
- end
21
- end
@@ -1,7 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
- def change
3
- add_index :<%= ::AhoyCaptain.visit.table_name %>, :started_at unless index_exists?(:<%= ::AhoyCaptain.visit.table_name %>, :started_at)
4
- add_index :<%= ::AhoyCaptain.event.table_name %>, :visit_id unless index_exists?(:<%= ::AhoyCaptain.event.table_name %>, :visit_id)
5
- add_index :<%= ::AhoyCaptain.event.table_name %>, :time unless index_exists?(:<%= ::AhoyCaptain.event.table_name %>, :time)
6
- end
7
- end