panda-cms 0.7.3 → 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 (70) 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/user_activity_component.rb +7 -18
  9. data/app/controllers/panda/cms/admin/block_contents_controller.rb +0 -1
  10. data/app/controllers/panda/cms/admin/forms_controller.rb +0 -1
  11. data/app/controllers/panda/cms/admin/my_profile_controller.rb +43 -0
  12. data/app/controllers/panda/cms/admin/pages_controller.rb +14 -4
  13. data/app/controllers/panda/cms/admin/posts_controller.rb +7 -22
  14. data/app/controllers/panda/cms/form_submissions_controller.rb +2 -0
  15. data/app/controllers/panda/cms/pages_controller.rb +10 -8
  16. data/app/javascript/panda/cms/controllers/index.js +4 -2
  17. data/app/javascript/panda/cms/controllers/slug_controller.js +64 -31
  18. data/app/javascript/panda/cms/controllers/theme_form_controller.js +9 -0
  19. data/app/jobs/panda/cms/record_visit_job.rb +12 -14
  20. data/app/models/panda/cms/application_record.rb +1 -0
  21. data/app/models/panda/cms/block.rb +9 -17
  22. data/app/models/panda/cms/block_content.rb +5 -6
  23. data/app/models/panda/cms/page.rb +24 -11
  24. data/app/models/panda/cms/post.rb +3 -5
  25. data/app/models/panda/cms/redirect.rb +5 -0
  26. data/app/models/panda/cms/template.rb +6 -7
  27. data/app/models/panda/cms/visit.rb +1 -1
  28. data/app/models/panda/social/instagram_post.rb +15 -0
  29. data/app/services/panda/cms/html_to_editor_js_converter.rb +6 -13
  30. data/app/services/panda/social/instagram_feed_service.rb +61 -0
  31. data/app/views/panda/cms/admin/my_profile/edit.html.erb +35 -0
  32. data/app/views/panda/cms/admin/pages/index.html.erb +1 -1
  33. data/app/views/panda/cms/admin/pages/new.html.erb +3 -3
  34. data/app/views/panda/cms/admin/posts/_form.html.erb +10 -0
  35. data/app/views/panda/cms/admin/posts/edit.html.erb +3 -2
  36. data/app/views/panda/cms/admin/posts/index.html.erb +1 -1
  37. data/app/views/panda/cms/admin/settings/index.html.erb +2 -0
  38. data/app/views/panda/cms/admin/shared/_sidebar.html.erb +1 -1
  39. data/app/views/panda/cms/shared/_header.html.erb +4 -2
  40. data/app/views/panda/cms/shared/_importmap.html.erb +1 -0
  41. data/config/locales/en.yml +5 -0
  42. data/config/routes.rb +3 -0
  43. data/db/migrate/20250120235542_remove_paper_trail.rb +55 -0
  44. data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +14 -0
  45. data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +5 -0
  46. data/lib/panda/cms/demo_site_generator.rb +25 -4
  47. data/lib/panda/cms/editor_js_content.rb +21 -0
  48. data/lib/panda/cms/engine.rb +7 -5
  49. data/lib/panda-cms/version.rb +1 -1
  50. data/lib/panda-cms.rb +13 -0
  51. data/lib/tasks/panda/cms/install.rake +23 -0
  52. data/lib/tasks/panda/social/instagram.rake +18 -0
  53. data/public/panda-cms-assets/editor-js/core/editorjs.min.js +83 -0
  54. data/public/panda-cms-assets/editor-js/plugins/embed.min.js +2 -0
  55. data/public/panda-cms-assets/editor-js/plugins/header.min.js +9 -0
  56. data/public/panda-cms-assets/editor-js/plugins/nested-list.min.js +2 -0
  57. data/public/panda-cms-assets/editor-js/plugins/paragraph.min.js +9 -0
  58. data/public/panda-cms-assets/editor-js/plugins/quote.min.js +2 -0
  59. data/public/panda-cms-assets/editor-js/plugins/simple-image.min.js +2 -0
  60. data/public/panda-cms-assets/editor-js/plugins/table.min.js +2 -0
  61. metadata +36 -557
  62. data/app/models/action_text/rich_text_version.rb +0 -6
  63. data/app/models/panda/cms/block_content_version.rb +0 -8
  64. data/app/models/panda/cms/page_version.rb +0 -8
  65. data/app/models/panda/cms/post_version.rb +0 -8
  66. data/app/models/panda/cms/template_version.rb +0 -8
  67. data/app/models/panda/cms/version.rb +0 -8
  68. data/config/initializers/panda/cms/paper_trail.rb +0 -7
  69. data/db/migrate/20240904200605_create_action_text_tables.action_text.rb +0 -24
  70. 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,12 +1,14 @@
1
1
  require "rubygems"
2
2
  require "panda/core"
3
+ require "panda/core/engine"
3
4
  require "panda/cms/railtie"
4
5
 
6
+ require "invisible_captcha"
7
+
5
8
  module Panda
6
9
  module CMS
7
10
  class Engine < ::Rails::Engine
8
11
  isolate_namespace Panda::CMS
9
- engine_name "panda-cms"
10
12
 
11
13
  # Add services directory to autoload paths
12
14
  config.autoload_paths += %W[
@@ -14,7 +16,7 @@ module Panda
14
16
  ]
15
17
 
16
18
  # Basic session setup only
17
- initializer "panda.cms.session", before: :load_config_initializers do |app|
19
+ initializer "panda_cms.session", before: :load_config_initializers do |app|
18
20
  if app.config.middleware.frozen?
19
21
  app.config.middleware = app.config.middleware.dup
20
22
  end
@@ -37,7 +39,7 @@ module Panda
37
39
  g.templates.unshift File.expand_path("../../templates", __FILE__)
38
40
  end
39
41
 
40
- # 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)
41
43
  config.app_middleware.use(
42
44
  Rack::Static,
43
45
  urls: ["/panda-cms-assets"],
@@ -47,7 +49,7 @@ module Panda
47
49
  # Custom error handling
48
50
  # config.exceptions_app = Panda::CMS::ExceptionsApp.new(exceptions_app: routes)
49
51
 
50
- initializer "panda.cms.assets" do |app|
52
+ initializer "panda_cms.assets" do |app|
51
53
  if Rails.configuration.respond_to?(:assets)
52
54
  # Add JavaScript paths
53
55
  app.config.assets.paths << root.join("app/javascript")
@@ -65,7 +67,7 @@ module Panda
65
67
  end
66
68
 
67
69
  # Add importmap paths from the engine
68
- initializer "panda.cms.importmap", before: "importmap" do |app|
70
+ initializer "panda_cms.importmap", before: "importmap" do |app|
69
71
  if app.config.respond_to?(:importmap)
70
72
  # Create a new array if frozen
71
73
  if app.config.importmap.paths.frozen?
@@ -1,5 +1,5 @@
1
1
  module Panda
2
2
  module CMS
3
- VERSION = "0.7.3"
3
+ VERSION = "0.7.4"
4
4
  end
5
5
  end
data/lib/panda-cms.rb CHANGED
@@ -18,6 +18,19 @@ module Panda
18
18
  setting :editor_js_tools, default: []
19
19
  setting :editor_js_tool_config, default: {}
20
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
+
21
34
  def self.root_path
22
35
  config.admin_path
23
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