panda-cms 0.7.2 → 0.7.4

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/app/assets/builds/panda.cms.css +2 -6
  4. data/app/assets/tailwind/application.css +178 -0
  5. data/app/assets/tailwind/tailwind.config.js +15 -0
  6. data/app/builders/panda/cms/form_builder.rb +15 -32
  7. data/app/components/panda/cms/admin/flash_message_component.html.erb +2 -2
  8. data/app/components/panda/cms/admin/table_component.html.erb +0 -3
  9. data/app/components/panda/cms/admin/user_activity_component.rb +7 -18
  10. data/app/controllers/panda/cms/admin/block_contents_controller.rb +0 -1
  11. data/app/controllers/panda/cms/admin/forms_controller.rb +0 -1
  12. data/app/controllers/panda/cms/admin/my_profile_controller.rb +43 -0
  13. data/app/controllers/panda/cms/admin/pages_controller.rb +14 -4
  14. data/app/controllers/panda/cms/admin/posts_controller.rb +7 -22
  15. data/app/controllers/panda/cms/form_submissions_controller.rb +2 -0
  16. data/app/controllers/panda/cms/pages_controller.rb +10 -8
  17. data/app/javascript/panda/cms/controllers/index.js +4 -2
  18. data/app/javascript/panda/cms/controllers/slug_controller.js +64 -31
  19. data/app/javascript/panda/cms/controllers/theme_form_controller.js +9 -0
  20. data/app/jobs/panda/cms/record_visit_job.rb +12 -14
  21. data/app/models/panda/cms/application_record.rb +1 -0
  22. data/app/models/panda/cms/block.rb +9 -17
  23. data/app/models/panda/cms/block_content.rb +5 -6
  24. data/app/models/panda/cms/page.rb +24 -11
  25. data/app/models/panda/cms/post.rb +3 -5
  26. data/app/models/panda/cms/redirect.rb +5 -0
  27. data/app/models/panda/cms/template.rb +6 -7
  28. data/app/models/panda/cms/visit.rb +1 -1
  29. data/app/models/panda/social/instagram_post.rb +15 -0
  30. data/app/services/panda/cms/html_to_editor_js_converter.rb +6 -13
  31. data/app/services/panda/social/instagram_feed_service.rb +61 -0
  32. data/app/views/panda/cms/admin/my_profile/edit.html.erb +35 -0
  33. data/app/views/panda/cms/admin/pages/index.html.erb +1 -1
  34. data/app/views/panda/cms/admin/pages/new.html.erb +3 -3
  35. data/app/views/panda/cms/admin/posts/_form.html.erb +10 -0
  36. data/app/views/panda/cms/admin/posts/edit.html.erb +3 -2
  37. data/app/views/panda/cms/admin/posts/index.html.erb +1 -1
  38. data/app/views/panda/cms/admin/settings/index.html.erb +2 -0
  39. data/app/views/panda/cms/admin/shared/_sidebar.html.erb +1 -1
  40. data/app/views/panda/cms/shared/_header.html.erb +4 -2
  41. data/app/views/panda/cms/shared/_importmap.html.erb +1 -0
  42. data/config/locales/en.yml +5 -0
  43. data/config/routes.rb +3 -0
  44. data/db/migrate/20250120235542_remove_paper_trail.rb +55 -0
  45. data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +14 -0
  46. data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +5 -0
  47. data/lib/panda/cms/demo_site_generator.rb +25 -4
  48. data/lib/panda/cms/editor_js_content.rb +21 -0
  49. data/lib/panda/cms/engine.rb +7 -12
  50. data/lib/panda-cms/version.rb +1 -1
  51. data/lib/panda-cms.rb +18 -11
  52. data/lib/tasks/panda/cms/install.rake +23 -0
  53. data/lib/tasks/panda/social/instagram.rake +18 -0
  54. data/public/panda-cms-assets/editor-js/core/editorjs.min.js +83 -0
  55. data/public/panda-cms-assets/editor-js/plugins/embed.min.js +2 -0
  56. data/public/panda-cms-assets/editor-js/plugins/header.min.js +9 -0
  57. data/public/panda-cms-assets/editor-js/plugins/nested-list.min.js +2 -0
  58. data/public/panda-cms-assets/editor-js/plugins/paragraph.min.js +9 -0
  59. data/public/panda-cms-assets/editor-js/plugins/quote.min.js +2 -0
  60. data/public/panda-cms-assets/editor-js/plugins/simple-image.min.js +2 -0
  61. data/public/panda-cms-assets/editor-js/plugins/table.min.js +2 -0
  62. metadata +35 -304
  63. data/app/models/action_text/rich_text_version.rb +0 -6
  64. data/app/models/panda/cms/block_content_version.rb +0 -8
  65. data/app/models/panda/cms/page_version.rb +0 -8
  66. data/app/models/panda/cms/post_version.rb +0 -8
  67. data/app/models/panda/cms/template_version.rb +0 -8
  68. data/app/models/panda/cms/version.rb +0 -8
  69. data/config/initializers/panda/cms/paper_trail.rb +0 -7
  70. data/db/migrate/20240904200605_create_action_text_tables.action_text.rb +0 -24
  71. data/db/migrate/20241119214549_remove_action_text_from_posts.rb +0 -9
@@ -47,3 +47,8 @@ en:
47
47
  text: Menu Item
48
48
  external_url: External URL
49
49
  panda/cms_page_id: Page
50
+ panda/cms/user:
51
+ firstname: First Name
52
+ lastname: Last Name
53
+ email: Email Address
54
+ current_theme: Theme
data/config/routes.rb CHANGED
@@ -12,6 +12,9 @@ Panda::CMS::Engine.routes.draw do
12
12
  resources :posts
13
13
 
14
14
  get "settings", to: "settings#index"
15
+
16
+ resource :my_profile, only: %i[edit update], controller: :my_profile
17
+
15
18
  namespace :settings, as: :settings do
16
19
  get "bulk_editor", to: "bulk_editor#new"
17
20
  post "bulk_editor", to: "bulk_editor#create"
@@ -0,0 +1,55 @@
1
+ class RemovePaperTrail < ActiveRecord::Migration[7.1]
2
+ def up
3
+ version_tables = %w[
4
+ panda_cms_versions
5
+ panda_cms_version_associations
6
+ panda_cms_template_versions
7
+ panda_cms_page_versions
8
+ panda_cms_block_content_versions
9
+ panda_cms_post_versions
10
+ action_text_rich_text_versions
11
+ ]
12
+
13
+ version_tables.each do |table|
14
+ if table_exists?(table)
15
+ drop_table table
16
+ end
17
+ end
18
+ end
19
+
20
+ def down
21
+ create_table :panda_cms_versions do |t|
22
+ t.string :item_type, null: false
23
+ t.uuid :item_id, null: false
24
+ t.string :event, null: false
25
+ t.string :whodunnit
26
+ t.jsonb :object
27
+ t.jsonb :object_changes
28
+ t.datetime :created_at
29
+ end
30
+ add_index :panda_cms_versions, %i[item_type item_id]
31
+
32
+ create_table :panda_cms_version_associations do |t|
33
+ t.integer :version_id
34
+ t.string :foreign_key_name, null: false
35
+ t.integer :foreign_key_id
36
+ t.string :foreign_type
37
+ end
38
+ add_index :panda_cms_version_associations, [:version_id]
39
+ add_index :panda_cms_version_associations, [:foreign_key_name, :foreign_key_id, :foreign_type], name: "index_version_associations_on_foreign_key"
40
+
41
+ # Model-specific version tables
42
+ %w[template page block_content post action_text_rich_text].each do |model|
43
+ create_table "panda_cms_#{model}_versions" do |t|
44
+ t.string :item_type, null: false
45
+ t.uuid :item_id, null: false
46
+ t.string :event, null: false
47
+ t.string :whodunnit
48
+ t.jsonb :object
49
+ t.jsonb :object_changes
50
+ t.datetime :created_at
51
+ end
52
+ add_index "panda_cms_#{model}_versions", %i[item_type item_id]
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ class CreatePandaSocialInstagramPosts < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :panda_social_instagram_posts, id: :uuid do |t|
4
+ t.string :instagram_id, null: false
5
+ t.text :caption
6
+ t.datetime :posted_at, null: false
7
+ t.string :permalink
8
+ t.timestamps
9
+
10
+ t.index :instagram_id, unique: true
11
+ t.index :posted_at
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class AddCurrentThemeToPandaCMSUsers < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :panda_cms_users, :current_theme, :string, default: "default"
4
+ end
5
+ end
@@ -34,10 +34,31 @@ module Panda
34
34
  #
35
35
  # @return [Hash] A hash containing the created pages
36
36
  def create_pages
37
- @pages[:home] = Panda::CMS::Page.find_or_create_by({path: "/", title: "Home", template: @templates[:homepage]})
38
- @pages[:about] = Panda::CMS::Page.find_or_create_by({path: "/about", title: "About", template: @templates[:page], parent: @pages[:home]})
39
- @pages[:not_found] = Panda::CMS::Page.find_or_create_by({path: "/404", title: "Page Not Found", template: @templates[:page], parent: @pages[:home], status: "hidden"})
40
- @pages[:internal_error] = Panda::CMS::Page.find_or_create_by({path: "/500", title: "Internal Server Error", template: @templates[:page], parent: @pages[:home], status: "hidden"})
37
+ @pages[:home] = Panda::CMS::Page.find_or_create_by({
38
+ path: "/",
39
+ title: "Home",
40
+ panda_cms_template_id: @templates[:homepage].id
41
+ })
42
+ @pages[:about] = Panda::CMS::Page.find_or_create_by({
43
+ path: "/about",
44
+ title: "About",
45
+ panda_cms_template_id: @templates[:page].id,
46
+ parent: @pages[:home]
47
+ })
48
+ @pages[:not_found] = Panda::CMS::Page.find_or_create_by({
49
+ path: "/404",
50
+ title: "Page Not Found",
51
+ panda_cms_template_id: @templates[:page].id,
52
+ parent: @pages[:home],
53
+ status: "hidden"
54
+ })
55
+ @pages[:internal_error] = Panda::CMS::Page.find_or_create_by({
56
+ path: "/500",
57
+ title: "Internal Server Error",
58
+ panda_cms_template_id: @templates[:page].id,
59
+ parent: @pages[:home],
60
+ status: "hidden"
61
+ })
41
62
 
42
63
  Panda::CMS::Page.reset_column_information
43
64
  Panda::CMS::Page.rebuild!
@@ -10,6 +10,27 @@ module Panda::CMS::EditorJsContent
10
10
  before_save :generate_cached_content
11
11
  end
12
12
 
13
+ def content=(value)
14
+ if value.is_a?(Hash)
15
+ super(value.to_json)
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def content
22
+ value = super
23
+ if value.is_a?(String)
24
+ begin
25
+ JSON.parse(value)
26
+ rescue JSON::ParserError
27
+ value
28
+ end
29
+ else
30
+ value
31
+ end
32
+ end
33
+
13
34
  def generate_cached_content
14
35
  if content.is_a?(String)
15
36
  begin
@@ -1,19 +1,14 @@
1
- require "importmap-rails"
2
- require "turbo-rails"
3
- require "stimulus-rails"
4
- require "view_component"
5
-
1
+ require "rubygems"
6
2
  require "panda/core"
3
+ require "panda/core/engine"
7
4
  require "panda/cms/railtie"
8
5
 
9
- require "omniauth"
10
- require "omniauth/rails_csrf_protection"
6
+ require "invisible_captcha"
11
7
 
12
8
  module Panda
13
9
  module CMS
14
10
  class Engine < ::Rails::Engine
15
11
  isolate_namespace Panda::CMS
16
- engine_name "panda_cms"
17
12
 
18
13
  # Add services directory to autoload paths
19
14
  config.autoload_paths += %W[
@@ -21,7 +16,7 @@ module Panda
21
16
  ]
22
17
 
23
18
  # Basic session setup only
24
- initializer "panda.cms.session", before: :load_config_initializers do |app|
19
+ initializer "panda_cms.session", before: :load_config_initializers do |app|
25
20
  if app.config.middleware.frozen?
26
21
  app.config.middleware = app.config.middleware.dup
27
22
  end
@@ -44,7 +39,7 @@ module Panda
44
39
  g.templates.unshift File.expand_path("../../templates", __FILE__)
45
40
  end
46
41
 
47
- # Make files in public available to the main app (e.g. /panda-cms-assets/favicon.ico)
42
+ # Make files in public available to the main app (e.g. /panda_cms-assets/favicon.ico)
48
43
  config.app_middleware.use(
49
44
  Rack::Static,
50
45
  urls: ["/panda-cms-assets"],
@@ -54,7 +49,7 @@ module Panda
54
49
  # Custom error handling
55
50
  # config.exceptions_app = Panda::CMS::ExceptionsApp.new(exceptions_app: routes)
56
51
 
57
- initializer "panda.cms.assets" do |app|
52
+ initializer "panda_cms.assets" do |app|
58
53
  if Rails.configuration.respond_to?(:assets)
59
54
  # Add JavaScript paths
60
55
  app.config.assets.paths << root.join("app/javascript")
@@ -72,7 +67,7 @@ module Panda
72
67
  end
73
68
 
74
69
  # Add importmap paths from the engine
75
- initializer "panda.cms.importmap", before: "importmap" do |app|
70
+ initializer "panda_cms.importmap", before: "importmap" do |app|
76
71
  if app.config.respond_to?(:importmap)
77
72
  # Create a new array if frozen
78
73
  if app.config.importmap.paths.frozen?
@@ -1,5 +1,5 @@
1
1
  module Panda
2
2
  module CMS
3
- VERSION = "0.7.2"
3
+ VERSION = "0.7.4"
4
4
  end
5
5
  end
data/lib/panda-cms.rb CHANGED
@@ -1,14 +1,8 @@
1
- require "dry-configurable"
2
- require "importmap-rails"
3
- require "lookbook"
4
- require "omniauth"
5
- require "omniauth/rails_csrf_protection"
6
- require "omniauth/strategies/microsoft_graph"
7
- require "omniauth/strategies/google_oauth2"
8
- require "omniauth/strategies/github"
9
- require "paper_trail"
10
- require "view_component"
11
- require "zeitwerk"
1
+ require "rubygems"
2
+ require "panda/core"
3
+ require "panda/cms/railtie"
4
+
5
+ require "capybara/rspec"
12
6
 
13
7
  module Panda
14
8
  module CMS
@@ -24,6 +18,19 @@ module Panda
24
18
  setting :editor_js_tools, default: []
25
19
  setting :editor_js_tool_config, default: {}
26
20
 
21
+ setting :instagram, default: {
22
+ enabled: false,
23
+ username: nil,
24
+ access_token: nil
25
+ }
26
+
27
+ setting :analytics, default: {
28
+ google_analytics: {
29
+ enabled: false,
30
+ tracking_id: nil
31
+ }
32
+ }
33
+
27
34
  def self.root_path
28
35
  config.admin_path
29
36
  end
@@ -0,0 +1,23 @@
1
+ namespace :panda do
2
+ namespace :cms do
3
+ desc "Copy any missing migrations from panda-cms to the host application"
4
+ task :install do
5
+ # Copy migrations
6
+ Rake::Task["railties:install:migrations"].invoke
7
+ end
8
+
9
+ namespace :test do
10
+ desc "Prepare test database by copying migrations and running them"
11
+ task :prepare do
12
+ # Remove all existing migrations from dummy app
13
+ FileUtils.rm_rf(Dir.glob("spec/dummy/db/migrate/*"))
14
+
15
+ # Copy all migrations from main app to dummy app
16
+ FileUtils.cp_r(Dir.glob("db/migrate/*"), "spec/dummy/db/migrate/")
17
+
18
+ # Drop and recreate test database
19
+ system("cd spec/dummy && RAILS_ENV=test rails db:drop db:create db:migrate")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ namespace :panda do
2
+ namespace :social do
3
+ namespace :instagram do
4
+ desc "Sync recent Instagram posts"
5
+ task sync: :environment do
6
+ if Panda::CMS.config.instagram[:access_token].present?
7
+ puts "Starting Instagram sync..."
8
+ Panda::Social::InstagramFeedService.new(
9
+ Panda::CMS.config.instagram[:access_token]
10
+ ).sync_recent_posts
11
+ puts "Instagram sync (@#{Panda::CMS.config.instagram[:username]}) completed"
12
+ else
13
+ puts "Instagram access token not configured"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end