ahoy_captain 0.82 → 0.91

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -13
  3. data/app/assets/javascript/ahoy_captain/controllers/active_links_controller.js +6 -3
  4. data/app/assets/javascript/ahoy_captain/controllers/filter/item_controller.js +12 -0
  5. data/app/assets/javascript/ahoy_captain/controllers/line_chart_controller.js +4 -4
  6. data/app/assets/javascript/ahoy_captain/controllers/toggle_controller.js +17 -0
  7. data/app/components/ahoy_captain/dropdown_button_component.html.erb +5 -5
  8. data/app/components/ahoy_captain/dropdown_link_component.html.erb +5 -5
  9. data/app/components/ahoy_captain/filter/dropdown_component.html.erb +48 -0
  10. data/app/components/ahoy_captain/filter/dropdown_component.rb +51 -0
  11. data/app/components/ahoy_captain/filter/modal_component.html.erb +2 -2
  12. data/app/components/ahoy_captain/filter/select_component.html.erb +3 -3
  13. data/app/components/ahoy_captain/filter/select_component.rb +22 -8
  14. data/app/components/ahoy_captain/filter/tag_component.html.erb +8 -4
  15. data/app/components/ahoy_captain/filter/tag_component.rb +6 -30
  16. data/app/components/ahoy_captain/filter/tag_container_component.html.erb +2 -3
  17. data/app/components/ahoy_captain/filter/tag_container_component.rb +1 -8
  18. data/app/components/ahoy_captain/stats/container_component.html.erb +8 -0
  19. data/app/components/ahoy_captain/stats/container_component.rb +12 -0
  20. data/app/components/ahoy_captain/sticky_nav_component.html.erb +7 -19
  21. data/app/components/ahoy_captain/sticky_nav_component.rb +8 -0
  22. data/app/components/ahoy_captain/table_component.html.erb +2 -2
  23. data/app/components/ahoy_captain/table_component.rb +3 -0
  24. data/app/components/ahoy_captain/tables/headers/goals_header_component.html.erb +1 -1
  25. data/app/components/ahoy_captain/tables/headers/header_component.html.erb +1 -1
  26. data/app/components/ahoy_captain/tables/rows/goals_row_component.html.erb +1 -1
  27. data/app/components/ahoy_captain/tables/rows/goals_row_component.rb +8 -0
  28. data/app/components/ahoy_captain/tables/rows/row_component.rb +2 -2
  29. data/app/components/ahoy_captain/tile_component.html.erb +4 -3
  30. data/app/components/ahoy_captain/tile_component.rb +1 -1
  31. data/app/components/ahoy_captain/tooltip_component.html.erb +2 -2
  32. data/app/controllers/ahoy_captain/filters/sources_controller.rb +1 -1
  33. data/app/controllers/ahoy_captain/stats/base_controller.rb +3 -3
  34. data/app/helpers/ahoy_captain/application_helper.rb +33 -0
  35. data/app/models/ahoy_captain/filter_parser.rb +67 -0
  36. data/app/presenters/ahoy_captain/goals_presenter.rb +3 -2
  37. data/app/queries/ahoy_captain/stats/average_views_per_visit_query.rb +1 -1
  38. data/app/queries/ahoy_captain/stats/visit_duration_query.rb +1 -1
  39. data/app/views/ahoy_captain/funnels/show.html.erb +5 -2
  40. data/app/views/ahoy_captain/layouts/application.html.erb +3 -3
  41. data/app/views/ahoy_captain/realtimes/show.html.erb +1 -1
  42. data/app/views/ahoy_captain/roots/_filters.html.erb +34 -0
  43. data/app/views/ahoy_captain/roots/show.html.erb +19 -89
  44. data/app/views/ahoy_captain/stats/base/index.html.erb +4 -3
  45. data/app/views/ahoy_captain/stats/show.html.erb +7 -52
  46. data/lib/ahoy_captain/ahoy/event_methods.rb +12 -3
  47. data/lib/ahoy_captain/ahoy/visit_methods.rb +1 -1
  48. data/lib/ahoy_captain/configuration.rb +16 -6
  49. data/lib/ahoy_captain/engine.rb +17 -0
  50. data/lib/ahoy_captain/filter_configuration/filter.rb +16 -0
  51. data/lib/ahoy_captain/filter_configuration/filter_collection.rb +48 -0
  52. data/lib/ahoy_captain/filters_configuration.rb +73 -0
  53. data/lib/ahoy_captain/goals.rb +1 -1
  54. data/lib/ahoy_captain/predicate_label.rb +7 -0
  55. data/lib/ahoy_captain/version.rb +1 -1
  56. data/lib/ahoy_captain.rb +1 -0
  57. data/lib/generators/ahoy_captain/templates/config.rb.tt +25 -0
  58. metadata +14 -2
@@ -1,9 +1,10 @@
1
1
  require 'ahoy_captain/period_collection'
2
+ require 'ahoy_captain/filters_configuration'
2
3
 
3
4
  module AhoyCaptain
4
5
  class Configuration
5
6
  attr_accessor :view_name, :theme
6
- attr_reader :goals, :funnels, :cache, :ranges, :disabled_widgets, :event, :models
7
+ attr_reader :goals, :funnels, :cache, :ranges, :disabled_widgets, :event, :models, :filters, :predicate_labels
7
8
  def initialize
8
9
  @goals = GoalCollection.new
9
10
  @funnels = FunnelCollection.new
@@ -14,15 +15,24 @@ module AhoyCaptain
14
15
  option.store = Rails.cache
15
16
  option.ttl = 1.minute
16
17
  end
17
- @event = ActiveSupport::OrderedOptions.new.tap do |option|
18
- option.view_name = "$view"
19
- option.url_column = "CONCAT(ahoy_events.properties->>'controller', '#', ahoy_events.properties->>'action')"
20
- option.url_exists = "JSONB_EXISTS(ahoy_events.properties, 'controller') AND JSONB_EXISTS(ahoy_events.properties, 'action')"
21
- end
22
18
  @models = ActiveSupport::OrderedOptions.new.tap do |option|
23
19
  option.event = "::Ahoy::Event"
24
20
  option.visit = "::Ahoy::Visit"
25
21
  end
22
+ @event = ActiveSupport::OrderedOptions.new.tap do |option|
23
+ option.view_name = "$view"
24
+ option.url_column = "CONCAT(#{@models.event.parameterize.tableize}.properties->>'controller', '#', #{@models.event.parameterize.tableize}.properties->>'action')"
25
+ option.url_exists = "JSONB_EXISTS(#{@models.event.parameterize.tableize}.properties, 'controller') AND JSONB_EXISTS(#{@models.event.parameterize.tableize}.properties, 'action')"
26
+ end
27
+ @filters = FiltersConfiguration.load_default
28
+ @predicate_labels = {
29
+ eq: 'equals',
30
+ not_eq: 'not equals',
31
+ cont: 'contains',
32
+ in: 'in',
33
+ not_in: 'not in',
34
+ }
35
+
26
36
  @disabled_widgets = []
27
37
  end
28
38
 
@@ -8,6 +8,23 @@ require 'groupdate'
8
8
  require 'pagy'
9
9
  require 'zip'
10
10
 
11
+ module Ransack
12
+ module Nodes
13
+ class Condition
14
+
15
+ # allows for sql from a formatter
16
+ # see https://github.com/activerecord-hackery/ransack/issues/702
17
+ def casted_array?(predicate)
18
+ return unless predicate.is_a?(Arel::Nodes::Casted)
19
+
20
+ predicate.value.is_a?(Array)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+
11
28
  module AhoyCaptain
12
29
  class Engine < Rails::Engine
13
30
  isolate_namespace ::AhoyCaptain
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,48 @@
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
@@ -0,0 +1,73 @@
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 Tag") 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]
39
+ end
40
+ end
41
+ end
42
+
43
+ def initialize
44
+ @registry = {}
45
+ end
46
+
47
+ def register(label, &block)
48
+ item = FilterConfiguration::FilterCollection.new(label)
49
+ item.instance_exec(&block)
50
+ @registry[label] = item
51
+ end
52
+
53
+ def [](val)
54
+ @registry[val]
55
+ end
56
+
57
+ def delete(name)
58
+ @registry.delete(name)
59
+ end
60
+
61
+ def reset
62
+ @registry = {}
63
+ end
64
+
65
+ def each(&block)
66
+ @registry.each(&block)
67
+ end
68
+
69
+ def detect(&block)
70
+ @registry.detect(&block)
71
+ end
72
+ end
73
+ end
@@ -33,7 +33,7 @@ module AhoyCaptain
33
33
  include Enumerable
34
34
 
35
35
  def initialize
36
- @goals = {}
36
+ @goals = {}.with_indifferent_access
37
37
  end
38
38
 
39
39
  def register(goal)
@@ -0,0 +1,7 @@
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,3 +1,3 @@
1
1
  module AhoyCaptain
2
- VERSION = "0.82"
2
+ VERSION = "0.91"
3
3
  end
data/lib/ahoy_captain.rb CHANGED
@@ -4,6 +4,7 @@ require "ahoy_captain/engine"
4
4
  require "ahoy_captain/goals"
5
5
  require "ahoy_captain/funnels"
6
6
  require "ahoy_captain/configuration"
7
+ require "ahoy_captain/predicate_label"
7
8
  require 'ahoy_captain/ahoy/visit_methods'
8
9
  require 'ahoy_captain/ahoy/event_methods'
9
10
 
@@ -81,6 +81,31 @@ AhoyCaptain.configure do |config|
81
81
  # Set to false to disable custom ranges
82
82
  # config.ranges.custom = true
83
83
 
84
+ # ==> Filters
85
+ #
86
+ # Defaults come from lib/ahoy_captain/filter_configuration.rb
87
+ #
88
+ # If you want your own entirely, first call reset.
89
+ # config.filters.reset
90
+ #
91
+ # Then you can add your own.
92
+ #
93
+ # config.filters.register "Group label" do
94
+ # filter label: "Some label", column: :column_name, url: :url_for_options, predicates: [:in, :not_in], multiple: true
95
+ # end
96
+ #
97
+ # You can also remove an existing group:
98
+ #
99
+ # config.filters.delete("Group label")
100
+ #
101
+ # Remove a specific filter from a group:
102
+ #
103
+ # config.filters["Group label"].delete(:column_name)
104
+ #
105
+ # You can add to an existing group:
106
+ #
107
+ # config.filters["Group label"].filter label: "Some label", column: :column_name, url: :url_for_options, predicates: [:in, :not_in], multiple: true
108
+
84
109
  # ==> Caching
85
110
  # config.cache.enabled = false
86
111
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_captain
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.82'
4
+ version: '0.91'
5
5
  platform: ruby
6
6
  authors:
7
7
  - joshmn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-04 00:00:00.000000000 Z
11
+ date: 2023-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -283,6 +283,7 @@ files:
283
283
  - app/assets/javascript/ahoy_captain/controllers/application_controller.js
284
284
  - app/assets/javascript/ahoy_captain/controllers/details_modal_controller.js
285
285
  - app/assets/javascript/ahoy_captain/controllers/dropdown_label_controller.js
286
+ - app/assets/javascript/ahoy_captain/controllers/filter/item_controller.js
286
287
  - app/assets/javascript/ahoy_captain/controllers/filter_form_controller.js
287
288
  - app/assets/javascript/ahoy_captain/controllers/filter_tag_controller.js
288
289
  - app/assets/javascript/ahoy_captain/controllers/funnel_chart_controller.js
@@ -292,11 +293,14 @@ files:
292
293
  - app/assets/javascript/ahoy_captain/controllers/predicate_select_controller.js
293
294
  - app/assets/javascript/ahoy_captain/controllers/realtime_controller.js
294
295
  - app/assets/javascript/ahoy_captain/controllers/search_select_controller.js
296
+ - app/assets/javascript/ahoy_captain/controllers/toggle_controller.js
295
297
  - app/assets/manifest/ahoy_captain/manifest.js
296
298
  - app/components/ahoy_captain/dropdown_button_component.html.erb
297
299
  - app/components/ahoy_captain/dropdown_button_component.rb
298
300
  - app/components/ahoy_captain/dropdown_link_component.html.erb
299
301
  - app/components/ahoy_captain/dropdown_link_component.rb
302
+ - app/components/ahoy_captain/filter/dropdown_component.html.erb
303
+ - app/components/ahoy_captain/filter/dropdown_component.rb
300
304
  - app/components/ahoy_captain/filter/modal_component.html.erb
301
305
  - app/components/ahoy_captain/filter/modal_component.rb
302
306
  - app/components/ahoy_captain/filter/select_component.html.erb
@@ -305,6 +309,8 @@ files:
305
309
  - app/components/ahoy_captain/filter/tag_component.rb
306
310
  - app/components/ahoy_captain/filter/tag_container_component.html.erb
307
311
  - app/components/ahoy_captain/filter/tag_container_component.rb
312
+ - app/components/ahoy_captain/stats/container_component.html.erb
313
+ - app/components/ahoy_captain/stats/container_component.rb
308
314
  - app/components/ahoy_captain/sticky_nav_component.html.erb
309
315
  - app/components/ahoy_captain/sticky_nav_component.rb
310
316
  - app/components/ahoy_captain/table_component.html.erb
@@ -373,6 +379,7 @@ files:
373
379
  - app/decorators/ahoy_captain/top_page_decorator.rb
374
380
  - app/helpers/ahoy_captain/application_helper.rb
375
381
  - app/models/ahoy_captain/export.rb
382
+ - app/models/ahoy_captain/filter_parser.rb
376
383
  - app/models/ahoy_captain/rangeable.rb
377
384
  - app/models/ahoy_captain/widget.rb
378
385
  - app/models/concerns/ahoy_captain/range_options.rb
@@ -419,6 +426,7 @@ files:
419
426
  - app/views/ahoy_captain/realtimes/show.html.erb
420
427
  - app/views/ahoy_captain/regions/index.html+details.erb
421
428
  - app/views/ahoy_captain/regions/index.html.erb
429
+ - app/views/ahoy_captain/roots/_filters.html.erb
422
430
  - app/views/ahoy_captain/roots/show.html.erb
423
431
  - app/views/ahoy_captain/sources/index.html+details.erb
424
432
  - app/views/ahoy_captain/sources/index.html.erb
@@ -433,9 +441,13 @@ files:
433
441
  - lib/ahoy_captain/ahoy/visit_methods.rb
434
442
  - lib/ahoy_captain/configuration.rb
435
443
  - lib/ahoy_captain/engine.rb
444
+ - lib/ahoy_captain/filter_configuration/filter.rb
445
+ - lib/ahoy_captain/filter_configuration/filter_collection.rb
446
+ - lib/ahoy_captain/filters_configuration.rb
436
447
  - lib/ahoy_captain/funnels.rb
437
448
  - lib/ahoy_captain/goals.rb
438
449
  - lib/ahoy_captain/period_collection.rb
450
+ - lib/ahoy_captain/predicate_label.rb
439
451
  - lib/ahoy_captain/railtie.rb
440
452
  - lib/ahoy_captain/version.rb
441
453
  - lib/generators/ahoy_captain/install_generator.rb