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.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/app/assets/builds/panda.cms.css +2 -6
- data/app/assets/tailwind/application.css +178 -0
- data/app/assets/tailwind/tailwind.config.js +15 -0
- data/app/builders/panda/cms/form_builder.rb +15 -32
- data/app/components/panda/cms/admin/flash_message_component.html.erb +2 -2
- data/app/components/panda/cms/admin/table_component.html.erb +0 -3
- data/app/components/panda/cms/admin/user_activity_component.rb +7 -18
- data/app/controllers/panda/cms/admin/block_contents_controller.rb +0 -1
- data/app/controllers/panda/cms/admin/forms_controller.rb +0 -1
- data/app/controllers/panda/cms/admin/my_profile_controller.rb +43 -0
- data/app/controllers/panda/cms/admin/pages_controller.rb +14 -4
- data/app/controllers/panda/cms/admin/posts_controller.rb +7 -22
- data/app/controllers/panda/cms/form_submissions_controller.rb +2 -0
- data/app/controllers/panda/cms/pages_controller.rb +10 -8
- data/app/javascript/panda/cms/controllers/index.js +4 -2
- data/app/javascript/panda/cms/controllers/slug_controller.js +64 -31
- data/app/javascript/panda/cms/controllers/theme_form_controller.js +9 -0
- data/app/jobs/panda/cms/record_visit_job.rb +12 -14
- data/app/models/panda/cms/application_record.rb +1 -0
- data/app/models/panda/cms/block.rb +9 -17
- data/app/models/panda/cms/block_content.rb +5 -6
- data/app/models/panda/cms/page.rb +24 -11
- data/app/models/panda/cms/post.rb +3 -5
- data/app/models/panda/cms/redirect.rb +5 -0
- data/app/models/panda/cms/template.rb +6 -7
- data/app/models/panda/cms/visit.rb +1 -1
- data/app/models/panda/social/instagram_post.rb +15 -0
- data/app/services/panda/cms/html_to_editor_js_converter.rb +6 -13
- data/app/services/panda/social/instagram_feed_service.rb +61 -0
- data/app/views/panda/cms/admin/my_profile/edit.html.erb +35 -0
- data/app/views/panda/cms/admin/pages/index.html.erb +1 -1
- data/app/views/panda/cms/admin/pages/new.html.erb +3 -3
- data/app/views/panda/cms/admin/posts/_form.html.erb +10 -0
- data/app/views/panda/cms/admin/posts/edit.html.erb +3 -2
- data/app/views/panda/cms/admin/posts/index.html.erb +1 -1
- data/app/views/panda/cms/admin/settings/index.html.erb +2 -0
- data/app/views/panda/cms/admin/shared/_sidebar.html.erb +1 -1
- data/app/views/panda/cms/shared/_header.html.erb +4 -2
- data/app/views/panda/cms/shared/_importmap.html.erb +1 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20250120235542_remove_paper_trail.rb +55 -0
- data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +14 -0
- data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +5 -0
- data/lib/panda/cms/demo_site_generator.rb +25 -4
- data/lib/panda/cms/editor_js_content.rb +21 -0
- data/lib/panda/cms/engine.rb +7 -12
- data/lib/panda-cms/version.rb +1 -1
- data/lib/panda-cms.rb +18 -11
- data/lib/tasks/panda/cms/install.rake +23 -0
- data/lib/tasks/panda/social/instagram.rake +18 -0
- data/public/panda-cms-assets/editor-js/core/editorjs.min.js +83 -0
- data/public/panda-cms-assets/editor-js/plugins/embed.min.js +2 -0
- data/public/panda-cms-assets/editor-js/plugins/header.min.js +9 -0
- data/public/panda-cms-assets/editor-js/plugins/nested-list.min.js +2 -0
- data/public/panda-cms-assets/editor-js/plugins/paragraph.min.js +9 -0
- data/public/panda-cms-assets/editor-js/plugins/quote.min.js +2 -0
- data/public/panda-cms-assets/editor-js/plugins/simple-image.min.js +2 -0
- data/public/panda-cms-assets/editor-js/plugins/table.min.js +2 -0
- metadata +35 -304
- data/app/models/action_text/rich_text_version.rb +0 -6
- data/app/models/panda/cms/block_content_version.rb +0 -8
- data/app/models/panda/cms/page_version.rb +0 -8
- data/app/models/panda/cms/post_version.rb +0 -8
- data/app/models/panda/cms/template_version.rb +0 -8
- data/app/models/panda/cms/version.rb +0 -8
- data/config/initializers/panda/cms/paper_trail.rb +0 -7
- data/db/migrate/20240904200605_create_action_text_tables.action_text.rb +0 -24
- data/db/migrate/20241119214549_remove_action_text_from_posts.rb +0 -9
data/config/locales/en.yml
CHANGED
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
|
@@ -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({
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
data/lib/panda/cms/engine.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
|
-
require "
|
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 "
|
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 "
|
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. /
|
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 "
|
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 "
|
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?
|
data/lib/panda-cms/version.rb
CHANGED
data/lib/panda-cms.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
|
-
require "
|
2
|
-
require "
|
3
|
-
require "
|
4
|
-
|
5
|
-
require "
|
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
|