koalagator 4.0.0 → 5.0.0

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +661 -0
  3. data/README.md +74 -21
  4. data/app/assets/config/calagator/manifest.js +5 -1
  5. data/app/assets/images/external_sites/mastodon.png +0 -0
  6. data/app/assets/images/nav_marker.png +0 -0
  7. data/app/assets/javascripts/calagator/forms.js +7 -0
  8. data/app/assets/stylesheets/calagator/custom/calendar.css +137 -0
  9. data/app/assets/stylesheets/calagator/errors.css +2 -4
  10. data/app/assets/stylesheets/calagator/forms.scss +5 -0
  11. data/app/assets/stylesheets/calagator/layout.scss +31 -9
  12. data/app/assets/stylesheets/calagator/typography.scss +39 -9
  13. data/app/assets/stylesheets/calagator/utils.scss +44 -0
  14. data/app/controllers/calagator/admin/curations_controller.rb +62 -0
  15. data/app/controllers/calagator/admin/users_controller.rb +79 -0
  16. data/app/controllers/calagator/application_controller.rb +29 -5
  17. data/app/controllers/calagator/curations_controller.rb +32 -0
  18. data/app/controllers/calagator/events_controller.rb +6 -0
  19. data/app/controllers/calagator/paper_trail_manager_controller.rb +5 -0
  20. data/app/controllers/calagator/passwords_controller.rb +4 -0
  21. data/app/controllers/calagator/registrations_controller.rb +5 -0
  22. data/app/controllers/calagator/sessions_controller.rb +4 -0
  23. data/app/controllers/calagator/site_controller.rb +10 -0
  24. data/app/controllers/calagator/sources_controller.rb +2 -0
  25. data/app/controllers/calagator/venues_controller.rb +5 -1
  26. data/app/controllers/calagator/versions_controller.rb +1 -1
  27. data/app/controllers/paper_trail_manager/changes_controller.rb +16 -16
  28. data/app/helpers/calagator/application_helper.rb +32 -3
  29. data/app/helpers/calagator/time_range_helper.rb +1 -1
  30. data/app/helpers/paper_trail_manager/changes_helper.rb +7 -7
  31. data/app/javascript/calagator/calendar/calendar.js +82 -0
  32. data/app/javascript/calagator/calendar/event.js +94 -0
  33. data/app/javascript/calagator/calendar/lib/components.js +120 -0
  34. data/app/javascript/calagator/calendar/lib/utils.js +67 -0
  35. data/app/models/calagator/curation.rb +32 -0
  36. data/app/models/calagator/event/browse.rb +3 -2
  37. data/app/models/calagator/event/cloner.rb +1 -1
  38. data/app/models/calagator/event/ical_renderer.rb +1 -1
  39. data/app/models/calagator/event/overview.rb +3 -1
  40. data/app/models/calagator/event/saver.rb +6 -1
  41. data/app/models/calagator/event/search.rb +1 -1
  42. data/app/models/calagator/event/search_engine.rb +1 -1
  43. data/app/models/calagator/event.rb +22 -5
  44. data/app/models/calagator/source/parser/hcal.rb +1 -1
  45. data/app/models/calagator/source/parser.rb +3 -3
  46. data/app/models/calagator/source.rb +23 -6
  47. data/app/models/calagator/user.rb +50 -0
  48. data/app/models/calagator/venue/geocoder.rb +1 -1
  49. data/app/models/calagator/venue/search.rb +1 -1
  50. data/app/models/calagator/venue/search_engine.rb +1 -1
  51. data/app/models/calagator/venue.rb +20 -1
  52. data/app/models/concerns/calagator/event_filterable.rb +22 -0
  53. data/app/views/calagator/admin/curations/_form.html.erb +56 -0
  54. data/app/views/calagator/admin/curations/_index.html.erb +12 -0
  55. data/app/views/calagator/admin/curations/edit.html.erb +2 -0
  56. data/app/views/calagator/admin/curations/index.html.erb +21 -0
  57. data/app/views/calagator/admin/curations/new.html.erb +2 -0
  58. data/app/views/calagator/admin/index.html.erb +6 -2
  59. data/app/views/calagator/admin/users/_form.html.erb +28 -0
  60. data/app/views/calagator/admin/users/edit.html.erb +7 -0
  61. data/app/views/calagator/admin/users/index.html.erb +38 -0
  62. data/app/views/calagator/admin/users/invite.html.erb +19 -0
  63. data/app/views/calagator/admin/users/new.html.erb +3 -0
  64. data/app/views/calagator/curations/show.html.erb +17 -0
  65. data/app/views/calagator/events/_index.html.erb +59 -0
  66. data/app/views/calagator/events/_item.html.erb +10 -3
  67. data/app/views/calagator/events/_subnav.html.erb +7 -2
  68. data/app/views/calagator/events/_subnav_custom.html.erb +0 -0
  69. data/app/views/calagator/events/index.atom.builder +1 -1
  70. data/app/views/calagator/events/index.html.erb +9 -60
  71. data/app/views/calagator/events/show.html.erb +5 -3
  72. data/app/views/calagator/shared/_calendar.html.erb +7 -0
  73. data/app/views/calagator/shared/_subnav_curations.html.erb +5 -0
  74. data/app/views/calagator/shared/_subnav_pinned_venues.html.erb +5 -0
  75. data/app/views/calagator/site/_contact.html.erb +1 -0
  76. data/app/views/calagator/site/_description.html.erb +2 -2
  77. data/app/views/calagator/site/about.html.erb +9 -0
  78. data/app/views/calagator/site/closed_registrations.html.erb +2 -0
  79. data/app/views/calagator/site/embed.html.erb +16 -0
  80. data/app/views/calagator/site/index.html.erb +1 -1
  81. data/app/views/calagator/sources/index.html.erb +1 -1
  82. data/app/views/calagator/sources/show.html.erb +1 -1
  83. data/app/views/calagator/venues/_form.html.erb +5 -1
  84. data/app/views/calagator/venues/_subnav.html.erb +9 -1
  85. data/app/views/calagator/venues/_subnav_custom.html.erb +0 -0
  86. data/app/views/calagator/venues/show.html.erb +1 -1
  87. data/app/views/layouts/calagator/_devise.html.erb +17 -0
  88. data/app/views/layouts/calagator/_footer.html.erb +3 -1
  89. data/app/views/layouts/calagator/_head.html.erb +0 -0
  90. data/app/views/layouts/calagator/_header.html.erb +3 -0
  91. data/app/views/layouts/calagator/application.html.erb +3 -0
  92. data/app/views/layouts/calagator/embed.html.erb +15 -0
  93. data/app/views/paper_trail_manager/changes/_version.html.erb +5 -5
  94. data/app/views/paper_trail_manager/changes/index.atom.builder +12 -12
  95. data/bin/{calagator → koalagator} +14 -9
  96. data/config/importmap.rb +11 -0
  97. data/config/initializers/admin_user.rb +15 -0
  98. data/config/initializers/observers.rb +1 -1
  99. data/config/initializers/paper_trail_manager.rb +1 -1
  100. data/config/locales/devise.en.yml +65 -0
  101. data/config/routes.rb +26 -1
  102. data/db/migrate/20240319042449_devise_create_calagator_users.rb +43 -0
  103. data/db/migrate/20240319061154_add_admin_flag_to_calagator_user.rb +5 -0
  104. data/db/migrate/20240320043535_add_name_to_calagator_user.rb +8 -0
  105. data/db/migrate/20240322035554_add_created_by_to_records.rb +12 -0
  106. data/db/migrate/20240510051940_create_calagator_curations.rb +15 -0
  107. data/db/migrate/20240628055300_add_pinned_to_venue.rb +5 -0
  108. data/db/seeds.rb +49 -0
  109. data/lib/calagator/decode_html_entities_hack.rb +1 -1
  110. data/lib/calagator/engine.rb +16 -1
  111. data/lib/calagator/machine_tag.rb +1 -1
  112. data/lib/calagator/strip_whitespace.rb +1 -1
  113. data/lib/calagator/vcalendar.rb +4 -4
  114. data/lib/calagator/version.rb +5 -2
  115. data/lib/generators/calagator/install_generator.rb +9 -1
  116. data/lib/generators/calagator/templates/app/views/devise/registrations/edit.html.erb +48 -0
  117. data/lib/generators/calagator/templates/app/views/devise/registrations/new.html.erb +29 -0
  118. data/lib/generators/calagator/templates/config/initializers/01_calagator.rb +34 -6
  119. data/lib/generators/calagator/templates/config/initializers/04_devise.rb +314 -0
  120. data/lib/{calagator.rb → koalagator.rb} +15 -3
  121. data/lib/paper_trail_manager.rb +11 -11
  122. data/lib/theme_reader.rb +1 -1
  123. data/rails_template.rb +6 -6
  124. data/vendor/javascript/@event-calendar--core.js +10 -0
  125. data/vendor/javascript/@event-calendar--day-grid.js +2 -0
  126. data/vendor/javascript/@event-calendar--list.js +2 -0
  127. data/vendor/javascript/ical.js.js +2 -0
  128. metadata +166 -105
  129. data/MIT-LICENSE.txt +0 -23
  130. data/app/models/calagator/event/search_engine/apache_sunspot.rb +0 -106
  131. data/app/models/calagator/venue/search_engine/apache_sunspot.rb +0 -85
  132. data/lib/tasks/sunspot_reindex_calagator.rake +0 -20
  133. data/lib/tasks/sunspot_solr_restart_enhancements.rake +0 -20
  134. data/lib/wait_for_solr.rb +0 -26
@@ -32,6 +32,9 @@
32
32
  <!-- JavaScripts, inserted -->
33
33
  <%= yield :javascript_insert %>
34
34
 
35
+ <!-- Additional head -->
36
+ <%= render partial: "layouts/calagator/head" %>
37
+
35
38
  <!-- Auto-discovery, static -->
36
39
  <%= auto_discovery_link_tag(:atom, events_url(:format => 'atom'), :title => 'Atom: All Events' )%>
37
40
 
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="googlebot" content="noindex,indexifembedded">
7
+
8
+ <%= javascript_importmap_tags %>
9
+ <%= yield :head if content_for?(:head) %>
10
+ </head>
11
+
12
+ <body>
13
+ <%= yield %>
14
+ </body>
15
+ </html>
@@ -5,7 +5,7 @@
5
5
  <div class='time'> <%= version.created_at.strftime('%H:%M:%S') %> </div>
6
6
  </td>
7
7
  <td class='change_details'>
8
- <p class='change_details_description'>
8
+ <span class='change_details_description'>
9
9
  <strong class='event'><%= version.event %></strong>
10
10
  <%= change_item_link(version) %>
11
11
  <% if PaperTrailManager.whodunnit_class && version.whodunnit %>
@@ -19,10 +19,10 @@
19
19
  by <%= version.whodunnit %>
20
20
  <% end %>
21
21
  <% end %>
22
- <% if change_revert_allowed?(version) %>
23
- <%= link_to 'Roll back', change_path(version), :method => 'put', :class => 'rollback', :data => { :confirm => 'Are you sure?' } %>
24
- <% end %>
25
- </p>
22
+ </span>
23
+ <% if change_revert_allowed?(version) %>
24
+ <%= button_to 'Roll back', change_path(version), class: "rollback a-like", form_class: "inline change_details_description", :method => 'put', :data => { :confirm => 'Are you sure?' } %>
25
+ <% end %>
26
26
  <% if version.event == 'update' or version.event == 'create' %>
27
27
  <% changes = changes_for(version) %>
28
28
  <table class='change_details_table'>
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  atom_feed do |feed|
4
- feed.title('Changes')
4
+ feed.title("Changes")
5
5
  date = @versions.first.try(:created_at) || Time.zone.at(0)
6
6
  feed.updated(date)
7
7
 
@@ -12,37 +12,37 @@ atom_feed do |feed|
12
12
  changes = changes_for(version)
13
13
 
14
14
  user = if PaperTrailManager.whodunnit_class && version.whodunnit
15
- begin
15
+ begin
16
16
  PaperTrailManager.whodunnit_class.find(version.whodunnit)
17
- rescue StandardError
18
- nil
17
+ rescue
18
+ nil
19
19
  end
20
- end
20
+ end
21
21
 
22
- entry.title "#{version.event.upcase} #{version.item_type} «#{change_title_for(version)}» #{user ? 'by ' + user.send(PaperTrailManager.whodunnit_name_method) : ''}"
22
+ entry.title "#{version.event.upcase} #{version.item_type} «#{change_title_for(version)}» #{user ? "by " + user.send(PaperTrailManager.whodunnit_name_method) : ""}"
23
23
  entry.updated version.created_at.utc.xmlschema
24
24
 
25
25
  xm = ::Builder::XmlMarkup.new
26
26
  xm.div do
27
27
  xm.p do
28
- xm.span << 'Go to: '
29
- xm.span << link_to('Change', change_url(version))
30
- xm.span << ' | '
31
- xm.span << link_to('Record', change_item_url(version))
28
+ xm.span << "Go to: "
29
+ xm.span << link_to("Change", change_url(version))
30
+ xm.span << " | "
31
+ xm.span << link_to("Record", change_item_url(version))
32
32
  end
33
33
  xm.table do
34
34
  changes.keys.sort.each do |key|
35
35
  xm.tr do
36
36
  xm.td { xm.b key }
37
37
  xm.td changes[key][:previous].inspect
38
- xm.td { xm.span << '&rarr;' }
38
+ xm.td { xm.span << "&rarr;" }
39
39
  xm.td changes[key][:current].inspect
40
40
  end
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
- entry.content(xm.to_s, type: 'html')
45
+ entry.content(xm.to_s, type: "html")
46
46
  end
47
47
  end
48
48
  end
@@ -4,26 +4,29 @@
4
4
  require_relative '../lib/calagator/version'
5
5
 
6
6
  USAGE = <<~END
7
- Calagator: v#{Calagator::VERSION}
8
- calagator: setup Calagator in a new or existing Rails application
7
+ Koalagator: v#{Calagator::VERSION}
8
+ koalagator: setup Koalagator in a new or existing Rails application
9
9
 
10
10
  Usage:
11
- calagator new APP_PATH [options]
12
- calagator install
11
+ koalagator new APP_PATH [options]
12
+ koalagator install
13
+ koalagator --version, -v
13
14
 
14
- calagator new: generates a new Rails app and install Calagator into it
15
+ koalagator new: generates a new Rails app and install Koalagator into it
15
16
 
16
17
  Options:
17
- --test_app # Generates an app suitable for use in spec/test_app for Calagator
18
+ --test_app # Generates an app suitable for use in spec/test_app for Koalagator
18
19
  # development and testing
19
20
 
20
- In the case of `calagator new`, all other options will be passed along
21
+ In the case of `koalagator new`, all other options will be passed along
21
22
  to `rails new`; see `rails new --help` for supported options.
22
23
 
23
- calagator install: install Calagator into an existing Rails application
24
+ koalagator install: install Koalagator into an existing Rails application
24
25
 
25
26
  Options:
26
27
  none
28
+
29
+ koalagator --version, -v: prints version info
27
30
  END
28
31
 
29
32
  TEMPLATE_PATH = File.expand_path('../rails_template.rb', __dir__)
@@ -34,7 +37,9 @@ case command
34
37
  when /_\d+\.\d+\.\d+_/, 'new'
35
38
  system "rails #{command} #{ARGV.join(' ')} -m #{TEMPLATE_PATH} --skip-bundle --skip-javascript" # Skip Webpack on Rails 6 as we're on our way to Rails 7.
36
39
  when 'install'
37
- system "bundle exec rake rails:template LOCATION=#{TEMPLATE_PATH}"
40
+ system "bundle exec rake app:template LOCATION=#{TEMPLATE_PATH}"
41
+ when '--version', '-v'
42
+ puts "#{Calagator::NAME} v#{Calagator::VERSION}"
38
43
  else
39
44
  puts USAGE
40
45
  end
@@ -0,0 +1,11 @@
1
+ def js(path) = Calagator::Engine.root.join("app/javascript").join(path)
2
+
3
+ pin "ical.js" # @2.0.1
4
+ pin "@event-calendar/core", to: "@event-calendar--core.js" # @3.4.0
5
+ pin "svelte", to: "https://ga.jspm.io/npm:svelte@4.2.18/src/runtime/index.js" # @4.2.18
6
+ pin "svelte/internal", to: "https://ga.jspm.io/npm:svelte@4.2.18/src/runtime/internal/index.js" # @4.2.18
7
+ pin "svelte/store", to: "https://ga.jspm.io/npm:svelte@4.2.18/src/runtime/store/index.js" # @4.2.18
8
+ pin "@event-calendar/list", to: "@event-calendar--list.js" # @3.4.0
9
+ pin "@event-calendar/day-grid", to: "@event-calendar--day-grid.js" # @3.4.0
10
+
11
+ pin_all_from js("calagator/calendar"), under: "calendar", to: "calagator/calendar"
@@ -0,0 +1,15 @@
1
+ module Calagator
2
+ Rails.application.config.after_initialize do
3
+ next unless Calagator.devise_enabled
4
+ next unless Calagator.admin_username.present? && Calagator.admin_email.present? && Calagator.admin_password.present?
5
+ begin
6
+ next if User.admin.any?
7
+ User.create(
8
+ name: Calagator.admin_username, email: Calagator.admin_email,
9
+ password: Calagator.admin_password, password_confirmation: Calagator.admin_password,
10
+ admin: true
11
+ )
12
+ rescue ActiveRecord::StatementInvalid
13
+ end
14
+ end
15
+ end
@@ -2,4 +2,4 @@
2
2
 
3
3
  Rails.configuration.after_initialize do
4
4
  ApplicationRecord.observers << Calagator::CacheObserver
5
- end
5
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  PaperTrailManager.route_helpers = Calagator::Engine.routes.url_helpers
4
- PaperTrailManager.base_controller = "Calagator::ApplicationController"
4
+ PaperTrailManager.base_controller = "Calagator::PaperTrailManagerController"
5
5
  PaperTrailManager.item_name_method = :title
@@ -0,0 +1,65 @@
1
+ # Additional translations at https://github.com/heartcombo/devise/wiki/I18n
2
+
3
+ en:
4
+ devise:
5
+ confirmations:
6
+ confirmed: "Your email address has been successfully confirmed."
7
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9
+ failure:
10
+ already_authenticated: "You are already signed in."
11
+ inactive: "Your account is not activated yet."
12
+ invalid: "Invalid %{authentication_keys} or password."
13
+ locked: "Your account is locked."
14
+ last_attempt: "You have one more attempt before your account is locked."
15
+ not_found_in_database: "Invalid %{authentication_keys} or password."
16
+ timeout: "Your session expired. Please sign in again to continue."
17
+ unauthenticated: "You need to sign in or sign up before continuing."
18
+ unconfirmed: "You have to confirm your email address before continuing."
19
+ mailer:
20
+ confirmation_instructions:
21
+ subject: "Confirmation instructions"
22
+ reset_password_instructions:
23
+ subject: "Reset password instructions"
24
+ unlock_instructions:
25
+ subject: "Unlock instructions"
26
+ email_changed:
27
+ subject: "Email Changed"
28
+ password_change:
29
+ subject: "Password Changed"
30
+ omniauth_callbacks:
31
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
32
+ success: "Successfully authenticated from %{kind} account."
33
+ passwords:
34
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
35
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
36
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
37
+ updated: "Your password has been changed successfully. You are now signed in."
38
+ updated_not_active: "Your password has been changed successfully."
39
+ registrations:
40
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
41
+ signed_up: "Welcome! You have signed up successfully."
42
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
43
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
44
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
45
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
46
+ updated: "Your account has been updated successfully."
47
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
48
+ sessions:
49
+ signed_in: "Signed in successfully."
50
+ signed_out: "Signed out successfully."
51
+ already_signed_out: "Signed out successfully."
52
+ unlocks:
53
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
54
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
55
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
56
+ errors:
57
+ messages:
58
+ already_confirmed: "was already confirmed, please try signing in"
59
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
60
+ expired: "has expired, please request a new one"
61
+ not_found: "not found"
62
+ not_locked: "was not locked"
63
+ not_saved:
64
+ one: "1 error prohibited this %{resource} from being saved:"
65
+ other: "%{count} errors prohibited this %{resource} from being saved:"
data/config/routes.rb CHANGED
@@ -6,6 +6,18 @@ Calagator::Engine.routes.draw do
6
6
 
7
7
  root "site#index"
8
8
 
9
+ # Change routes if registrations are closed
10
+ if Calagator.open_registration
11
+ devise_for :users, class_name: "Calagator::User" if Calagator.devise_enabled
12
+ else
13
+ devise_for :users, skip: [:registrations], class_name: "Calagator::User" if Calagator.devise_enabled
14
+ as :user do
15
+ get "users/sign_up" => "site#closed_registrations", :as => "new_user_registration"
16
+ get "users/edit" => "devise/registrations#edit", :as => "edit_user_registration"
17
+ put "users" => "devise/registrations#update", :as => "user_registration"
18
+ end
19
+ end
20
+
9
21
  get "omfg" => "site#omfg"
10
22
  get "hello" => "site#hello"
11
23
 
@@ -19,6 +31,19 @@ Calagator::Engine.routes.draw do
19
31
  get "admin/events"
20
32
  post "lock_event" => "admin#lock_event"
21
33
 
34
+ namespace :admin do
35
+ resources :curations, except: :show
36
+ if Calagator.devise_enabled
37
+ resources :users do
38
+ get :invite, as: :invite
39
+ end
40
+ end
41
+ end
42
+
43
+ get "embed", to: "site#embed", as: "embed"
44
+ get "curations", to: redirect("/")
45
+ resources :curations, only: :show
46
+
22
47
  resources :events do
23
48
  collection do
24
49
  post :squash_many_duplicates
@@ -59,4 +84,4 @@ Calagator::Engine.routes.draw do
59
84
 
60
85
  get "/index" => "site#index"
61
86
  get "/index.:format" => "site#index"
62
- end
87
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeviseCreateCalagatorUsers < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :calagator_users do |t|
6
+ ## Database authenticatable
7
+ t.string :email, null: false, default: ""
8
+ t.string :encrypted_password, null: false, default: ""
9
+
10
+ ## Recoverable
11
+ t.string :reset_password_token
12
+ t.datetime :reset_password_sent_at
13
+
14
+ ## Rememberable
15
+ t.datetime :remember_created_at
16
+
17
+ ## Trackable
18
+ # t.integer :sign_in_count, default: 0, null: false
19
+ # t.datetime :current_sign_in_at
20
+ # t.datetime :last_sign_in_at
21
+ # t.string :current_sign_in_ip
22
+ # t.string :last_sign_in_ip
23
+
24
+ ## Confirmable
25
+ # t.string :confirmation_token
26
+ # t.datetime :confirmed_at
27
+ # t.datetime :confirmation_sent_at
28
+ # t.string :unconfirmed_email # Only if using reconfirmable
29
+
30
+ ## Lockable
31
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
32
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
33
+ # t.datetime :locked_at
34
+
35
+ t.timestamps null: false
36
+ end
37
+
38
+ add_index :calagator_users, :email, unique: true
39
+ add_index :calagator_users, :reset_password_token, unique: true
40
+ # add_index :calagator_users, :confirmation_token, unique: true
41
+ # add_index :calagator_users, :unlock_token, unique: true
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ class AddAdminFlagToCalagatorUser < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :calagator_users, :admin, :boolean
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ class AddNameToCalagatorUser < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :calagator_users, :name, :string, null: false
4
+ add_column :calagator_users, :display_name, :string
5
+
6
+ add_index :calagator_users, :name, unique: true
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ class AddCreatedByToRecords < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :events, :created_by_name, :string
4
+ add_reference :events, :created_by, foreign_key: {to_table: :calagator_users}
5
+
6
+ add_column :venues, :created_by_name, :string
7
+ add_reference :venues, :created_by, foreign_key: {to_table: :calagator_users}
8
+
9
+ add_column :sources, :created_by_name, :string
10
+ add_reference :sources, :created_by, foreign_key: {to_table: :calagator_users}
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ class CreateCalagatorCurations < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :calagator_curations do |t|
4
+ t.string :name, null: false
5
+ t.string :display_name
6
+ t.string :description
7
+ t.integer :priority, null: false, default: 0
8
+ t.boolean :unlisted, null: false, default: false
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :calagator_curations, :name, unique: true
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class AddPinnedToVenue < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :venues, :pinned, :boolean, null: false, default: false
4
+ end
5
+ end
data/db/seeds.rb CHANGED
@@ -9,6 +9,20 @@ rescue LoadError
9
9
  exit 1
10
10
  end
11
11
 
12
+ TAGS = [
13
+ "gardening",
14
+ "birdwatching",
15
+ "camping",
16
+ "hiking",
17
+ "nature",
18
+ "public lecture",
19
+ "book launch"
20
+ ].freeze
21
+
22
+ def random_tags
23
+ TAGS.sample(rand(2..4)).join(", ")
24
+ end
25
+
12
26
  FactoryBot.define do
13
27
  factory :seed_venue, class: Calagator::Venue do
14
28
  title { Faker::Company.name }
@@ -54,6 +68,8 @@ FactoryBot.define do
54
68
  created_at { start_time - 1.day }
55
69
  end_time { start_time + 3.hours }
56
70
 
71
+ tag_list { random_tags }
72
+
57
73
  trait :with_venue do
58
74
  before(:create) do |seed_event|
59
75
  venue = create(:seed_venue)
@@ -63,6 +79,39 @@ FactoryBot.define do
63
79
  end
64
80
  end
65
81
 
82
+ Calagator::Curation.create(
83
+ description: "events related to being around the home",
84
+ display_name: "at home",
85
+ name: "at_home",
86
+ priority: 0,
87
+ block_list: "",
88
+ require_list: "gardening, nature",
89
+ deny_list: "",
90
+ allow_list: ""
91
+ )
92
+
93
+ Calagator::Curation.create(
94
+ description: "events related to being outdoors",
95
+ display_name: "outdoors",
96
+ name: "outdoors",
97
+ priority: 1,
98
+ block_list: "",
99
+ require_list: "birdwatching, hiking, camping, nature",
100
+ deny_list: "",
101
+ allow_list: ""
102
+ )
103
+
104
+ Calagator::Curation.create(
105
+ description: "events related to civic engagement",
106
+ display_name: "civic engagement",
107
+ name: "civic_engagement",
108
+ priority: 2,
109
+ block_list: "",
110
+ require_list: "public lecture, book launch",
111
+ deny_list: "",
112
+ allow_list: ""
113
+ )
114
+
66
115
  puts "Seeding database with sample data..."
67
116
  FactoryBot.create_list(:seed_venue, 25, :with_events)
68
117
  FactoryBot.create_list(:seed_venue, 25)
@@ -25,7 +25,7 @@ module Calagator
25
25
  attributes.each do |field, value|
26
26
  decoded_content = HTMLEntities.new.decode(value)
27
27
  if decoded_content.present? && decoded_content != value
28
- send("#{field}=", decoded_content)
28
+ send(:"#{field}=", decoded_content)
29
29
  end
30
30
  end
31
31
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/contrib/jsonp"
4
- require 'sprockets/railtie'
4
+ require "sprockets/railtie"
5
+ require "importmap-rails"
5
6
 
6
7
  module Calagator
7
8
  class Engine < ::Rails::Engine
@@ -9,9 +10,18 @@ module Calagator
9
10
 
10
11
  config.middleware.use Rack::JSONP
11
12
 
13
+ # https://stackoverflow.com/questions/69635552/how-to-set-up-importmap-rails-in-rails-7-engine
14
+ initializer "calagator.importmap", before: "importmap" do |app|
15
+ app.config.importmap.paths << root.join("config/importmap.rb")
16
+ app.config.importmap.cache_sweepers +=
17
+ ["vendor/javascript", "app/javascript"].map { |str| root.join(str) }
18
+ end
19
+
20
+ config.assets.paths += %w[app/javascript vendor/javascript].map { |path| root.join(path) }
12
21
  config.assets.precompile += %w[
13
22
  *.png
14
23
  *.gif
24
+ *.js
15
25
  calagator/errors.css
16
26
  leaflet.js
17
27
  leaflet_google_layer.js
@@ -21,6 +31,11 @@ module Calagator
21
31
  leaflet
22
32
  ]
23
33
 
34
+ config.to_prepare do
35
+ # Include custom helpers from parent app
36
+ Calagator::ApplicationController.helper Rails.application.helpers
37
+ end
38
+
24
39
  config.after_initialize do
25
40
  Calagator.configure_search_engine
26
41
  end
@@ -65,7 +65,7 @@ module Calagator
65
65
  private
66
66
 
67
67
  # Regular expression for parsing machine tags
68
- MACHINE_TAG_PATTERN = /(?<namespace>[^:]+):(?<predicate>[^=]+)=(?<value>.+)/.freeze
68
+ MACHINE_TAG_PATTERN = /(?<namespace>[^:]+):(?<predicate>[^=]+)=(?<value>.+)/
69
69
 
70
70
  def matches
71
71
  name.match(MACHINE_TAG_PATTERN) || {}
@@ -9,7 +9,7 @@ module StripWhitespace
9
9
  def strip_whitespace!(*fields)
10
10
  before_validation do |record|
11
11
  fields.each do |field|
12
- setter = "#{field}=".to_sym
12
+ setter = :"#{field}="
13
13
  value = record.send(field.to_sym)
14
14
  if value.respond_to?(:strip) && record.respond_to?(setter)
15
15
  record.send(setter, value.strip)
@@ -4,9 +4,9 @@ require "ri_cal"
4
4
 
5
5
  module Calagator
6
6
  class VCalendar < Struct.new(:ri_cal_calendar)
7
- VENUE_CONTENT_RE = /^BEGIN:VVENUE$.*?^END:VVENUE$/m.freeze
7
+ VENUE_CONTENT_RE = /^BEGIN:VVENUE$.*?^END:VVENUE$/m
8
8
  def self.parse(raw_ical)
9
- raw_ical = raw_ical.gsub(/\r\n/, "\n") # normalize line endings
9
+ raw_ical = raw_ical.gsub("\r\n", "\n") # normalize line endings
10
10
  raw_ical = raw_ical.gsub(/;TZID=GMT:(.*)/, ':\1Z') # normalize timezones
11
11
  ri_cal = RiCal.parse_string(raw_ical)
12
12
  ri_cal.map do |ri_cal_calendar|
@@ -34,7 +34,7 @@ module Calagator
34
34
  end
35
35
 
36
36
  class VEvent < Struct.new(:ri_cal_event, :vvenues)
37
- VCARD_LINES_RE = /^(?<key>[^;]+?)(?<qualifier>;[^:]*?)?:(?<value>.*)$/.freeze
37
+ VCARD_LINES_RE = /^(?<key>[^;]+?)(?<qualifier>;[^:]*?)?:(?<value>.*)$/
38
38
  def old?
39
39
  cutoff = Time.now.in_time_zone.yesterday
40
40
  (ri_cal_event.dtend || ri_cal_event.dtstart).to_time < cutoff
@@ -76,7 +76,7 @@ module Calagator
76
76
  end
77
77
 
78
78
  class VVenue < Struct.new(:raw_ical_venue)
79
- VCARD_LINES_RE = /^(?<key>[^;]+?)(?<qualifier>;[^:]*?)?:(?<value>.*)$/.freeze
79
+ VCARD_LINES_RE = /^(?<key>[^;]+?)(?<qualifier>;[^:]*?)?:(?<value>.*)$/
80
80
  def uid
81
81
  raw_ical_venue.match(/^UID:(?<uid>.+)$/)[:uid]
82
82
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Calagator
4
- VERSION = "4.0.0"
5
- RAILS_VERSION = "~> 7.0"
4
+ NAME = "Koalagator"
5
+ GEMSPEC = "koalagator"
6
+ VERSION = "5.0.0"
7
+ RAILS_VERSION = "~> 7.1"
8
+ MAJOR_RUBY_VERSION = RUBY_VERSION[0].to_i
6
9
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fileutils"
4
+
3
5
  module Calagator
4
6
  class InstallGenerator < Rails::Generators::Base
5
7
  source_root File.expand_path("templates", __dir__)
@@ -12,6 +14,7 @@ module Calagator
12
14
  add_initializers
13
15
  add_javascripts
14
16
  add_stylesheets
17
+ add_devise_views
15
18
  add_assets
16
19
  add_seeds
17
20
  run "rm -f public/index.html"
@@ -31,7 +34,7 @@ module Calagator
31
34
  # PaperTrail needs Time and BigDecimal as supported YAML classes
32
35
  def add_yaml_config
33
36
  inject_into_file "config/application.rb",
34
- "\s\s\s\sconfig.active_record.yaml_column_permitted_classes = [Time, BigDecimal]",
37
+ "\s\s\s\sconfig.active_record.yaml_column_permitted_classes = [ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, Time, BigDecimal]",
35
38
  after: /config.load_defaults.+\n/
36
39
  end
37
40
 
@@ -39,6 +42,7 @@ module Calagator
39
42
  initializer "01_calagator.rb", File.read(File.expand_path("templates/config/initializers/01_calagator.rb", __dir__))
40
43
  initializer "02_geokit.rb", File.read(File.expand_path("templates/config/initializers/02_geokit.rb", __dir__))
41
44
  initializer "03_recaptcha.rb", File.read(File.expand_path("templates/config/initializers/03_recaptcha.rb", __dir__))
45
+ initializer "04_devise.rb", File.read(File.expand_path("templates/config/initializers/04_devise.rb", __dir__))
42
46
  end
43
47
 
44
48
  def add_javascripts
@@ -59,6 +63,10 @@ module Calagator
59
63
  run "cp #{File.expand_path("../../../app/assets/images/site-icon.png", __dir__)} app/assets/images/"
60
64
  end
61
65
 
66
+ def add_devise_views
67
+ FileUtils.cp_r(File.expand_path("./templates/app/views/devise/", __dir__), "app/views/")
68
+ end
69
+
62
70
  def add_seeds
63
71
  append_file "db/seeds.rb", "Calagator::Engine.load_seed"
64
72
  end