ruby_cms 0.2.0.5 → 0.2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/app/components/ruby_cms/admin/bulk_action_table/bulk_action_table.rb +9 -1
  4. data/app/components/ruby_cms/admin/bulk_action_table/bulk_action_table_actions.rb +3 -3
  5. data/app/components/ruby_cms/admin/bulk_action_table/bulk_action_table_delete_modal.rb +8 -8
  6. data/app/components/ruby_cms/admin/bulk_action_table/bulk_action_table_header_bar.rb +15 -5
  7. data/app/components/ruby_cms/admin/bulk_action_table/bulk_actions.rb +57 -12
  8. data/app/controllers/concerns/ruby_cms/page_tracking.rb +15 -0
  9. data/app/controllers/ruby_cms/admin/analytics_controller.rb +12 -0
  10. data/app/controllers/ruby_cms/admin/commands_controller.rb +6 -6
  11. data/app/javascript/controllers/ruby_cms/bulk_action_table_controller.js +65 -13
  12. data/app/services/ruby_cms/analytics/report.rb +119 -7
  13. data/app/services/ruby_cms/command_runner.rb +3 -3
  14. data/app/views/ruby_cms/admin/analytics/index.html.erb +160 -67
  15. data/app/views/ruby_cms/admin/analytics/partials/_browser_device.html.erb +21 -15
  16. data/app/views/ruby_cms/admin/analytics/partials/_daily_activity_chart.html.erb +36 -16
  17. data/app/views/ruby_cms/admin/analytics/partials/_hourly_activity_chart.html.erb +29 -13
  18. data/app/views/ruby_cms/admin/analytics/partials/_landing_pages.html.erb +27 -15
  19. data/app/views/ruby_cms/admin/analytics/partials/_os_stats.html.erb +29 -18
  20. data/app/views/ruby_cms/admin/analytics/partials/_popular_pages.html.erb +17 -12
  21. data/app/views/ruby_cms/admin/analytics/partials/_recent_activity.html.erb +25 -14
  22. data/app/views/ruby_cms/admin/analytics/partials/_top_referrers.html.erb +27 -15
  23. data/app/views/ruby_cms/admin/analytics/partials/_top_visitors.html.erb +20 -10
  24. data/app/views/ruby_cms/admin/analytics/partials/_utm_sources.html.erb +27 -15
  25. data/app/views/ruby_cms/admin/content_blocks/index.html.erb +8 -1
  26. data/config/locales/en.yml +69 -5
  27. data/config/locales/nl.yml +98 -0
  28. data/lib/generators/ruby_cms/install_generator.rb +21 -6
  29. data/lib/generators/ruby_cms/templates/ruby_cms.rb +40 -3
  30. data/lib/ruby_cms/settings_registry.rb +35 -0
  31. data/lib/ruby_cms/version.rb +1 -1
  32. metadata +1 -1
@@ -57,10 +57,22 @@ en:
57
57
  settings:
58
58
  title: "Settings"
59
59
  subtitle: "Configure admin interface preferences"
60
+ categories_title: "Sections"
61
+ form_hint: "Toggles save immediately; other fields use Save below."
62
+ save_hint: "Toggles autosave; text fields need Save."
63
+ save_changes: "Save changes"
60
64
  pagination: "Pagination"
61
65
  pagination_description: "Number of items to display per page in each table"
62
66
  navigation: "Navigation"
63
67
  navigation_description: "Control which pages appear in the navigation menu"
68
+ navigation_title: "Navigation"
69
+ navigation_hint: "Reorder items or choose what appears in the sidebar."
70
+ nav_order_tab: "Order"
71
+ nav_items_tab: "Visibility"
72
+ drag_hint: "Drag to reorder"
73
+ show_in_sidebar: "Show in sidebar"
74
+ show_in_sidebar_hint: "Turn sections on or off. Changes save when you toggle."
75
+ no_nav_items: "No items to configure here."
64
76
  nav_order_label: "Menu order"
65
77
  nav_order_hint: "Drag items to reorder the sidebar menu."
66
78
  general: "General"
@@ -73,6 +85,44 @@ en:
73
85
  no_settings: "No settings in this category"
74
86
  commands_page_hint: "Registered rake tasks (Commands) are not a tab on this screen. Open “Commands” in the left sidebar under “Settings”, or use the link below."
75
87
  commands_open_link: "Open Commands"
88
+ categories:
89
+ general:
90
+ label: "General"
91
+ description: "General preferences for the admin environment."
92
+ navigation:
93
+ label: "Navigation"
94
+ description: "Control sidebar order and visibility."
95
+ pagination:
96
+ label: "Pagination"
97
+ description: "Define default table page sizes."
98
+ analytics:
99
+ label: "Analytics"
100
+ description: "Adjust analytics-related display settings."
101
+ dashboard:
102
+ label: "Dashboard"
103
+ description: "Configure dashboard widgets and defaults."
104
+ content:
105
+ label: "Content"
106
+ description: "Tune content editing and publishing preferences."
107
+ bulk_action_table:
108
+ selected: "selected"
109
+ select_all: "Select all"
110
+ clear: "Clear"
111
+ close: "Close"
112
+ confirm: "Confirm"
113
+ processing: "Processing..."
114
+ delete_selected_items: "Delete Selected Items"
115
+ delete_selected: "Delete Selected"
116
+ delete_selected_confirm: "Are you sure you want to delete the selected items? This action cannot be undone."
117
+ are_you_sure_you_want_to_delete_the_selected_items: "Are you sure you want to delete the selected items?"
118
+ this_action_cannot_be_undone: "This action cannot be undone."
119
+ cancel: "Cancel"
120
+ select_at_least_one: "Please select at least one item."
121
+ item_id_not_found: "Item ID not found for deletion."
122
+ delete_path_not_found: "Delete path not found."
123
+ action_url_not_configured: "Action URL not configured. Please configure an action URL for this page."
124
+ default_confirm: "Are you sure you want to proceed?"
125
+ generic_action_error: "An error occurred while performing %{action}."
76
126
  analytics:
77
127
  title: "Analytics"
78
128
  subtitle: "Traffic and engagement overview"
@@ -80,14 +130,28 @@ en:
80
130
  back_to_analytics: "Back to analytics"
81
131
  page_details_title: "Page details"
82
132
  visitor_details_title: "Visitor details"
83
- total_page_views: "Total page views"
84
- unique_visitors: "Unique visitors"
85
- total_sessions: "Total sessions"
86
- popular_pages: "Popular pages"
87
- top_visitors: "Top visitors"
133
+ total_page_views: "Page Views"
134
+ unique_visitors: "Unique Visitors"
135
+ total_sessions: "Sessions"
136
+ bounce_rate: "Bounce Rate"
137
+ popular_pages: "Popular Pages"
138
+ top_visitors: "Top Visitors"
88
139
  suspicious_activity: "Suspicious activity"
89
140
  none_detected: "None detected in selected range."
90
141
  no_data: "No data yet."
142
+ exit_pages: "Exit Pages"
143
+ exit_pages_subtitle: "Last page viewed per session."
144
+ conversions: "Conversions"
145
+ conversions_subtitle: "Goals tracked via ahoy.track in your app."
146
+ conversions_total: "Total"
147
+ conversions_by_goal: "By goal"
148
+ no_conversions: "No conversions recorded."
149
+ no_conversions_hint: "Track goals with ahoy.track \"%{event}\", goal: \"your_goal\" in your controllers."
150
+ period_vs_previous: "vs previous period"
151
+ no_exit_pages: "No exit page data available."
152
+ page: "Page"
153
+ no_activity: "No activity recorded"
154
+ no_referrers: "No referrers recorded"
91
155
  visitor_errors:
92
156
  title: "Visitor errors"
93
157
  item_name: "error"
@@ -44,13 +44,111 @@ nl:
44
44
  unknown: "Onbekend commando."
45
45
  right_column_label: "Commando-resultaat en applicatielog"
46
46
  settings:
47
+ title: "Instellingen"
48
+ subtitle: "Beheerinterface-voorkeuren configureren"
49
+ categories_title: "Secties"
50
+ form_hint: "Schakelaars slaan direct op; andere velden gebruik je met Opslaan."
51
+ save_hint: "Schakelaars slaan automatisch op; tekstvelden vereisen Opslaan."
52
+ save_changes: "Wijzigingen opslaan"
53
+ pagination: "Paginering"
54
+ pagination_description: "Aantal items per pagina in elke tabel"
55
+ navigation: "Navigatie"
56
+ navigation_description: "Bepaal welke pagina's in het navigatiemenu verschijnen"
57
+ navigation_title: "Navigatie"
58
+ navigation_hint: "Herschik items of kies wat in de zijbalk verschijnt."
59
+ nav_order_tab: "Volgorde"
60
+ nav_items_tab: "Zichtbaarheid"
61
+ drag_hint: "Sleep om te herschikken"
62
+ show_in_sidebar: "Toon in zijbalk"
63
+ show_in_sidebar_hint: "Zet secties aan of uit. Wijzigingen slaan op bij toggelen."
64
+ no_nav_items: "Geen items om hier in te stellen."
65
+ nav_order_label: "Menuvolgorde"
66
+ nav_order_hint: "Wijzigingen worden automatisch opgeslagen als je een item verplaatst."
67
+ general: "Algemeen"
68
+ updated: "Instelling '%{key}' is bijgewerkt."
69
+ defaults_reset: "Alle instellingen zijn teruggezet naar de standaardwaarden."
70
+ reset_defaults: "Standaardwaarden herstellen"
71
+ reset_defaults_short: "Herstel standaard"
72
+ reset_inline_hint: "Herstel fabrieksinstellingen voor de hele admin (alle secties)."
73
+ reset_confirm: "Alle instellingen terugzetten naar standaardwaarden?"
74
+ no_settings: "Geen instellingen in deze categorie"
47
75
  commands_page_hint: "Geregistreerde Rake-taken (Commando's) staan niet als tab op dit scherm. Open «Commando's» in de linkerzijbalk onder het kopje Instellingen, of gebruik de link hieronder."
48
76
  commands_open_link: "Commando's openen"
77
+ categories:
78
+ general:
79
+ label: "Algemeen"
80
+ description: "Algemene voorkeuren voor de beheeromgeving."
81
+ navigation:
82
+ label: "Navigatie"
83
+ description: "Beheer de volgorde en zichtbaarheid van de zijbalk."
84
+ pagination:
85
+ label: "Paginering"
86
+ description: "Stel standaard paginagroottes voor tabellen in."
87
+ analytics:
88
+ label: "Analytics"
89
+ description: "Pas analytics-gerelateerde weergave-instellingen aan."
90
+ dashboard:
91
+ label: "Dashboard"
92
+ description: "Configureer dashboard-widgets en standaardwaarden."
93
+ content:
94
+ label: "Inhoud"
95
+ description: "Stel voorkeuren voor bewerken en publiceren in."
96
+ bulk_action_table:
97
+ selected: "geselecteerd"
98
+ select_all: "Alles selecteren"
99
+ clear: "Wissen"
100
+ close: "Sluiten"
101
+ confirm: "Bevestigen"
102
+ processing: "Verwerken..."
103
+ delete_selected_items: "Geselecteerde items verwijderen"
104
+ delete_selected: "Geselecteerde verwijderen"
105
+ delete_selected_confirm: "Weet je zeker dat je de geselecteerde items wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt."
106
+ are_you_sure_you_want_to_delete_the_selected_items: "Weet je zeker dat je de geselecteerde items wilt verwijderen?"
107
+ this_action_cannot_be_undone: "Deze actie kan niet ongedaan worden gemaakt."
108
+ cancel: "Annuleren"
109
+ select_at_least_one: "Selecteer minimaal een item."
110
+ item_id_not_found: "Item-ID voor verwijderen niet gevonden."
111
+ delete_path_not_found: "Verwijderpad niet gevonden."
112
+ action_url_not_configured: "Actie-URL is niet ingesteld. Configureer een actie-URL voor deze pagina."
113
+ default_confirm: "Weet je zeker dat je wilt doorgaan?"
114
+ generic_action_error: "Er is een fout opgetreden tijdens het uitvoeren van %{action}."
115
+ analytics:
116
+ title: "Analytics"
117
+ subtitle: "Verkeer- en betrokkenheidoverzicht"
118
+ apply_filters: "Toepassen"
119
+ back_to_analytics: "Terug naar analytics"
120
+ page_details_title: "Paginadetails"
121
+ visitor_details_title: "Bezoekersdetails"
122
+ total_page_views: "Paginaweergaven"
123
+ unique_visitors: "Unieke bezoekers"
124
+ total_sessions: "Sessies"
125
+ bounce_rate: "Bouncepercentage"
126
+ popular_pages: "Populaire pagina's"
127
+ top_visitors: "Top bezoekers"
128
+ suspicious_activity: "Verdachte activiteit"
129
+ none_detected: "Niets gedetecteerd in de geselecteerde periode."
130
+ no_data: "Nog geen gegevens."
131
+ exit_pages: "Uitstappagina's"
132
+ exit_pages_subtitle: "Laatste bekeken pagina per sessie."
133
+ conversions: "Conversies"
134
+ conversions_subtitle: "Doelen bijgehouden via ahoy.track in je app."
135
+ conversions_total: "Totaal"
136
+ conversions_by_goal: "Per doel"
137
+ no_conversions: "Geen conversies geregistreerd."
138
+ no_conversions_hint: "Houd doelen bij met ahoy.track \"%{event}\", goal: \"jouw_doel\" in je controllers."
139
+ period_vs_previous: "t.o.v. vorige periode"
140
+ no_exit_pages: "Geen uitstappagina-gegevens beschikbaar."
141
+ page: "Pagina"
142
+ no_activity: "Geen activiteit geregistreerd"
143
+ no_referrers: "Geen verwijzers geregistreerd"
49
144
  content_blocks:
50
145
  created: "Contentblok aangemaakt."
51
146
  updated: "Contentblok bijgewerkt."
52
147
  deleted: "Contentblok verwijderd."
148
+ locale_read_only: "(taal kan niet worden gewijzigd voor bestaande blokken)"
53
149
  select_locale: "Selecteer taal"
150
+ edit_in_locale: "Bewerken in %{locale_name}"
151
+ other_languages: "Andere talen"
54
152
  content_type: "Inhoudstype"
55
153
  title: "Titel"
56
154
  content: "Inhoud"
@@ -28,6 +28,9 @@ module RubyCms
28
28
  - Visitor errors: Automatically captured via ApplicationController (see /admin/visitor_errors)
29
29
  - Page views (Ahoy): Include RubyCms::PageTracking in your public controllers to track page views
30
30
  Example: class PagesController < ApplicationController; include RubyCms::PageTracking; end
31
+ - Conversions: Call ahoy.track RubyCms::Analytics::Report::EVENT_CONVERSION, goal: "contact_form"
32
+ from any controller action (e.g. after a successful form submit). Goal names are free-form strings.
33
+ - Bot filtering: Set config.ruby_cms.analytics_visit_scope to exclude IPs/bots (see config/initializers/ruby_cms.rb)
31
34
  - Analytics: View visit/event data in Ahoy tables (ahoy_visits, ahoy_events)
32
35
  TEXT
33
36
 
@@ -870,19 +873,16 @@ module RubyCms
870
873
  # Remove RubyCMS-specific Tailwind source globs to keep host-app builds fast.
871
874
  # Not a generator task.
872
875
  def remove_ruby_cms_tailwind_source(tailwind_css_path)
873
- return unless tailwind_css_path.to_s.present? && File.exist?(tailwind_css_path)
876
+ return unless valid_tailwind_source_path?(tailwind_css_path)
874
877
 
875
878
  content = File.read(tailwind_css_path)
876
879
  cleaned_content = remove_legacy_ruby_cms_tailwind_sources(content)
877
880
  return if cleaned_content == content
878
881
 
879
882
  File.write(tailwind_css_path, cleaned_content)
880
- say "✓ Task tailwind/source: Removed RubyCMS @source paths from tailwind entry CSS.",
881
- :green
883
+ say_tailwind_source_cleaned
882
884
  rescue StandardError => e
883
- say "⚠ Task tailwind/source: Could not clean @source lines: #{e.message}. " \
884
- "Check tailwind/application.css manually.",
885
- :yellow
885
+ say_tailwind_source_clean_failed(e)
886
886
  end
887
887
 
888
888
  # Remove RubyCMS content globs from Tailwind v3 config as well.
@@ -905,6 +905,21 @@ module RubyCms
905
905
  .gsub(%r{^\s*/\*\s*Include RubyCMS views/components so Tailwind finds utility classes\.\s*\*/\s*$\n?}, "")
906
906
  .gsub(/^\s*@source\s+"[^"\n]*ruby_cms[^"\n]*";\s*$\n?/i, "")
907
907
  end
908
+
909
+ def valid_tailwind_source_path?(tailwind_css_path)
910
+ tailwind_css_path.to_s.present? && File.exist?(tailwind_css_path)
911
+ end
912
+
913
+ def say_tailwind_source_cleaned
914
+ say "✓ Task tailwind/source: Removed RubyCMS @source paths from tailwind entry CSS.",
915
+ :green
916
+ end
917
+
918
+ def say_tailwind_source_clean_failed(error)
919
+ say "⚠ Task tailwind/source: Could not clean @source lines: #{error.message}. " \
920
+ "Check tailwind/application.css manually.",
921
+ :yellow
922
+ end
908
923
  end
909
924
 
910
925
  def run_migrate
@@ -49,10 +49,30 @@ RubyCms.configure do |c|
49
49
  # Preview data proc to pass instance variables.
50
50
  # c.preview_data = ->(page_key, view) { { products: Product.limit(5) } }
51
51
 
52
- # Optional hook: customize Ahoy visit scope (e.g. exclude internal traffic)
53
- # c.analytics_visit_scope = ->(scope) { scope.where.not(ip: ["127.0.0.1"]) }
52
+ # Optional hook: filter Ahoy visits before analytics queries run.
53
+ # Use this to exclude known bots, internal IPs, or staging traffic.
54
+ # Examples (combine as needed):
55
+ #
56
+ # Exclude localhost + internal subnets:
57
+ # c.analytics_visit_scope = ->(scope) {
58
+ # scope.where.not(ip: %w[127.0.0.1 ::1])
59
+ # .where("ip NOT LIKE '10.%'")
60
+ # .where("ip NOT LIKE '192.168.%'")
61
+ # }
62
+ #
63
+ # Exclude Ahoy's built-in bot detection (requires Ahoy.bot_detection_enabled = true
64
+ # in config/initializers/ahoy.rb, which sets user_agent on the visit):
65
+ # c.analytics_visit_scope = ->(scope) {
66
+ # scope.where("user_agent NOT REGEXP ?", Ahoy::BOT_AGENTS.join("|"))
67
+ # }
68
+ #
69
+ # Simple IP-based staging exclusion:
70
+ # INTERNAL_IPS = %w[127.0.0.1 ::1].freeze
71
+ # c.analytics_visit_scope = ->(scope) { scope.where.not(ip: INTERNAL_IPS) }
72
+ #
73
+ # c.analytics_visit_scope = ->(scope) { scope.where.not(ip: ["127.0.0.1", "::1"]) }
54
74
 
55
- # Optional hook: customize Ahoy event scope
75
+ # Optional hook: customize Ahoy event scope (e.g. exclude events from certain visits)
56
76
  # c.analytics_event_scope = ->(scope) { scope }
57
77
 
58
78
  # Optional hook: provide extra dashboard cards
@@ -60,6 +80,23 @@ RubyCms.configure do |c|
60
80
  # [{ title: "Custom KPI", value: visits_scope.where.not(utm_source: nil).count }]
61
81
  # end
62
82
 
83
+ # Conversion tracking: track goals from host app controllers or form handlers.
84
+ # Use the EVENT_CONVERSION constant to stay consistent with the analytics dashboard.
85
+ # Example in a controller action (after a successful form submit):
86
+ #
87
+ # def create
88
+ # if @contact.save
89
+ # ahoy.track RubyCms::Analytics::Report::EVENT_CONVERSION,
90
+ # goal: "contact_form", path: request.path
91
+ # redirect_to success_path
92
+ # else
93
+ # render :new
94
+ # end
95
+ # end
96
+ #
97
+ # Goal names are free-form strings; keep them consistent so the dashboard groups them.
98
+ # Recommended goal names: "contact_form", "newsletter_signup", "registration", "purchase"
99
+
63
100
  # -----------------------------------------------------------------------------
64
101
  # Optional bootstrap values (initializer -> DB import, once)
65
102
  #
@@ -166,6 +166,41 @@ module RubyCms
166
166
  category: :analytics,
167
167
  description: "Events shown on visitor details screen"
168
168
  )
169
+ register(
170
+ key: :analytics_max_exit_pages,
171
+ type: :integer,
172
+ default: 10,
173
+ category: :analytics,
174
+ description: "Maximum number of exit pages to show"
175
+ )
176
+ register(
177
+ key: :analytics_max_conversions,
178
+ type: :integer,
179
+ default: 10,
180
+ category: :analytics,
181
+ description: "Maximum number of conversion goals to show in breakdown"
182
+ )
183
+ register(
184
+ key: :analytics_max_referrers,
185
+ type: :integer,
186
+ default: 10,
187
+ category: :analytics,
188
+ description: "Maximum number of top referrers to show"
189
+ )
190
+ register(
191
+ key: :analytics_max_landing_pages,
192
+ type: :integer,
193
+ default: 10,
194
+ category: :analytics,
195
+ description: "Maximum number of top landing pages to show"
196
+ )
197
+ register(
198
+ key: :analytics_max_utm_sources,
199
+ type: :integer,
200
+ default: 10,
201
+ category: :analytics,
202
+ description: "Maximum number of UTM sources to show"
203
+ )
169
204
 
170
205
  # Dashboard
171
206
  register(
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyCms
4
- VERSION = "0.2.0.5"
4
+ VERSION = "0.2.0.8"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.5
4
+ version: 0.2.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Codebyjob