panda-cms 0.7.3 → 0.7.5
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 +40 -5
- data/Rakefile +2 -0
- 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 +27 -36
- data/app/components/panda/cms/admin/flash_message_component.html.erb +2 -2
- data/app/components/panda/cms/admin/heading_component.rb +5 -4
- data/app/components/panda/cms/admin/panel_component.rb +2 -2
- data/app/components/panda/cms/admin/statistics_component.rb +1 -2
- data/app/components/panda/cms/admin/user_activity_component.html.erb +3 -1
- data/app/components/panda/cms/admin/user_activity_component.rb +8 -21
- data/app/components/panda/cms/code_component.rb +8 -4
- data/app/components/panda/cms/menu_component.rb +7 -6
- data/app/components/panda/cms/page_menu_component.rb +15 -17
- data/app/components/panda/cms/rich_text_component.rb +5 -6
- data/app/components/panda/cms/text_component.rb +6 -7
- data/app/constraints/panda/cms/admin_constraint.rb +4 -1
- data/app/controllers/panda/cms/admin/block_contents_controller.rb +0 -1
- data/app/controllers/panda/cms/admin/dashboard_controller.rb +13 -9
- data/app/controllers/panda/cms/admin/forms_controller.rb +0 -3
- data/app/controllers/panda/cms/admin/my_profile_controller.rb +44 -0
- data/app/controllers/panda/cms/admin/pages_controller.rb +15 -4
- data/app/controllers/panda/cms/admin/posts_controller.rb +6 -22
- data/app/controllers/panda/cms/admin/sessions_controller.rb +3 -5
- data/app/controllers/panda/cms/admin/settings/bulk_editor_controller.rb +32 -25
- data/app/controllers/panda/cms/admin/settings_controller.rb +14 -10
- data/app/controllers/panda/cms/application_controller.rb +7 -2
- data/app/controllers/panda/cms/errors_controller.rb +5 -2
- data/app/controllers/panda/cms/form_submissions_controller.rb +4 -0
- data/app/controllers/panda/cms/pages_controller.rb +40 -35
- data/app/controllers/panda/cms/posts_controller.rb +2 -0
- data/app/helpers/panda/cms/admin/files_helper.rb +5 -1
- data/app/helpers/panda/cms/admin/pages_helper.rb +5 -1
- data/app/helpers/panda/cms/asset_helper.rb +182 -0
- data/app/helpers/panda/cms/pages_helper.rb +2 -0
- data/app/helpers/panda/cms/posts_helper.rb +2 -0
- data/app/helpers/panda/cms/theme_helper.rb +2 -0
- data/app/javascript/panda/cms/controllers/editor_form_controller.js +59 -6
- data/app/javascript/panda/cms/controllers/index.js +5 -9
- data/app/javascript/panda/cms/controllers/slug_controller.js +64 -31
- data/app/javascript/panda/cms/controllers/theme_form_controller.js +25 -0
- data/app/javascript/panda/cms/stimulus-loading.js +39 -0
- data/app/javascript/panda_cms/stimulus-loading.js +39 -0
- data/app/jobs/panda/cms/application_job.rb +2 -0
- data/app/jobs/panda/cms/record_visit_job.rb +14 -14
- data/app/mailers/panda/cms/application_mailer.rb +2 -0
- data/app/mailers/panda/cms/form_mailer.rb +3 -1
- data/app/models/panda/cms/application_record.rb +3 -0
- data/app/models/panda/cms/block.rb +12 -17
- data/app/models/panda/cms/block_content.rb +7 -6
- data/app/models/panda/cms/breadcrumb.rb +2 -0
- data/app/models/panda/cms/current.rb +2 -0
- data/app/models/panda/cms/form.rb +2 -0
- data/app/models/panda/cms/form_submission.rb +2 -0
- data/app/models/panda/cms/menu.rb +12 -9
- data/app/models/panda/cms/menu_item.rb +10 -6
- data/app/models/panda/cms/page.rb +31 -16
- data/app/models/panda/cms/post.rb +12 -10
- data/app/models/panda/cms/redirect.rb +9 -1
- data/app/models/panda/cms/template.rb +17 -13
- data/app/models/panda/cms/user.rb +2 -0
- data/app/models/panda/cms/visit.rb +3 -1
- data/app/models/panda/social/instagram_post.rb +17 -0
- data/app/services/panda/cms/html_to_editor_js_converter.rb +10 -15
- data/app/services/panda/social/instagram_feed_service.rb +63 -0
- data/app/views/layouts/different_page.html.erb +6 -0
- data/app/views/layouts/homepage.html.erb +37 -0
- data/app/views/layouts/page.html.erb +18 -0
- data/app/views/layouts/panda/cms/application.html.erb +1 -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 +14 -8
- 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 +3 -1
- data/app/views/panda/cms/admin/shared/_sidebar.html.erb +1 -1
- data/app/views/panda/cms/shared/_header.html.erb +14 -4
- data/app/views/panda/cms/shared/_importmap.html.erb +2 -1
- data/app/views/shared/_footer.html.erb +3 -0
- data/app/views/shared/_header.html.erb +11 -0
- data/config/importmap.rb +2 -0
- data/config/initializers/inflections.rb +2 -0
- data/config/initializers/panda/cms/form_errors.rb +20 -21
- data/config/initializers/panda/cms/healthcheck_log_silencer.rb +2 -0
- data/config/initializers/panda/cms.rb +2 -0
- data/config/initializers/zeitwork.rb +2 -0
- data/config/locales/en.yml +5 -0
- data/config/puma/test.rb +3 -1
- data/config/routes.rb +11 -8
- data/db/migrate/20240205223709_create_panda_cms_pages.rb +2 -0
- data/db/migrate/20240219213327_create_panda_cms_page_versions.rb +2 -0
- data/db/migrate/20240303002805_create_panda_cms_templates.rb +4 -1
- data/db/migrate/20240303003434_create_panda_cms_template_versions.rb +2 -0
- data/db/migrate/20240303022441_create_panda_cms_blocks.rb +4 -1
- data/db/migrate/20240303024256_create_panda_cms_block_contents.rb +2 -0
- data/db/migrate/20240303024746_create_panda_cms_block_content_versions.rb +2 -0
- data/db/migrate/20240303233238_add_panda_cms_menu_table.rb +2 -0
- data/db/migrate/20240303234724_add_panda_cms_menu_item_table.rb +2 -0
- data/db/migrate/20240304134343_add_parent_id_to_panda_cms_pages.rb +2 -0
- data/db/migrate/20240315125411_add_status_to_panda_cms_pages.rb +7 -5
- data/db/migrate/20240315125421_add_nested_sets_to_panda_cms_pages.rb +2 -0
- data/db/migrate/20240316212822_add_kind_to_panda_cms_menus.rb +3 -1
- data/db/migrate/20240316221425_add_start_page_to_panda_cms_menus.rb +2 -0
- data/db/migrate/20240316230706_add_nested_to_panda_cms_menu_items.rb +2 -0
- data/db/migrate/20240317010532_create_panda_cms_users.rb +2 -0
- data/db/migrate/20240317161534_add_max_uses_to_panda_cms_template.rb +2 -0
- data/db/migrate/20240317163053_reset_counter_cache_on_panda_cms_template.rb +2 -0
- data/db/migrate/20240317214827_create_panda_cms_redirects.rb +2 -0
- data/db/migrate/20240317230622_create_panda_cms_visits.rb +2 -0
- data/db/migrate/20240324205703_create_active_storage_tables.active_storage.rb +5 -2
- data/db/migrate/20240408084718_default_panda_cms_users_admin_to_false.rb +2 -0
- data/db/migrate/20240701225422_add_service_name_to_active_storage_blobs.active_storage.rb +8 -6
- data/db/migrate/20240701225423_create_active_storage_variant_records.active_storage.rb +2 -0
- data/db/migrate/20240701225424_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb +2 -0
- data/db/migrate/20240804235210_create_panda_cms_forms.rb +2 -0
- data/db/migrate/20240805013612_create_panda_cms_form_submissions.rb +2 -0
- data/db/migrate/20240805121123_create_panda_cms_posts.rb +3 -1
- data/db/migrate/20240805123104_create_panda_cms_post_versions.rb +2 -0
- data/db/migrate/20240806112735_fix_panda_cms_visits_column_names.rb +2 -0
- data/db/migrate/20240806204412_add_completion_path_to_panda_cms_forms.rb +2 -0
- data/db/migrate/20240820081917_change_form_submissions_to_submission_count.rb +2 -0
- data/db/migrate/20240923234535_add_depth_to_panda_cms_menus.rb +6 -4
- data/db/migrate/20241031205109_add_cached_content_to_panda_cms_block_contents.rb +2 -0
- data/db/migrate/20241119214548_convert_post_content_to_editor_js.rb +2 -0
- data/db/migrate/20241120000419_remove_post_tag_references.rb +2 -0
- data/db/migrate/20241120110943_add_editor_js_to_posts.rb +2 -0
- data/db/migrate/20241120113859_add_cached_content_to_panda_cms_posts.rb +2 -0
- data/db/migrate/20241123234140_remove_post_tag_id_from_posts.rb +2 -0
- data/db/migrate/20250106223303_add_author_id_to_panda_cms_posts.rb +2 -0
- data/db/migrate/20250120235542_remove_paper_trail.rb +56 -0
- data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +16 -0
- data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +7 -0
- data/db/seeds.rb +2 -0
- data/lib/generators/panda/cms/install_generator.rb +2 -0
- data/lib/panda/cms/asset_loader.rb +390 -0
- data/lib/panda/cms/bulk_editor.rb +7 -3
- data/lib/panda/cms/demo_site_generator.rb +27 -4
- data/lib/panda/cms/editor_js/blocks/alert.rb +2 -0
- data/lib/panda/cms/editor_js/blocks/base.rb +2 -0
- data/lib/panda/cms/editor_js/blocks/header.rb +2 -0
- data/lib/panda/cms/editor_js/blocks/image.rb +3 -0
- data/lib/panda/cms/editor_js/blocks/list.rb +2 -0
- data/lib/panda/cms/editor_js/blocks/paragraph.rb +3 -0
- data/lib/panda/cms/editor_js/blocks/quote.rb +3 -0
- data/lib/panda/cms/editor_js/blocks/table.rb +3 -1
- data/lib/panda/cms/editor_js/renderer.rb +3 -0
- data/lib/panda/cms/editor_js.rb +2 -0
- data/lib/panda/cms/editor_js_content.rb +50 -23
- data/lib/panda/cms/engine.rb +36 -37
- data/lib/panda/cms/exceptions_app.rb +2 -0
- data/lib/panda/cms/railtie.rb +2 -0
- data/lib/panda/cms/slug.rb +3 -1
- data/lib/panda-cms/version.rb +3 -1
- data/lib/panda-cms.rb +17 -2
- data/lib/tasks/assets.rake +547 -0
- data/lib/tasks/panda/cms/install.rake +25 -0
- data/lib/tasks/panda/social/instagram.rake +20 -0
- data/lib/tasks/panda_cms.rake +3 -30
- 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
- data/public/panda-cms-assets/manifest.json +20 -0
- data/public/panda-cms-assets/panda-cms-0.7.4.css +26 -0
- data/public/panda-cms-assets/panda-cms-0.7.4.js +150 -0
- metadata +71 -438
- 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
@@ -12,9 +12,7 @@ module Panda
|
|
12
12
|
|
13
13
|
KIND = "rich_text"
|
14
14
|
|
15
|
-
attr_accessor :editable
|
16
|
-
attr_accessor :content
|
17
|
-
attr_accessor :options
|
15
|
+
attr_accessor :editable, :content, :options
|
18
16
|
|
19
17
|
def initialize(key: :text_component, text: "Lorem ipsum...", editable: true, **options)
|
20
18
|
@key = key
|
@@ -27,7 +25,8 @@ module Panda
|
|
27
25
|
def before_render
|
28
26
|
@editable &&= params[:embed_id].present? && params[:embed_id] == Current.page.id && Current.user.admin?
|
29
27
|
|
30
|
-
block = Panda::CMS::Block.find_by(kind: "rich_text", key: @key,
|
28
|
+
block = Panda::CMS::Block.find_by(kind: "rich_text", key: @key,
|
29
|
+
panda_cms_template_id: Current.page.panda_cms_template_id)
|
31
30
|
raise ComponentError, "Block not found for key: #{@key}" unless block
|
32
31
|
|
33
32
|
block_content = block.block_contents.find_by(panda_cms_page_id: Current.page.id)
|
@@ -65,7 +64,7 @@ module Panda
|
|
65
64
|
# Ensure the content is properly structured
|
66
65
|
{
|
67
66
|
"time" => parsed["time"] || Time.current.to_i * 1000,
|
68
|
-
"blocks" => parsed["blocks"].map
|
67
|
+
"blocks" => parsed["blocks"].map do |block|
|
69
68
|
{
|
70
69
|
"type" => block["type"],
|
71
70
|
"data" => block["data"].merge(
|
@@ -73,7 +72,7 @@ module Panda
|
|
73
72
|
),
|
74
73
|
"tunes" => block["tunes"]
|
75
74
|
}.compact
|
76
|
-
|
75
|
+
end,
|
77
76
|
"version" => parsed["version"] || "2.28.2"
|
78
77
|
}
|
79
78
|
else
|
@@ -25,10 +25,10 @@ module Panda
|
|
25
25
|
content_tag(:span, @content, @options, false) # Don't escape the content
|
26
26
|
rescue
|
27
27
|
if !Rails.env.production? || is_defined?(Sentry)
|
28
|
-
raise Panda::CMS::MissingBlockError
|
29
|
-
else
|
30
|
-
false
|
28
|
+
raise Panda::CMS::MissingBlockError, "Block with key #{@key} not found for page #{Current.page.title}"
|
31
29
|
end
|
30
|
+
|
31
|
+
false
|
32
32
|
end
|
33
33
|
|
34
34
|
#
|
@@ -45,11 +45,10 @@ module Panda
|
|
45
45
|
def before_render
|
46
46
|
@editable &&= params[:embed_id].present? && params[:embed_id] == Current.page.id
|
47
47
|
|
48
|
-
block = Panda::CMS::Block.find_by(kind: KIND, key: @key,
|
48
|
+
block = Panda::CMS::Block.find_by(kind: KIND, key: @key,
|
49
|
+
panda_cms_template_id: Current.page.panda_cms_template_id)
|
49
50
|
|
50
|
-
if block.nil?
|
51
|
-
return false
|
52
|
-
end
|
51
|
+
return false if block.nil?
|
53
52
|
|
54
53
|
block_content = block.block_contents.find_by(panda_cms_page_id: Current.page.id)
|
55
54
|
plain_text = block_content&.content.to_s
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
5
|
class AdminConstraint
|
@@ -11,7 +13,8 @@ module Panda
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def current_user(request)
|
14
|
-
|
16
|
+
user_id = request.session[:user_id]
|
17
|
+
User.find_by(id: user_id)
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
@@ -6,7 +6,6 @@ module Panda
|
|
6
6
|
class BlockContentsController < ApplicationController
|
7
7
|
before_action :set_page, only: %i[update]
|
8
8
|
before_action :set_block_content, only: %i[update]
|
9
|
-
before_action :set_paper_trail_whodunnit, only: %i[update]
|
10
9
|
before_action :authenticate_admin_user!
|
11
10
|
|
12
11
|
# @type PATCH/PUT
|
@@ -1,19 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "groupdate"
|
2
4
|
|
3
5
|
module Panda
|
4
6
|
module CMS
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
module Admin
|
8
|
+
class DashboardController < ApplicationController
|
9
|
+
before_action :set_initial_breadcrumb, only: %i[show]
|
10
|
+
before_action :authenticate_admin_user!
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
# GET /admin
|
13
|
+
def show
|
14
|
+
end
|
12
15
|
|
13
|
-
|
16
|
+
private
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
def set_initial_breadcrumb
|
19
|
+
add_breadcrumb "Dashboard", Panda::CMS.route_namespace
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -5,7 +5,6 @@ module Panda
|
|
5
5
|
module Admin
|
6
6
|
class FormsController < ApplicationController
|
7
7
|
before_action :set_initial_breadcrumb, only: %i[index show]
|
8
|
-
# before_action :set_paper_trail_whodunnit, only: %i[create update]
|
9
8
|
before_action :authenticate_admin_user!
|
10
9
|
|
11
10
|
# Lists all forms
|
@@ -39,8 +38,6 @@ module Panda
|
|
39
38
|
add_breadcrumb "Forms", admin_forms_path
|
40
39
|
end
|
41
40
|
|
42
|
-
private
|
43
|
-
|
44
41
|
# Only allow a list of trusted parameters through
|
45
42
|
# @type private
|
46
43
|
# @return ActionController::StrongParameters
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Panda
|
4
|
+
module CMS
|
5
|
+
module Admin
|
6
|
+
class MyProfileController < ApplicationController
|
7
|
+
before_action :set_initial_breadcrumb, only: %i[edit update]
|
8
|
+
before_action :authenticate_admin_user!
|
9
|
+
|
10
|
+
# Shows the edit form for the current user's profile
|
11
|
+
# @type GET
|
12
|
+
# @return void
|
13
|
+
def edit
|
14
|
+
render :edit, locals: {user: current_user}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Updates the current user's profile
|
18
|
+
# @type PATCH/PUT
|
19
|
+
# @return void
|
20
|
+
def update
|
21
|
+
if current_user.update(user_params)
|
22
|
+
flash[:success] = "Your profile has been updated successfully."
|
23
|
+
redirect_to edit_admin_my_profile_path
|
24
|
+
else
|
25
|
+
render :edit, locals: {user: current_user}, status: :unprocessable_entity
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def set_initial_breadcrumb
|
32
|
+
add_breadcrumb "My Profile", edit_admin_my_profile_path
|
33
|
+
end
|
34
|
+
|
35
|
+
# Only allow a list of trusted parameters through
|
36
|
+
# @type private
|
37
|
+
# @return ActionController::StrongParameters
|
38
|
+
def user_params
|
39
|
+
params.require(:user).permit(:firstname, :lastname, :email, :current_theme)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -5,7 +5,6 @@ module Panda
|
|
5
5
|
module Admin
|
6
6
|
class PagesController < ApplicationController
|
7
7
|
before_action :set_initial_breadcrumb, only: %i[index edit new create update]
|
8
|
-
before_action :set_paper_trail_whodunnit, only: %i[create update]
|
9
8
|
before_action :authenticate_admin_user!
|
10
9
|
|
11
10
|
# Lists all pages which can be managed by the administrator
|
@@ -34,11 +33,20 @@ module Panda
|
|
34
33
|
# POST /admin/pages
|
35
34
|
def create
|
36
35
|
page = Panda::CMS::Page.new(page_params)
|
36
|
+
|
37
|
+
# Normalize empty path to nil so presence validation triggers
|
38
|
+
page.path = nil if page.path.blank?
|
39
|
+
|
40
|
+
# Set the full path before validation if we have a parent
|
41
|
+
if page.parent && page.parent.path != "/" && page.path.present? && !page.path.start_with?(page.parent.path)
|
42
|
+
# Only prepend parent path if it's not already included
|
43
|
+
page.path = page.parent.path + page.path
|
44
|
+
end
|
45
|
+
|
37
46
|
if page.save
|
38
|
-
page.update(path: page.parent.path + page.path) unless page.parent.path == "/"
|
39
47
|
redirect_to edit_admin_page_path(page), notice: "The page was successfully created."
|
40
48
|
else
|
41
|
-
flash[:error] =
|
49
|
+
flash.now[:error] = page.errors.full_messages.to_sentence
|
42
50
|
locals = setup_new_page_form(page: page)
|
43
51
|
render :new, locals: locals, status: :unprocessable_entity
|
44
52
|
end
|
@@ -76,7 +84,10 @@ module Panda
|
|
76
84
|
|
77
85
|
def setup_new_page_form(page:)
|
78
86
|
add_breadcrumb "Add Page", new_admin_page_path
|
79
|
-
{
|
87
|
+
{
|
88
|
+
page: page,
|
89
|
+
available_templates: Panda::CMS::Template.available
|
90
|
+
}
|
80
91
|
end
|
81
92
|
|
82
93
|
# Only allow a list of trusted parameters through.
|
@@ -6,8 +6,7 @@ module Panda
|
|
6
6
|
module CMS
|
7
7
|
module Admin
|
8
8
|
class PostsController < ApplicationController
|
9
|
-
before_action :set_initial_breadcrumb, only: %i[index new
|
10
|
-
before_action :set_paper_trail_whodunnit, only: %i[create update]
|
9
|
+
before_action :set_initial_breadcrumb, only: %i[index edit new create update]
|
11
10
|
before_action :authenticate_admin_user!
|
12
11
|
|
13
12
|
# Get all posts
|
@@ -29,20 +28,7 @@ module Panda
|
|
29
28
|
# @type GET
|
30
29
|
def edit
|
31
30
|
add_breadcrumb post.title, edit_admin_post_path(post.admin_param)
|
32
|
-
|
33
|
-
# Get the latest version's content or fall back to post's content
|
34
|
-
preserved_content = if post.versions.exists?
|
35
|
-
reified_post = post.versions.last.reify
|
36
|
-
reified_post&.content || post.content
|
37
|
-
else
|
38
|
-
post.content
|
39
|
-
end
|
40
|
-
|
41
|
-
render :edit, locals: {
|
42
|
-
post: post,
|
43
|
-
url: admin_post_path(post.admin_param),
|
44
|
-
preserved_content: preserved_content
|
45
|
-
}
|
31
|
+
render :edit, locals: {post: post}
|
46
32
|
end
|
47
33
|
|
48
34
|
# POST /admin/posts
|
@@ -53,7 +39,7 @@ module Panda
|
|
53
39
|
|
54
40
|
if @post.save
|
55
41
|
Rails.logger.debug "Post saved successfully"
|
56
|
-
redirect_to edit_admin_post_path(@post.admin_param),
|
42
|
+
redirect_to edit_admin_post_path(@post.admin_param), notice: "The post was successfully created!"
|
57
43
|
else
|
58
44
|
Rails.logger.debug "Post save failed: #{@post.errors.full_messages.inspect}"
|
59
45
|
flash.now[:error] = @post.errors.full_messages.join(", ")
|
@@ -75,17 +61,15 @@ module Panda
|
|
75
61
|
if post.update(update_params)
|
76
62
|
Rails.logger.debug "Post updated successfully"
|
77
63
|
add_breadcrumb post.title, edit_admin_post_path(post.admin_param)
|
78
|
-
|
79
|
-
|
80
|
-
flash: {success: "The post was successfully updated!"}
|
64
|
+
flash[:success] = "The post was successfully updated"
|
65
|
+
redirect_to edit_admin_post_path(post.admin_param), status: :see_other
|
81
66
|
else
|
82
67
|
Rails.logger.debug "Post update failed: #{post.errors.full_messages.inspect}"
|
83
68
|
Rails.logger.debug "Preserving content: #{post_params[:content].inspect}"
|
84
|
-
flash[:error] = post.errors.full_messages.join(", ")
|
85
69
|
add_breadcrumb post.title.presence || "Edit Post", edit_admin_post_path(post.admin_param)
|
70
|
+
flash.now[:error] = post.errors.full_messages.join(", ")
|
86
71
|
render :edit, locals: {
|
87
72
|
post: post,
|
88
|
-
url: admin_post_path(post.admin_param),
|
89
73
|
preserved_content: post_params[:content]
|
90
74
|
}, status: :unprocessable_entity
|
91
75
|
end
|
@@ -27,9 +27,7 @@ module Panda
|
|
27
27
|
|
28
28
|
# Always create the first user as admin, regardless of what our settings look like
|
29
29
|
# else we can't ever really login. :)
|
30
|
-
if !create_as_admin
|
31
|
-
create_as_admin = true if !create_as_admin && Panda::CMS::User.count.zero?
|
32
|
-
end
|
30
|
+
create_as_admin = true if !create_as_admin && Panda::CMS::User.count.zero?
|
33
31
|
|
34
32
|
if user_info["first_name"] && user_info["last_name"]
|
35
33
|
firstname = user_info["first_name"]
|
@@ -55,9 +53,9 @@ module Panda
|
|
55
53
|
return
|
56
54
|
end
|
57
55
|
|
58
|
-
|
56
|
+
unless user.admin?
|
59
57
|
# User can't be found with this email address or can't login
|
60
|
-
Rails.logger.error "User ID #{user.id} attempted admin login, is not admin."
|
58
|
+
Rails.logger.error "User ID #{user.id} attempted admin login, is not admin."
|
61
59
|
redirect_to admin_login_path, flash: {error: t("panda.cms.admin.sessions.create.error")}
|
62
60
|
return
|
63
61
|
end
|
@@ -1,36 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
|
-
|
4
|
-
|
5
|
+
module Admin
|
6
|
+
module Settings
|
7
|
+
class BulkEditorController < ApplicationController
|
8
|
+
before_action :set_initial_breadcrumb, only: %i[new]
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
def new
|
11
|
+
@json_data = BulkEditor.export
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def create
|
15
|
+
begin
|
16
|
+
debug_output = BulkEditor.import(params[:site_content])
|
17
|
+
rescue JSON::ParserError
|
18
|
+
redirect_to admin_settings_bulk_editor_path,
|
19
|
+
flash: {error: "Error parsing content; are you sure this update is valid? Reverting..."}
|
20
|
+
return
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
23
|
+
# Grab the latest content back so it's all formatted properly
|
24
|
+
@json_data = BulkEditor.export
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
if debug_output[:error].empty? && debug_output[:warning].empty? && debug_output[:success].empty?
|
27
|
+
redirect_to admin_settings_bulk_editor_path, flash: {success: "No changes were found!"}
|
28
|
+
else
|
29
|
+
@debug = debug_output
|
30
|
+
render :new, flash: {warning: "Please review the output below for more information."}
|
31
|
+
end
|
32
|
+
end
|
28
33
|
|
29
|
-
|
34
|
+
private
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
def set_initial_breadcrumb
|
37
|
+
add_breadcrumb "Settings", admin_settings_path
|
38
|
+
add_breadcrumb "Bulk Editor", "#"
|
39
|
+
end
|
40
|
+
end
|
34
41
|
end
|
35
42
|
end
|
36
43
|
end
|
@@ -1,19 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
module Admin
|
6
|
+
class SettingsController < ApplicationController
|
7
|
+
before_action :set_initial_breadcrumb, only: %i[index show]
|
8
|
+
before_action :authenticate_admin_user!
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
def index
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
13
|
+
def show
|
14
|
+
end
|
12
15
|
|
13
|
-
|
16
|
+
private
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
def set_initial_breadcrumb
|
19
|
+
add_breadcrumb "Settings", admin_settings_path
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
5
|
class ApplicationController < ::ActionController::Base
|
@@ -37,11 +39,14 @@ module Panda
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def authenticate_user!
|
40
|
-
redirect_to root_path, flash: {error: "Please login to view this!"} unless user_signed_in?
|
42
|
+
redirect_to main_app.root_path, flash: {error: "Please login to view this!"} unless user_signed_in?
|
41
43
|
end
|
42
44
|
|
43
45
|
def authenticate_admin_user!
|
44
|
-
|
46
|
+
return if user_signed_in? && current_user.admin?
|
47
|
+
|
48
|
+
redirect_to admin_login_path,
|
49
|
+
flash: {error: "Please login to view this!"}
|
45
50
|
end
|
46
51
|
|
47
52
|
# Required for paper_trail and seems as good as convention these days
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
5
|
class ErrorsController < ApplicationController
|
@@ -5,7 +7,8 @@ module Panda
|
|
5
7
|
|
6
8
|
def show
|
7
9
|
exception = request.env["action_dispatch.exception"]
|
8
|
-
status_code = exception.try(:status_code) || ActionDispatch::ExceptionWrapper.new(request.env,
|
10
|
+
status_code = exception.try(:status_code) || ActionDispatch::ExceptionWrapper.new(request.env,
|
11
|
+
exception).status_code
|
9
12
|
|
10
13
|
render view_for_code(status_code), status: status_code
|
11
14
|
end
|
@@ -17,7 +20,7 @@ module Panda
|
|
17
20
|
private
|
18
21
|
|
19
22
|
def view_for_code(code)
|
20
|
-
supported_error_codes.fetch(code
|
23
|
+
supported_error_codes.fetch(code, "404")
|
21
24
|
end
|
22
25
|
|
23
26
|
def supported_error_codes
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Panda
|
2
4
|
module CMS
|
3
5
|
class PagesController < ApplicationController
|
4
6
|
include ActionView::Helpers::TagHelper
|
5
7
|
|
6
|
-
before_action :check_login_required, only: [
|
7
|
-
before_action :handle_redirects, only: [
|
8
|
-
after_action :record_visit, only: [
|
8
|
+
before_action :check_login_required, only: %i[root show]
|
9
|
+
before_action :handle_redirects, only: %i[root show]
|
10
|
+
after_action :record_visit, only: %i[root show], unless: :ignore_visit?
|
9
11
|
|
10
12
|
def root
|
11
13
|
params[:path] = ""
|
@@ -14,15 +16,13 @@ module Panda
|
|
14
16
|
|
15
17
|
def show
|
16
18
|
page = if @overrides&.dig(:page_path_match)
|
17
|
-
Panda::CMS::Page.find_by(path: @overrides
|
19
|
+
Panda::CMS::Page.find_by(path: @overrides[:page_path_match])
|
18
20
|
else
|
19
|
-
Panda::CMS::Page.find_by(path: "
|
21
|
+
Panda::CMS::Page.find_by(path: "/#{params[:path]}")
|
20
22
|
end
|
21
23
|
|
22
24
|
Panda::CMS::Current.page = page || Panda::CMS::Page.find_by(path: "/404")
|
23
|
-
if @overrides
|
24
|
-
Panda::CMS::Current.page.title = @overrides&.dig(:title) || page.title
|
25
|
-
end
|
25
|
+
Panda::CMS::Current.page.title = @overrides&.dig(:title) || page.title if @overrides
|
26
26
|
|
27
27
|
layout = page&.template&.file_path
|
28
28
|
|
@@ -42,59 +42,64 @@ module Panda
|
|
42
42
|
private
|
43
43
|
|
44
44
|
def handle_redirects
|
45
|
-
current_path = "
|
45
|
+
current_path = "/#{params[:path]}"
|
46
46
|
redirect = Panda::CMS::Redirect.find_by(origin_path: current_path)
|
47
47
|
|
48
|
-
|
49
|
-
redirect.increment!(:visits)
|
48
|
+
return unless redirect
|
50
49
|
|
51
|
-
|
52
|
-
next_redirect = Panda::CMS::Redirect.find_by(origin_path: redirect.destination_path)
|
53
|
-
if next_redirect
|
54
|
-
next_redirect.increment!(:visits)
|
55
|
-
redirect_to next_redirect.destination_path, status: redirect.status_code and return
|
56
|
-
end
|
50
|
+
redirect.increment!(:visits)
|
57
51
|
|
58
|
-
|
52
|
+
# Check if the destination is also a redirect
|
53
|
+
next_redirect = Panda::CMS::Redirect.find_by(origin_path: redirect.destination_path)
|
54
|
+
if next_redirect
|
55
|
+
next_redirect.increment!(:visits)
|
56
|
+
redirect_to next_redirect.destination_path, status: redirect.status_code and return
|
59
57
|
end
|
58
|
+
|
59
|
+
redirect_to redirect.destination_path, status: redirect.status_code and return
|
60
60
|
end
|
61
61
|
|
62
62
|
def check_login_required
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
return unless Panda::CMS.config.require_login_to_view && !user_signed_in?
|
64
|
+
|
65
|
+
redirect_to panda_cms_maintenance_path and return
|
66
66
|
end
|
67
67
|
|
68
68
|
def ignore_visit?
|
69
69
|
# Ignore visits from bots (TODO: make this configurable)
|
70
70
|
return true if /bot/i.match?(request.user_agent)
|
71
71
|
# Ignore visits from Honeybadger
|
72
|
-
|
72
|
+
if request.headers.to_h.key?("Honeybadger-Token") || request.user_agent == "Honeybadger Uptime Check"
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
# Ignore visits where we're asking for PHP files
|
76
|
+
return true if request.path.ends_with?(".php")
|
73
77
|
|
78
|
+
# Otherwise, record the visit
|
74
79
|
false
|
75
80
|
end
|
76
81
|
|
77
82
|
def record_visit
|
78
83
|
RecordVisitJob.perform_later(
|
79
|
-
|
84
|
+
path: request.path,
|
85
|
+
user_id: Current.user&.id,
|
86
|
+
redirect_id: @redirect&.id,
|
87
|
+
page_id: Current.page&.id,
|
80
88
|
user_agent: request.user_agent,
|
81
|
-
referrer: request.referrer,
|
82
89
|
ip_address: request.remote_ip,
|
83
|
-
|
84
|
-
|
85
|
-
params: params.to_unsafe_h.except(:controller, :action, :path),
|
86
|
-
visited_at: Time.zone.now
|
90
|
+
referer: request.referer, # TODO: Fix the naming of this column
|
91
|
+
params: request.parameters
|
87
92
|
)
|
88
93
|
end
|
89
94
|
|
90
95
|
def create_redirect_if_path_changed
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
return unless path_changed? && path_was.present?
|
97
|
+
|
98
|
+
Panda::CMS::Redirect.create!(
|
99
|
+
origin_path: path_was,
|
100
|
+
destination_path: path,
|
101
|
+
status_code: 301
|
102
|
+
)
|
98
103
|
end
|
99
104
|
end
|
100
105
|
end
|