panda-cms 0.8.2 → 0.10.2
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 +75 -5
- data/app/components/panda/cms/code_component.rb +154 -39
- data/app/components/panda/cms/grid_component.rb +26 -6
- data/app/components/panda/cms/menu_component.rb +72 -34
- data/app/components/panda/cms/page_menu_component.rb +102 -13
- data/app/components/panda/cms/rich_text_component.rb +229 -139
- data/app/components/panda/cms/text_component.rb +107 -42
- data/app/controllers/panda/cms/admin/base_controller.rb +19 -3
- data/app/controllers/panda/cms/admin/dashboard_controller.rb +3 -3
- data/app/controllers/panda/cms/admin/files_controller.rb +7 -0
- data/app/controllers/panda/cms/admin/menus_controller.rb +47 -3
- data/app/controllers/panda/cms/admin/pages_controller.rb +11 -2
- data/app/controllers/panda/cms/admin/posts_controller.rb +3 -1
- data/app/controllers/panda/cms/form_submissions_controller.rb +134 -11
- data/app/controllers/panda/cms/pages_controller.rb +7 -2
- data/app/controllers/panda/cms/posts_controller.rb +16 -0
- data/app/helpers/panda/cms/application_helper.rb +17 -4
- data/app/helpers/panda/cms/asset_helper.rb +14 -61
- data/app/helpers/panda/cms/forms_helper.rb +60 -0
- data/app/helpers/panda/cms/seo_helper.rb +85 -0
- data/app/javascript/panda/cms/{application_panda_cms.js → application.js} +5 -1
- data/app/javascript/panda/cms/controllers/code_editor_controller.js +95 -0
- data/app/javascript/panda/cms/controllers/editor_iframe_controller.js +31 -4
- data/app/javascript/panda/cms/controllers/file_gallery_controller.js +128 -0
- data/app/javascript/panda/cms/controllers/file_upload_controller.js +165 -0
- data/app/javascript/panda/cms/controllers/index.js +54 -13
- data/app/javascript/panda/cms/controllers/inline_code_editor_controller.js +96 -0
- data/app/javascript/panda/cms/controllers/menu_form_controller.js +53 -0
- data/app/javascript/panda/cms/controllers/nested_form_controller.js +35 -0
- data/app/javascript/panda/cms/controllers/page_form_controller.js +454 -0
- data/app/javascript/panda/cms/controllers/tree_controller.js +214 -0
- data/app/javascript/panda/cms/stimulus-loading.js +6 -7
- data/app/models/panda/cms/block_content.rb +9 -0
- data/app/models/panda/cms/menu.rb +12 -0
- data/app/models/panda/cms/page.rb +147 -0
- data/app/models/panda/cms/post.rb +98 -0
- data/app/views/layouts/homepage.html.erb +1 -4
- data/app/views/layouts/page.html.erb +1 -4
- data/app/views/panda/cms/admin/dashboard/show.html.erb +5 -5
- data/app/views/panda/cms/admin/files/_file_details.html.erb +45 -0
- data/app/views/panda/cms/admin/files/index.html.erb +11 -118
- data/app/views/panda/cms/admin/forms/index.html.erb +2 -2
- data/app/views/panda/cms/admin/forms/new.html.erb +1 -2
- data/app/views/panda/cms/admin/forms/show.html.erb +15 -30
- data/app/views/panda/cms/admin/menus/_menu_item_fields.html.erb +11 -0
- data/app/views/panda/cms/admin/menus/edit.html.erb +62 -0
- data/app/views/panda/cms/admin/menus/index.html.erb +3 -2
- data/app/views/panda/cms/admin/menus/new.html.erb +38 -0
- data/app/views/panda/cms/admin/pages/edit.html.erb +147 -22
- data/app/views/panda/cms/admin/pages/index.html.erb +49 -11
- data/app/views/panda/cms/admin/pages/new.html.erb +3 -11
- data/app/views/panda/cms/admin/posts/_form.html.erb +44 -15
- data/app/views/panda/cms/admin/posts/edit.html.erb +2 -2
- data/app/views/panda/cms/admin/posts/index.html.erb +6 -6
- data/app/views/panda/cms/admin/posts/new.html.erb +1 -1
- data/app/views/panda/cms/admin/settings/bulk_editor/new.html.erb +1 -1
- data/app/views/panda/cms/admin/settings/index.html.erb +3 -3
- data/app/views/shared/_header.html.erb +1 -4
- data/config/brakeman.ignore +38 -0
- data/config/importmap.rb +10 -10
- data/config/initializers/panda/cms/healthcheck_log_silencer.rb.disabled +31 -0
- data/config/initializers/panda/cms.rb +52 -10
- data/config/locales/en.yml +41 -0
- data/config/routes.rb +5 -3
- data/db/migrate/20240305000000_convert_html_content_to_editor_js.rb +2 -2
- data/db/migrate/20240315125421_add_nested_sets_to_panda_cms_pages.rb +6 -1
- data/db/migrate/20250809231125_migrate_users_to_panda_core.rb +23 -21
- data/db/migrate/20251104150640_add_cached_last_updated_at_to_panda_cms_pages.rb +22 -0
- data/db/migrate/20251104172242_add_page_type_to_panda_cms_pages.rb +6 -0
- data/db/migrate/20251104172638_set_page_types_for_existing_pages.rb +27 -0
- data/db/migrate/20251105000001_add_pending_review_status_to_pages_and_posts.panda_cms.rb +21 -0
- data/db/migrate/20251109131150_add_seo_fields_to_pages.rb +32 -0
- data/db/migrate/20251109131205_add_seo_fields_to_posts.rb +27 -0
- data/db/migrate/20251110114258_add_spam_tracking_to_form_submissions.rb +7 -0
- data/db/migrate/20251110122812_add_performance_indexes_to_pages_and_redirects.rb +13 -0
- data/lib/generators/panda/cms/install_generator.rb +2 -5
- data/lib/panda/cms/asset_loader.rb +46 -76
- data/lib/panda/cms/bulk_editor.rb +288 -12
- data/lib/panda/cms/debug.rb +29 -0
- data/lib/panda/cms/engine/asset_config.rb +49 -0
- data/lib/panda/cms/engine/autoload_config.rb +19 -0
- data/lib/panda/cms/engine/backtrace_config.rb +42 -0
- data/lib/panda/cms/engine/core_config.rb +106 -0
- data/lib/panda/cms/engine/helper_config.rb +20 -0
- data/lib/panda/cms/engine/route_config.rb +34 -0
- data/lib/panda/cms/engine/view_component_config.rb +31 -0
- data/lib/panda/cms/engine.rb +44 -162
- data/lib/panda/cms/features.rb +52 -0
- data/lib/panda/cms.rb +10 -0
- data/lib/panda-cms/version.rb +1 -1
- data/lib/panda-cms.rb +20 -7
- data/lib/tasks/panda_cms_tasks.rake +16 -0
- metadata +41 -50
- data/app/components/panda/cms/admin/container_component.html.erb +0 -13
- data/app/components/panda/cms/admin/flash_message_component.html.erb +0 -31
- data/app/components/panda/cms/admin/panel_component.html.erb +0 -7
- data/app/components/panda/cms/admin/slideover_component.html.erb +0 -9
- data/app/components/panda/cms/admin/slideover_component.rb +0 -15
- data/app/components/panda/cms/admin/statistics_component.html.erb +0 -4
- data/app/components/panda/cms/admin/statistics_component.rb +0 -16
- data/app/components/panda/cms/admin/tab_bar_component.html.erb +0 -35
- data/app/components/panda/cms/admin/tab_bar_component.rb +0 -15
- data/app/components/panda/cms/admin/table_component.html.erb +0 -29
- data/app/components/panda/cms/admin/user_activity_component.html.erb +0 -7
- data/app/components/panda/cms/admin/user_activity_component.rb +0 -20
- data/app/components/panda/cms/admin/user_display_component.html.erb +0 -17
- data/app/components/panda/cms/admin/user_display_component.rb +0 -21
- data/app/components/panda/cms/grid_component.html.erb +0 -6
- data/app/components/panda/cms/menu_component.html.erb +0 -6
- data/app/components/panda/cms/page_menu_component.html.erb +0 -21
- data/app/components/panda/cms/rich_text_component.html.erb +0 -90
- data/app/javascript/panda_cms/stimulus-loading.js +0 -39
- data/app/views/layouts/panda/cms/application.html.erb +0 -42
- data/app/views/panda/cms/admin/shared/_breadcrumbs.html.erb +0 -28
- data/app/views/panda/cms/admin/shared/_flash.html.erb +0 -5
- data/app/views/panda/cms/admin/shared/_sidebar.html.erb +0 -41
- data/app/views/panda/cms/shared/_footer.html.erb +0 -2
- data/app/views/panda/cms/shared/_header.html.erb +0 -25
- data/app/views/panda/cms/shared/_importmap.html.erb +0 -34
- data/config/initializers/inflections.rb +0 -5
- data/config/initializers/panda/cms/healthcheck_log_silencer.rb +0 -13
- data/lib/tasks/assets.rake +0 -587
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Panda
|
|
4
|
+
module CMS
|
|
5
|
+
class Engine < ::Rails::Engine
|
|
6
|
+
# ViewComponent configuration
|
|
7
|
+
module ViewComponentConfig
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
# Set up ViewComponent
|
|
12
|
+
initializer "panda.cms.view_component" do |app|
|
|
13
|
+
app.config.view_component.preview_paths ||= []
|
|
14
|
+
app.config.view_component.preview_paths << root.join("spec/components/previews")
|
|
15
|
+
app.config.view_component.generate.sidecar = true
|
|
16
|
+
app.config.view_component.generate.preview = true
|
|
17
|
+
|
|
18
|
+
# Add preview directories to autoload paths in development
|
|
19
|
+
if Rails.env.development?
|
|
20
|
+
# Handle frozen autoload_paths array
|
|
21
|
+
if app.config.autoload_paths.frozen?
|
|
22
|
+
app.config.autoload_paths = app.config.autoload_paths.dup
|
|
23
|
+
end
|
|
24
|
+
app.config.autoload_paths << root.join("spec/components/previews")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/panda/cms/engine.rb
CHANGED
|
@@ -9,184 +9,55 @@ require "panda/cms/railtie"
|
|
|
9
9
|
|
|
10
10
|
require "invisible_captcha"
|
|
11
11
|
|
|
12
|
+
# Load engine configuration modules
|
|
13
|
+
require_relative "engine/autoload_config"
|
|
14
|
+
require_relative "engine/asset_config"
|
|
15
|
+
require_relative "engine/route_config"
|
|
16
|
+
require_relative "engine/core_config"
|
|
17
|
+
require_relative "engine/helper_config"
|
|
18
|
+
require_relative "engine/backtrace_config"
|
|
19
|
+
|
|
12
20
|
module Panda
|
|
13
21
|
module CMS
|
|
14
22
|
class Engine < ::Rails::Engine
|
|
15
23
|
isolate_namespace Panda::CMS
|
|
16
24
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
# Basic session setup only
|
|
23
|
-
initializer "panda.cms.session", before: :load_config_initializers do |app|
|
|
24
|
-
app.config.middleware = app.config.middleware.dup if app.config.middleware.frozen?
|
|
25
|
-
|
|
26
|
-
app.config.session_store :cookie_store, key: "_panda_cms_session"
|
|
27
|
-
app.config.middleware.use ActionDispatch::Cookies
|
|
28
|
-
app.config.middleware.use ActionDispatch::Session::CookieStore, app.config.session_options
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
config.to_prepare do
|
|
32
|
-
ApplicationController.helper(::ApplicationHelper)
|
|
33
|
-
ApplicationController.helper(Panda::CMS::AssetHelper)
|
|
34
|
-
end
|
|
25
|
+
# Include shared configuration modules from panda-core
|
|
26
|
+
include Panda::Core::Shared::InflectionsConfig
|
|
27
|
+
include Panda::Core::Shared::GeneratorConfig
|
|
35
28
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
end
|
|
29
|
+
# Include CMS-specific configuration modules
|
|
30
|
+
include AutoloadConfig
|
|
31
|
+
include AssetConfig
|
|
32
|
+
include RouteConfig
|
|
33
|
+
include CoreConfig
|
|
34
|
+
include HelperConfig
|
|
35
|
+
include BacktraceConfig
|
|
44
36
|
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
Rack::Static,
|
|
48
|
-
urls: ["/panda-cms-assets"],
|
|
49
|
-
root: Panda::CMS::Engine.root.join("public")
|
|
50
|
-
)
|
|
37
|
+
# Session configuration is left to the consuming application
|
|
38
|
+
# The CMS engine does not impose session store requirements
|
|
51
39
|
|
|
52
40
|
# Custom error handling
|
|
53
41
|
# config.exceptions_app = Panda::CMS::ExceptionsApp.new(exceptions_app: routes)
|
|
54
42
|
|
|
55
|
-
initializer "panda.cms.assets" do |app|
|
|
56
|
-
if Rails.configuration.respond_to?(:assets)
|
|
57
|
-
# Add JavaScript paths
|
|
58
|
-
app.config.assets.paths << root.join("app/javascript")
|
|
59
|
-
app.config.assets.paths << root.join("app/javascript/panda")
|
|
60
|
-
app.config.assets.paths << root.join("app/javascript/panda/cms")
|
|
61
|
-
app.config.assets.paths << root.join("app/javascript/panda/cms/controllers")
|
|
62
|
-
|
|
63
|
-
# Make sure these files are precompiled
|
|
64
|
-
app.config.assets.precompile += %w[
|
|
65
|
-
panda_cms_manifest.js
|
|
66
|
-
panda/cms/controllers/**/*.js
|
|
67
|
-
panda/cms/application_panda_cms.js
|
|
68
|
-
]
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Add importmap paths from the engine
|
|
73
|
-
initializer "panda.cms.importmap", before: "importmap" do |app|
|
|
74
|
-
if app.config.respond_to?(:importmap)
|
|
75
|
-
# Create a new array if frozen
|
|
76
|
-
app.config.importmap.paths = app.config.importmap.paths.dup if app.config.importmap.paths.frozen?
|
|
77
|
-
|
|
78
|
-
# Add our paths
|
|
79
|
-
app.config.importmap.paths << root.join("config/importmap.rb")
|
|
80
|
-
|
|
81
|
-
# Handle cache sweepers similarly
|
|
82
|
-
if app.config.importmap.cache_sweepers.frozen?
|
|
83
|
-
app.config.importmap.cache_sweepers = app.config.importmap.cache_sweepers.dup
|
|
84
|
-
end
|
|
85
|
-
app.config.importmap.cache_sweepers << root.join("app/javascript")
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
config.after_initialize do |app|
|
|
90
|
-
# Append routes to the routes file
|
|
91
|
-
app.routes.append do
|
|
92
|
-
mount Panda::CMS::Engine => "/", :as => "panda_cms"
|
|
93
|
-
post "/_forms/:id", to: "panda/cms/form_submissions#create", as: :panda_cms_form_submit
|
|
94
|
-
get "/_maintenance", to: "panda/cms/errors#error_503", as: :panda_cms_maintenance
|
|
95
|
-
get "/*path", to: "panda/cms/pages#show", as: :panda_cms_page
|
|
96
|
-
root to: "panda/cms/pages#root"
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
initializer "#{engine_name}.backtrace_cleaner" do |_app|
|
|
101
|
-
engine_root_regex = Regexp.escape(root.to_s + File::SEPARATOR)
|
|
102
|
-
|
|
103
|
-
# Clean those ERB lines, we don't need the internal autogenerated
|
|
104
|
-
# ERB method, what we do need (line number in ERB file) is already there
|
|
105
|
-
Rails.backtrace_cleaner.add_filter do |line|
|
|
106
|
-
line.sub(/(\.erb:\d+):in `__.*$/, '\\1')
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Remove our own engine's path prefix, even if it's
|
|
110
|
-
# being used from a local path rather than the gem directory.
|
|
111
|
-
Rails.backtrace_cleaner.add_filter do |line|
|
|
112
|
-
line.sub(/^#{engine_root_regex}/, "#{engine_name} ")
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Keep Umlaut's own stacktrace in the backtrace -- we have to remove Rails
|
|
116
|
-
# silencers and re-add them how we want.
|
|
117
|
-
Rails.backtrace_cleaner.remove_silencers!
|
|
118
|
-
|
|
119
|
-
# Silence what Rails silenced, UNLESS it looks like
|
|
120
|
-
# it's from Umlaut engine
|
|
121
|
-
Rails.backtrace_cleaner.add_silencer do |line|
|
|
122
|
-
(line !~ Rails::BacktraceCleaner::APP_DIRS_PATTERN) &&
|
|
123
|
-
(line !~ /^#{engine_root_regex}/) &&
|
|
124
|
-
(line !~ /^#{engine_name} /)
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Set up ViewComponent
|
|
129
|
-
initializer "panda.cms.view_component" do |app|
|
|
130
|
-
app.config.view_component.preview_paths ||= []
|
|
131
|
-
app.config.view_component.preview_paths << root.join("spec/components/previews")
|
|
132
|
-
app.config.view_component.generate.sidecar = true
|
|
133
|
-
app.config.view_component.generate.preview = true
|
|
134
|
-
end
|
|
135
|
-
|
|
136
43
|
# Authentication is now handled by Panda::Core::Engine
|
|
137
44
|
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
config.login_page_title = "Panda CMS Admin"
|
|
144
|
-
|
|
145
|
-
# Set dashboard redirect path to CMS dashboard (using Core's admin_path)
|
|
146
|
-
config.dashboard_redirect_path = "#{Panda::Core.configuration.admin_path}/cms"
|
|
147
|
-
|
|
148
|
-
# Customize initial breadcrumb
|
|
149
|
-
config.initial_admin_breadcrumb = ->(controller) {
|
|
150
|
-
# Use CMS dashboard path - just use the string path
|
|
151
|
-
["Admin", "#{Panda::Core.configuration.admin_path}/cms"]
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
# Dashboard widgets
|
|
155
|
-
config.admin_dashboard_widgets = ->(user) {
|
|
156
|
-
widgets = []
|
|
157
|
-
|
|
158
|
-
# Add CMS statistics widgets if CMS is available
|
|
159
|
-
if defined?(Panda::CMS)
|
|
160
|
-
widgets << Panda::CMS::Admin::StatisticsComponent.new(
|
|
161
|
-
metric: "Views Today",
|
|
162
|
-
value: Panda::CMS::Visit.group_by_day(:visited_at, last: 1).count.values.first || 0
|
|
163
|
-
)
|
|
164
|
-
widgets << Panda::CMS::Admin::StatisticsComponent.new(
|
|
165
|
-
metric: "Views Last Week",
|
|
166
|
-
value: Panda::CMS::Visit.group_by_week(:visited_at, last: 1).count.values.first || 0
|
|
167
|
-
)
|
|
168
|
-
widgets << Panda::CMS::Admin::StatisticsComponent.new(
|
|
169
|
-
metric: "Views Last Month",
|
|
170
|
-
value: Panda::CMS::Visit.group_by_month(:visited_at, last: 1).count.values.first || 0
|
|
171
|
-
)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
widgets
|
|
175
|
-
}
|
|
45
|
+
# Load the engine's importmap
|
|
46
|
+
# This keeps the engine's JavaScript separate from the app's importmap
|
|
47
|
+
initializer "panda_cms.importmap", before: "importmap" do |app|
|
|
48
|
+
Panda::CMS.importmap = Importmap::Map.new.tap do |map|
|
|
49
|
+
map.draw(Panda::CMS::Engine.root.join("config/importmap.rb"))
|
|
176
50
|
end
|
|
177
51
|
end
|
|
178
52
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
# Example: { image: { class: 'ImageTool', config: { ... } } }
|
|
188
|
-
config.editor_js_tool_config ||= {}
|
|
189
|
-
end
|
|
53
|
+
# Static asset middleware for serving public files
|
|
54
|
+
# JavaScript serving is handled by Panda::Core::ModuleRegistry::JavaScriptMiddleware
|
|
55
|
+
initializer "panda.cms.static_assets" do |app|
|
|
56
|
+
# Serve public assets (CSS, images, etc.)
|
|
57
|
+
# JavaScript is served by ModuleRegistry's JavaScriptMiddleware in panda-core
|
|
58
|
+
app.config.middleware.use Rack::Static,
|
|
59
|
+
urls: ["/panda-cms-assets"],
|
|
60
|
+
root: Panda::CMS::Engine.root.join("public")
|
|
190
61
|
end
|
|
191
62
|
end
|
|
192
63
|
|
|
@@ -195,3 +66,14 @@ module Panda
|
|
|
195
66
|
class BlockError < StandardError; end
|
|
196
67
|
end
|
|
197
68
|
end
|
|
69
|
+
|
|
70
|
+
# Register CMS module with ModuleRegistry for JavaScript serving
|
|
71
|
+
Panda::Core::ModuleRegistry.register(
|
|
72
|
+
gem_name: "panda-cms",
|
|
73
|
+
engine: "Panda::CMS::Engine",
|
|
74
|
+
paths: {
|
|
75
|
+
views: "app/views/panda/cms/**/*.erb",
|
|
76
|
+
components: "app/components/panda/cms/**/*.rb"
|
|
77
|
+
# JavaScript paths are auto-discovered from config/importmap.rb
|
|
78
|
+
}
|
|
79
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Panda
|
|
4
|
+
module CMS
|
|
5
|
+
# Lightweight feature flag registry so open-source core can gate functionality
|
|
6
|
+
# that is only available when panda-cms-pro is installed.
|
|
7
|
+
module Features
|
|
8
|
+
Feature = Struct.new(:name, :provider, keyword_init: true)
|
|
9
|
+
|
|
10
|
+
class MissingFeatureError < StandardError; end
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def register(name, provider:)
|
|
14
|
+
registry[name.to_sym] = Feature.new(name: name.to_sym, provider: provider)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def unregister(name)
|
|
18
|
+
registry.delete(name.to_sym)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def reset!
|
|
22
|
+
registry.clear
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def enabled?(name)
|
|
26
|
+
registry.key?(name.to_sym)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def require!(name)
|
|
30
|
+
return if enabled?(name)
|
|
31
|
+
|
|
32
|
+
raise MissingFeatureError,
|
|
33
|
+
"The #{name} feature is only available with panda-cms-pro."
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def provider_for(name)
|
|
37
|
+
registry[name.to_sym]&.provider
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def enabled_features
|
|
41
|
+
registry.keys
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def registry
|
|
47
|
+
@registry ||= {}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/panda/cms.rb
CHANGED
data/lib/panda-cms/version.rb
CHANGED
data/lib/panda-cms.rb
CHANGED
|
@@ -3,14 +3,12 @@
|
|
|
3
3
|
require "rubygems"
|
|
4
4
|
require "panda/core"
|
|
5
5
|
require "panda/cms/railtie"
|
|
6
|
-
require "view_component"
|
|
7
6
|
|
|
8
7
|
module Panda
|
|
9
8
|
module CMS
|
|
10
9
|
class Configuration
|
|
11
10
|
attr_accessor :title, :require_login_to_view, :authentication,
|
|
12
|
-
:posts, :url, :
|
|
13
|
-
:editor_js_tool_config, :instagram, :analytics
|
|
11
|
+
:posts, :url, :instagram, :analytics, :performance
|
|
14
12
|
|
|
15
13
|
def initialize
|
|
16
14
|
@title = "Demo Site"
|
|
@@ -18,8 +16,6 @@ module Panda
|
|
|
18
16
|
@authentication = {}
|
|
19
17
|
@posts = {enabled: true, prefix: "blog"}
|
|
20
18
|
@url = nil
|
|
21
|
-
@editor_js_tools = []
|
|
22
|
-
@editor_js_tool_config = {}
|
|
23
19
|
@instagram = {
|
|
24
20
|
enabled: false,
|
|
25
21
|
username: nil,
|
|
@@ -31,6 +27,21 @@ module Panda
|
|
|
31
27
|
tracking_id: nil
|
|
32
28
|
}
|
|
33
29
|
}
|
|
30
|
+
@performance = {
|
|
31
|
+
http_caching: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
public: true
|
|
34
|
+
},
|
|
35
|
+
fragment_caching: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
expires_in: 1.hour
|
|
38
|
+
},
|
|
39
|
+
cache_store: {
|
|
40
|
+
type: :memory_store, # :memory_store, :redis_cache_store, :file_store
|
|
41
|
+
redis_url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"),
|
|
42
|
+
namespace: "panda_cms"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
34
45
|
end
|
|
35
46
|
end
|
|
36
47
|
|
|
@@ -56,7 +67,7 @@ module Panda
|
|
|
56
67
|
|
|
57
68
|
def self.root_path
|
|
58
69
|
# Delegate to Panda::Core's admin_path configuration
|
|
59
|
-
Panda::Core.
|
|
70
|
+
Panda::Core.config.admin_path
|
|
60
71
|
end
|
|
61
72
|
|
|
62
73
|
class << self
|
|
@@ -64,7 +75,7 @@ module Panda
|
|
|
64
75
|
|
|
65
76
|
def route_namespace
|
|
66
77
|
# Delegate to Panda::Core's admin_path configuration
|
|
67
|
-
Panda::Core.
|
|
78
|
+
Panda::Core.config.admin_path
|
|
68
79
|
end
|
|
69
80
|
end
|
|
70
81
|
end
|
|
@@ -91,10 +102,12 @@ Panda::CMS.loader.inflector.inflect(
|
|
|
91
102
|
|
|
92
103
|
# Manually require files from panda-cms directory
|
|
93
104
|
require_relative "panda-cms/version"
|
|
105
|
+
require_relative "panda/cms/debug"
|
|
94
106
|
require_relative "panda/cms/exceptions_app"
|
|
95
107
|
require_relative "panda/cms/engine"
|
|
96
108
|
require_relative "panda/cms/demo_site_generator"
|
|
97
109
|
require_relative "panda/cms/asset_loader"
|
|
110
|
+
require_relative "panda/cms/features"
|
|
98
111
|
require_relative "panda/cms/slug"
|
|
99
112
|
|
|
100
113
|
Panda::CMS.loader.setup
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Provide consistent namespacing for Panda tasks
|
|
4
|
+
# Rails auto-generates panda_cms:* tasks from the module name,
|
|
5
|
+
# but we want to use panda:cms:* for consistency across all Panda gems
|
|
6
|
+
|
|
7
|
+
namespace :panda do
|
|
8
|
+
namespace :cms do
|
|
9
|
+
namespace :install do
|
|
10
|
+
desc "Copy migrations from panda-cms to application"
|
|
11
|
+
task :migrations do
|
|
12
|
+
Rake::Task["panda_cms:install:migrations"].invoke
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: panda-cms
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
- Otaina Limited
|
|
7
|
+
- Otaina Limited
|
|
8
8
|
- James Inman
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 3.8.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 3.8.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: down
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -248,22 +248,8 @@ dependencies:
|
|
|
248
248
|
- - ">="
|
|
249
249
|
- !ruby/object:Gem::Version
|
|
250
250
|
version: '0'
|
|
251
|
-
- !ruby/object:Gem::Dependency
|
|
252
|
-
name: view_component
|
|
253
|
-
requirement: !ruby/object:Gem::Requirement
|
|
254
|
-
requirements:
|
|
255
|
-
- - ">="
|
|
256
|
-
- !ruby/object:Gem::Version
|
|
257
|
-
version: '0'
|
|
258
|
-
type: :runtime
|
|
259
|
-
prerelease: false
|
|
260
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
261
|
-
requirements:
|
|
262
|
-
- - ">="
|
|
263
|
-
- !ruby/object:Gem::Version
|
|
264
|
-
version: '0'
|
|
265
251
|
email:
|
|
266
|
-
-
|
|
252
|
+
- james@otaina.co.uk
|
|
267
253
|
executables: []
|
|
268
254
|
extensions: []
|
|
269
255
|
extra_rdoc_files: []
|
|
@@ -276,28 +262,10 @@ files:
|
|
|
276
262
|
- app/assets/stylesheets/panda/cms/editor.css
|
|
277
263
|
- app/assets/tailwind/application.css
|
|
278
264
|
- app/assets/tailwind/tailwind.config.js
|
|
279
|
-
- app/components/panda/cms/admin/container_component.html.erb
|
|
280
|
-
- app/components/panda/cms/admin/flash_message_component.html.erb
|
|
281
|
-
- app/components/panda/cms/admin/panel_component.html.erb
|
|
282
|
-
- app/components/panda/cms/admin/slideover_component.html.erb
|
|
283
|
-
- app/components/panda/cms/admin/slideover_component.rb
|
|
284
|
-
- app/components/panda/cms/admin/statistics_component.html.erb
|
|
285
|
-
- app/components/panda/cms/admin/statistics_component.rb
|
|
286
|
-
- app/components/panda/cms/admin/tab_bar_component.html.erb
|
|
287
|
-
- app/components/panda/cms/admin/tab_bar_component.rb
|
|
288
|
-
- app/components/panda/cms/admin/table_component.html.erb
|
|
289
|
-
- app/components/panda/cms/admin/user_activity_component.html.erb
|
|
290
|
-
- app/components/panda/cms/admin/user_activity_component.rb
|
|
291
|
-
- app/components/panda/cms/admin/user_display_component.html.erb
|
|
292
|
-
- app/components/panda/cms/admin/user_display_component.rb
|
|
293
265
|
- app/components/panda/cms/code_component.rb
|
|
294
|
-
- app/components/panda/cms/grid_component.html.erb
|
|
295
266
|
- app/components/panda/cms/grid_component.rb
|
|
296
|
-
- app/components/panda/cms/menu_component.html.erb
|
|
297
267
|
- app/components/panda/cms/menu_component.rb
|
|
298
|
-
- app/components/panda/cms/page_menu_component.html.erb
|
|
299
268
|
- app/components/panda/cms/page_menu_component.rb
|
|
300
|
-
- app/components/panda/cms/rich_text_component.html.erb
|
|
301
269
|
- app/components/panda/cms/rich_text_component.rb
|
|
302
270
|
- app/components/panda/cms/text_component.rb
|
|
303
271
|
- app/controllers/panda/cms/admin/base_controller.rb
|
|
@@ -320,22 +288,31 @@ files:
|
|
|
320
288
|
- app/helpers/panda/cms/admin/posts_helper.rb
|
|
321
289
|
- app/helpers/panda/cms/application_helper.rb
|
|
322
290
|
- app/helpers/panda/cms/asset_helper.rb
|
|
291
|
+
- app/helpers/panda/cms/forms_helper.rb
|
|
323
292
|
- app/helpers/panda/cms/pages_helper.rb
|
|
324
293
|
- app/helpers/panda/cms/posts_helper.rb
|
|
294
|
+
- app/helpers/panda/cms/seo_helper.rb
|
|
325
295
|
- app/helpers/panda/cms/theme_helper.rb
|
|
326
296
|
- app/javascript/panda/cms/@editorjs--editorjs.js
|
|
327
297
|
- app/javascript/panda/cms/@hotwired--stimulus.js
|
|
328
298
|
- app/javascript/panda/cms/@hotwired--turbo.js
|
|
329
299
|
- app/javascript/panda/cms/@rails--actioncable--src.js
|
|
330
|
-
- app/javascript/panda/cms/
|
|
300
|
+
- app/javascript/panda/cms/application.js
|
|
301
|
+
- app/javascript/panda/cms/controllers/code_editor_controller.js
|
|
331
302
|
- app/javascript/panda/cms/controllers/dashboard_controller.js
|
|
332
303
|
- app/javascript/panda/cms/controllers/editor_form_controller.js
|
|
333
304
|
- app/javascript/panda/cms/controllers/editor_iframe_controller.js
|
|
305
|
+
- app/javascript/panda/cms/controllers/file_gallery_controller.js
|
|
306
|
+
- app/javascript/panda/cms/controllers/file_upload_controller.js
|
|
334
307
|
- app/javascript/panda/cms/controllers/index.js
|
|
308
|
+
- app/javascript/panda/cms/controllers/inline_code_editor_controller.js
|
|
309
|
+
- app/javascript/panda/cms/controllers/menu_form_controller.js
|
|
310
|
+
- app/javascript/panda/cms/controllers/nested_form_controller.js
|
|
311
|
+
- app/javascript/panda/cms/controllers/page_form_controller.js
|
|
335
312
|
- app/javascript/panda/cms/controllers/slug_controller.js
|
|
313
|
+
- app/javascript/panda/cms/controllers/tree_controller.js
|
|
336
314
|
- app/javascript/panda/cms/stimulus-loading.js
|
|
337
315
|
- app/javascript/panda/cms/tailwindcss-stimulus-components.js
|
|
338
|
-
- app/javascript/panda_cms/stimulus-loading.js
|
|
339
316
|
- app/jobs/panda/cms/application_job.rb
|
|
340
317
|
- app/jobs/panda/cms/record_visit_job.rb
|
|
341
318
|
- app/mailers/panda/cms/application_mailer.rb
|
|
@@ -360,16 +337,19 @@ files:
|
|
|
360
337
|
- app/views/layouts/different_page.html.erb
|
|
361
338
|
- app/views/layouts/homepage.html.erb
|
|
362
339
|
- app/views/layouts/page.html.erb
|
|
363
|
-
- app/views/layouts/panda/cms/application.html.erb
|
|
364
340
|
- app/views/layouts/panda/cms/public.html.erb
|
|
365
341
|
- app/views/panda/cms/admin/dashboard/show.html.erb
|
|
342
|
+
- app/views/panda/cms/admin/files/_file_details.html.erb
|
|
366
343
|
- app/views/panda/cms/admin/files/index.html.erb
|
|
367
344
|
- app/views/panda/cms/admin/files/show.html.erb
|
|
368
345
|
- app/views/panda/cms/admin/forms/edit.html.erb
|
|
369
346
|
- app/views/panda/cms/admin/forms/index.html.erb
|
|
370
347
|
- app/views/panda/cms/admin/forms/new.html.erb
|
|
371
348
|
- app/views/panda/cms/admin/forms/show.html.erb
|
|
349
|
+
- app/views/panda/cms/admin/menus/_menu_item_fields.html.erb
|
|
350
|
+
- app/views/panda/cms/admin/menus/edit.html.erb
|
|
372
351
|
- app/views/panda/cms/admin/menus/index.html.erb
|
|
352
|
+
- app/views/panda/cms/admin/menus/new.html.erb
|
|
373
353
|
- app/views/panda/cms/admin/pages/edit.html.erb
|
|
374
354
|
- app/views/panda/cms/admin/pages/index.html.erb
|
|
375
355
|
- app/views/panda/cms/admin/pages/new.html.erb
|
|
@@ -381,22 +361,16 @@ files:
|
|
|
381
361
|
- app/views/panda/cms/admin/settings/bulk_editor/new.html.erb
|
|
382
362
|
- app/views/panda/cms/admin/settings/index.html.erb
|
|
383
363
|
- app/views/panda/cms/admin/settings/insta.html
|
|
384
|
-
- app/views/panda/cms/admin/shared/_breadcrumbs.html.erb
|
|
385
|
-
- app/views/panda/cms/admin/shared/_flash.html.erb
|
|
386
|
-
- app/views/panda/cms/admin/shared/_sidebar.html.erb
|
|
387
364
|
- app/views/panda/cms/form_mailer/notification_email.html.erb
|
|
388
365
|
- app/views/panda/cms/shared/_editor.html.erb
|
|
389
366
|
- app/views/panda/cms/shared/_favicons.html.erb
|
|
390
|
-
- app/views/panda/cms/shared/_footer.html.erb
|
|
391
|
-
- app/views/panda/cms/shared/_header.html.erb
|
|
392
|
-
- app/views/panda/cms/shared/_importmap.html.erb
|
|
393
367
|
- app/views/shared/_footer.html.erb
|
|
394
368
|
- app/views/shared/_header.html.erb
|
|
369
|
+
- config/brakeman.ignore
|
|
395
370
|
- config/importmap.rb
|
|
396
|
-
- config/initializers/inflections.rb
|
|
397
371
|
- config/initializers/panda/cms.rb
|
|
398
372
|
- config/initializers/panda/cms/form_errors.rb
|
|
399
|
-
- config/initializers/panda/cms/healthcheck_log_silencer.rb
|
|
373
|
+
- config/initializers/panda/cms/healthcheck_log_silencer.rb.disabled
|
|
400
374
|
- config/initializers/zeitwork.rb
|
|
401
375
|
- config/locales/en.yml
|
|
402
376
|
- config/puma/test.rb
|
|
@@ -447,6 +421,14 @@ files:
|
|
|
447
421
|
- db/migrate/20250126234001_create_panda_social_instagram_posts.rb
|
|
448
422
|
- db/migrate/20250809231125_migrate_users_to_panda_core.rb
|
|
449
423
|
- db/migrate/20250811111000_make_post_user_references_nullable.rb
|
|
424
|
+
- db/migrate/20251104150640_add_cached_last_updated_at_to_panda_cms_pages.rb
|
|
425
|
+
- db/migrate/20251104172242_add_page_type_to_panda_cms_pages.rb
|
|
426
|
+
- db/migrate/20251104172638_set_page_types_for_existing_pages.rb
|
|
427
|
+
- db/migrate/20251105000001_add_pending_review_status_to_pages_and_posts.panda_cms.rb
|
|
428
|
+
- db/migrate/20251109131150_add_seo_fields_to_pages.rb
|
|
429
|
+
- db/migrate/20251109131205_add_seo_fields_to_posts.rb
|
|
430
|
+
- db/migrate/20251110114258_add_spam_tracking_to_form_submissions.rb
|
|
431
|
+
- db/migrate/20251110122812_add_performance_indexes_to_pages_and_redirects.rb
|
|
450
432
|
- db/migrate/migrate
|
|
451
433
|
- db/seeds.rb
|
|
452
434
|
- lib/generators/panda/cms/install_generator.rb
|
|
@@ -455,16 +437,25 @@ files:
|
|
|
455
437
|
- lib/panda/cms.rb
|
|
456
438
|
- lib/panda/cms/asset_loader.rb
|
|
457
439
|
- lib/panda/cms/bulk_editor.rb
|
|
440
|
+
- lib/panda/cms/debug.rb
|
|
458
441
|
- lib/panda/cms/demo_site_generator.rb
|
|
459
442
|
- lib/panda/cms/engine.rb
|
|
443
|
+
- lib/panda/cms/engine/asset_config.rb
|
|
444
|
+
- lib/panda/cms/engine/autoload_config.rb
|
|
445
|
+
- lib/panda/cms/engine/backtrace_config.rb
|
|
446
|
+
- lib/panda/cms/engine/core_config.rb
|
|
447
|
+
- lib/panda/cms/engine/helper_config.rb
|
|
448
|
+
- lib/panda/cms/engine/route_config.rb
|
|
449
|
+
- lib/panda/cms/engine/view_component_config.rb
|
|
460
450
|
- lib/panda/cms/exceptions_app.rb
|
|
451
|
+
- lib/panda/cms/features.rb
|
|
461
452
|
- lib/panda/cms/railtie.rb
|
|
462
453
|
- lib/panda/cms/slug.rb
|
|
463
|
-
- lib/tasks/assets.rake
|
|
464
454
|
- lib/tasks/panda/cms/install.rake
|
|
465
455
|
- lib/tasks/panda/cms/migrations.rake
|
|
466
456
|
- lib/tasks/panda/social/instagram.rake
|
|
467
457
|
- lib/tasks/panda_cms.rake
|
|
458
|
+
- lib/tasks/panda_cms_tasks.rake
|
|
468
459
|
- lib/templates/erb/scaffold/_form.html.erb.tt
|
|
469
460
|
- lib/templates/erb/scaffold/edit.html.erb.tt
|
|
470
461
|
- lib/templates/erb/scaffold/index.html.erb.tt
|
|
@@ -519,7 +510,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
519
510
|
- !ruby/object:Gem::Version
|
|
520
511
|
version: '0'
|
|
521
512
|
requirements: []
|
|
522
|
-
rubygems_version: 3.
|
|
513
|
+
rubygems_version: 3.7.2
|
|
523
514
|
specification_version: 4
|
|
524
515
|
summary: Better websites on Rails.
|
|
525
516
|
test_files: []
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<main class="overflow-auto flex-1 h-full min-h-full max-h-full">
|
|
2
|
-
<div class="overflow-auto px-2 pt-4 mx-auto sm:px-6 lg:px-6">
|
|
3
|
-
<%= heading %>
|
|
4
|
-
<%= tab_bar %>
|
|
5
|
-
<%# I mean, you can edit this CSS if you want, but I hope you want to lose 2 hours to iFrame joy? %>
|
|
6
|
-
<section class="flex-auto h-[calc(100vh-10rem)]">
|
|
7
|
-
<div class="flex-1 mt-4 w-full h-full">
|
|
8
|
-
<%= content %>
|
|
9
|
-
</div>
|
|
10
|
-
<%= slideover %>
|
|
11
|
-
</section>
|
|
12
|
-
</div>
|
|
13
|
-
</main>
|