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.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -5
  3. data/Rakefile +2 -0
  4. data/app/assets/builds/panda.cms.css +2 -6
  5. data/app/assets/tailwind/application.css +178 -0
  6. data/app/assets/tailwind/tailwind.config.js +15 -0
  7. data/app/builders/panda/cms/form_builder.rb +27 -36
  8. data/app/components/panda/cms/admin/flash_message_component.html.erb +2 -2
  9. data/app/components/panda/cms/admin/heading_component.rb +5 -4
  10. data/app/components/panda/cms/admin/panel_component.rb +2 -2
  11. data/app/components/panda/cms/admin/statistics_component.rb +1 -2
  12. data/app/components/panda/cms/admin/user_activity_component.html.erb +3 -1
  13. data/app/components/panda/cms/admin/user_activity_component.rb +8 -21
  14. data/app/components/panda/cms/code_component.rb +8 -4
  15. data/app/components/panda/cms/menu_component.rb +7 -6
  16. data/app/components/panda/cms/page_menu_component.rb +15 -17
  17. data/app/components/panda/cms/rich_text_component.rb +5 -6
  18. data/app/components/panda/cms/text_component.rb +6 -7
  19. data/app/constraints/panda/cms/admin_constraint.rb +4 -1
  20. data/app/controllers/panda/cms/admin/block_contents_controller.rb +0 -1
  21. data/app/controllers/panda/cms/admin/dashboard_controller.rb +13 -9
  22. data/app/controllers/panda/cms/admin/forms_controller.rb +0 -3
  23. data/app/controllers/panda/cms/admin/my_profile_controller.rb +44 -0
  24. data/app/controllers/panda/cms/admin/pages_controller.rb +15 -4
  25. data/app/controllers/panda/cms/admin/posts_controller.rb +6 -22
  26. data/app/controllers/panda/cms/admin/sessions_controller.rb +3 -5
  27. data/app/controllers/panda/cms/admin/settings/bulk_editor_controller.rb +32 -25
  28. data/app/controllers/panda/cms/admin/settings_controller.rb +14 -10
  29. data/app/controllers/panda/cms/application_controller.rb +7 -2
  30. data/app/controllers/panda/cms/errors_controller.rb +5 -2
  31. data/app/controllers/panda/cms/form_submissions_controller.rb +4 -0
  32. data/app/controllers/panda/cms/pages_controller.rb +40 -35
  33. data/app/controllers/panda/cms/posts_controller.rb +2 -0
  34. data/app/helpers/panda/cms/admin/files_helper.rb +5 -1
  35. data/app/helpers/panda/cms/admin/pages_helper.rb +5 -1
  36. data/app/helpers/panda/cms/asset_helper.rb +182 -0
  37. data/app/helpers/panda/cms/pages_helper.rb +2 -0
  38. data/app/helpers/panda/cms/posts_helper.rb +2 -0
  39. data/app/helpers/panda/cms/theme_helper.rb +2 -0
  40. data/app/javascript/panda/cms/controllers/editor_form_controller.js +59 -6
  41. data/app/javascript/panda/cms/controllers/index.js +5 -9
  42. data/app/javascript/panda/cms/controllers/slug_controller.js +64 -31
  43. data/app/javascript/panda/cms/controllers/theme_form_controller.js +25 -0
  44. data/app/javascript/panda/cms/stimulus-loading.js +39 -0
  45. data/app/javascript/panda_cms/stimulus-loading.js +39 -0
  46. data/app/jobs/panda/cms/application_job.rb +2 -0
  47. data/app/jobs/panda/cms/record_visit_job.rb +14 -14
  48. data/app/mailers/panda/cms/application_mailer.rb +2 -0
  49. data/app/mailers/panda/cms/form_mailer.rb +3 -1
  50. data/app/models/panda/cms/application_record.rb +3 -0
  51. data/app/models/panda/cms/block.rb +12 -17
  52. data/app/models/panda/cms/block_content.rb +7 -6
  53. data/app/models/panda/cms/breadcrumb.rb +2 -0
  54. data/app/models/panda/cms/current.rb +2 -0
  55. data/app/models/panda/cms/form.rb +2 -0
  56. data/app/models/panda/cms/form_submission.rb +2 -0
  57. data/app/models/panda/cms/menu.rb +12 -9
  58. data/app/models/panda/cms/menu_item.rb +10 -6
  59. data/app/models/panda/cms/page.rb +31 -16
  60. data/app/models/panda/cms/post.rb +12 -10
  61. data/app/models/panda/cms/redirect.rb +9 -1
  62. data/app/models/panda/cms/template.rb +17 -13
  63. data/app/models/panda/cms/user.rb +2 -0
  64. data/app/models/panda/cms/visit.rb +3 -1
  65. data/app/models/panda/social/instagram_post.rb +17 -0
  66. data/app/services/panda/cms/html_to_editor_js_converter.rb +10 -15
  67. data/app/services/panda/social/instagram_feed_service.rb +63 -0
  68. data/app/views/layouts/different_page.html.erb +6 -0
  69. data/app/views/layouts/homepage.html.erb +37 -0
  70. data/app/views/layouts/page.html.erb +18 -0
  71. data/app/views/layouts/panda/cms/application.html.erb +1 -0
  72. data/app/views/panda/cms/admin/my_profile/edit.html.erb +35 -0
  73. data/app/views/panda/cms/admin/pages/index.html.erb +1 -1
  74. data/app/views/panda/cms/admin/pages/new.html.erb +14 -8
  75. data/app/views/panda/cms/admin/posts/_form.html.erb +10 -0
  76. data/app/views/panda/cms/admin/posts/edit.html.erb +3 -2
  77. data/app/views/panda/cms/admin/posts/index.html.erb +1 -1
  78. data/app/views/panda/cms/admin/settings/index.html.erb +3 -1
  79. data/app/views/panda/cms/admin/shared/_sidebar.html.erb +1 -1
  80. data/app/views/panda/cms/shared/_header.html.erb +14 -4
  81. data/app/views/panda/cms/shared/_importmap.html.erb +2 -1
  82. data/app/views/shared/_footer.html.erb +3 -0
  83. data/app/views/shared/_header.html.erb +11 -0
  84. data/config/importmap.rb +2 -0
  85. data/config/initializers/inflections.rb +2 -0
  86. data/config/initializers/panda/cms/form_errors.rb +20 -21
  87. data/config/initializers/panda/cms/healthcheck_log_silencer.rb +2 -0
  88. data/config/initializers/panda/cms.rb +2 -0
  89. data/config/initializers/zeitwork.rb +2 -0
  90. data/config/locales/en.yml +5 -0
  91. data/config/puma/test.rb +3 -1
  92. data/config/routes.rb +11 -8
  93. data/db/migrate/20240205223709_create_panda_cms_pages.rb +2 -0
  94. data/db/migrate/20240219213327_create_panda_cms_page_versions.rb +2 -0
  95. data/db/migrate/20240303002805_create_panda_cms_templates.rb +4 -1
  96. data/db/migrate/20240303003434_create_panda_cms_template_versions.rb +2 -0
  97. data/db/migrate/20240303022441_create_panda_cms_blocks.rb +4 -1
  98. data/db/migrate/20240303024256_create_panda_cms_block_contents.rb +2 -0
  99. data/db/migrate/20240303024746_create_panda_cms_block_content_versions.rb +2 -0
  100. data/db/migrate/20240303233238_add_panda_cms_menu_table.rb +2 -0
  101. data/db/migrate/20240303234724_add_panda_cms_menu_item_table.rb +2 -0
  102. data/db/migrate/20240304134343_add_parent_id_to_panda_cms_pages.rb +2 -0
  103. data/db/migrate/20240315125411_add_status_to_panda_cms_pages.rb +7 -5
  104. data/db/migrate/20240315125421_add_nested_sets_to_panda_cms_pages.rb +2 -0
  105. data/db/migrate/20240316212822_add_kind_to_panda_cms_menus.rb +3 -1
  106. data/db/migrate/20240316221425_add_start_page_to_panda_cms_menus.rb +2 -0
  107. data/db/migrate/20240316230706_add_nested_to_panda_cms_menu_items.rb +2 -0
  108. data/db/migrate/20240317010532_create_panda_cms_users.rb +2 -0
  109. data/db/migrate/20240317161534_add_max_uses_to_panda_cms_template.rb +2 -0
  110. data/db/migrate/20240317163053_reset_counter_cache_on_panda_cms_template.rb +2 -0
  111. data/db/migrate/20240317214827_create_panda_cms_redirects.rb +2 -0
  112. data/db/migrate/20240317230622_create_panda_cms_visits.rb +2 -0
  113. data/db/migrate/20240324205703_create_active_storage_tables.active_storage.rb +5 -2
  114. data/db/migrate/20240408084718_default_panda_cms_users_admin_to_false.rb +2 -0
  115. data/db/migrate/20240701225422_add_service_name_to_active_storage_blobs.active_storage.rb +8 -6
  116. data/db/migrate/20240701225423_create_active_storage_variant_records.active_storage.rb +2 -0
  117. data/db/migrate/20240701225424_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb +2 -0
  118. data/db/migrate/20240804235210_create_panda_cms_forms.rb +2 -0
  119. data/db/migrate/20240805013612_create_panda_cms_form_submissions.rb +2 -0
  120. data/db/migrate/20240805121123_create_panda_cms_posts.rb +3 -1
  121. data/db/migrate/20240805123104_create_panda_cms_post_versions.rb +2 -0
  122. data/db/migrate/20240806112735_fix_panda_cms_visits_column_names.rb +2 -0
  123. data/db/migrate/20240806204412_add_completion_path_to_panda_cms_forms.rb +2 -0
  124. data/db/migrate/20240820081917_change_form_submissions_to_submission_count.rb +2 -0
  125. data/db/migrate/20240923234535_add_depth_to_panda_cms_menus.rb +6 -4
  126. data/db/migrate/20241031205109_add_cached_content_to_panda_cms_block_contents.rb +2 -0
  127. data/db/migrate/20241119214548_convert_post_content_to_editor_js.rb +2 -0
  128. data/db/migrate/20241120000419_remove_post_tag_references.rb +2 -0
  129. data/db/migrate/20241120110943_add_editor_js_to_posts.rb +2 -0
  130. data/db/migrate/20241120113859_add_cached_content_to_panda_cms_posts.rb +2 -0
  131. data/db/migrate/20241123234140_remove_post_tag_id_from_posts.rb +2 -0
  132. data/db/migrate/20250106223303_add_author_id_to_panda_cms_posts.rb +2 -0
  133. data/db/migrate/20250120235542_remove_paper_trail.rb +56 -0
  134. data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +16 -0
  135. data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +7 -0
  136. data/db/seeds.rb +2 -0
  137. data/lib/generators/panda/cms/install_generator.rb +2 -0
  138. data/lib/panda/cms/asset_loader.rb +390 -0
  139. data/lib/panda/cms/bulk_editor.rb +7 -3
  140. data/lib/panda/cms/demo_site_generator.rb +27 -4
  141. data/lib/panda/cms/editor_js/blocks/alert.rb +2 -0
  142. data/lib/panda/cms/editor_js/blocks/base.rb +2 -0
  143. data/lib/panda/cms/editor_js/blocks/header.rb +2 -0
  144. data/lib/panda/cms/editor_js/blocks/image.rb +3 -0
  145. data/lib/panda/cms/editor_js/blocks/list.rb +2 -0
  146. data/lib/panda/cms/editor_js/blocks/paragraph.rb +3 -0
  147. data/lib/panda/cms/editor_js/blocks/quote.rb +3 -0
  148. data/lib/panda/cms/editor_js/blocks/table.rb +3 -1
  149. data/lib/panda/cms/editor_js/renderer.rb +3 -0
  150. data/lib/panda/cms/editor_js.rb +2 -0
  151. data/lib/panda/cms/editor_js_content.rb +50 -23
  152. data/lib/panda/cms/engine.rb +36 -37
  153. data/lib/panda/cms/exceptions_app.rb +2 -0
  154. data/lib/panda/cms/railtie.rb +2 -0
  155. data/lib/panda/cms/slug.rb +3 -1
  156. data/lib/panda-cms/version.rb +3 -1
  157. data/lib/panda-cms.rb +17 -2
  158. data/lib/tasks/assets.rake +547 -0
  159. data/lib/tasks/panda/cms/install.rake +25 -0
  160. data/lib/tasks/panda/social/instagram.rake +20 -0
  161. data/lib/tasks/panda_cms.rake +3 -30
  162. data/public/panda-cms-assets/editor-js/core/editorjs.min.js +83 -0
  163. data/public/panda-cms-assets/editor-js/plugins/embed.min.js +2 -0
  164. data/public/panda-cms-assets/editor-js/plugins/header.min.js +9 -0
  165. data/public/panda-cms-assets/editor-js/plugins/nested-list.min.js +2 -0
  166. data/public/panda-cms-assets/editor-js/plugins/paragraph.min.js +9 -0
  167. data/public/panda-cms-assets/editor-js/plugins/quote.min.js +2 -0
  168. data/public/panda-cms-assets/editor-js/plugins/simple-image.min.js +2 -0
  169. data/public/panda-cms-assets/editor-js/plugins/table.min.js +2 -0
  170. data/public/panda-cms-assets/manifest.json +20 -0
  171. data/public/panda-cms-assets/panda-cms-0.7.4.css +26 -0
  172. data/public/panda-cms-assets/panda-cms-0.7.4.js +150 -0
  173. metadata +71 -438
  174. data/app/models/action_text/rich_text_version.rb +0 -6
  175. data/app/models/panda/cms/block_content_version.rb +0 -8
  176. data/app/models/panda/cms/page_version.rb +0 -8
  177. data/app/models/panda/cms/post_version.rb +0 -8
  178. data/app/models/panda/cms/template_version.rb +0 -8
  179. data/app/models/panda/cms/version.rb +0 -8
  180. data/config/initializers/panda/cms/paper_trail.rb +0 -7
  181. data/db/migrate/20240904200605_create_action_text_tables.action_text.rb +0 -24
  182. data/db/migrate/20241119214549_remove_action_text_from_posts.rb +0 -9
@@ -0,0 +1,35 @@
1
+ <%= render Panda::CMS::Admin::ContainerComponent.new do |component| %>
2
+ <% component.with_heading(text: "My Profile", level: 1) %>
3
+
4
+ <%= panda_cms_form_with model: user,
5
+ url: admin_my_profile_path,
6
+ method: :patch,
7
+ data: { controller: "theme-form" } do |f| %>
8
+ <% if user.errors.any? %>
9
+ <div class="mb-4 p-4 bg-red-50 border border-red-200 rounded-md">
10
+ <div class="text-sm text-red-600">
11
+ <% user.errors.full_messages.each do |message| %>
12
+ <p><%= message %></p>
13
+ <% end %>
14
+ </div>
15
+ </div>
16
+ <% end %>
17
+
18
+ <div class="space-y-4">
19
+ <%= f.text_field :firstname %>
20
+
21
+ <%= f.text_field :lastname %>
22
+
23
+ <%= f.email_field :email %>
24
+
25
+ <%= f.select :current_theme,
26
+ [["Default", "default"], ["Sky", "sky"]],
27
+ { label: "Theme" },
28
+ data: { action: "change->theme-form#updateTheme" } %>
29
+ </div>
30
+
31
+ <%= f.submit "Update Profile",
32
+ class: "btn btn-primary mt-6",
33
+ data: { disable_with: "Saving..." } %>
34
+ <% end %>
35
+ <% end %>
@@ -12,7 +12,7 @@
12
12
  </div>
13
13
  <% end %>
14
14
  <% table.column("Status") { |page| render Panda::CMS::Admin::TagComponent.new(status: page.status) } %>
15
- <% table.column("Last Updated") { |page| render Panda::CMS::Admin::UserActivityComponent.new(whodunnit_to: page)} %>
15
+ <% table.column("Last Updated") { |page| render Panda::CMS::Admin::UserActivityComponent.new(model: page) } %>
16
16
  <% end %>
17
17
  <% else %>
18
18
  <div class="p-6 bg-error/10 text-error rounded-lg">
@@ -2,14 +2,20 @@
2
2
  <% component.with_heading(text: "Add Page", level: 1) do |heading| %>
3
3
  <% end %>
4
4
  <%= panda_cms_form_with model: page, url: admin_pages_path, method: :post do |f| %>
5
+ <% if page.errors.any? %>
6
+ <div class="mb-4 p-4 bg-red-50 border border-red-200 rounded-md">
7
+ <div class="text-sm text-red-600">
8
+ <% page.errors.full_messages.each do |message| %>
9
+ <p><%= message %></p>
10
+ <% end %>
11
+ </div>
12
+ </div>
13
+ <% end %>
5
14
  <% options = nested_set_options(Panda::CMS::Page, page) { |i| "#{"-" * i.level} #{i.title} (#{i.path})" } %>
6
- <div data-controller="slug">
7
- <input type="hidden" value="<%= Panda::CMS::Current.root %>" data-slug-target="existing_root">
8
- <%= f.select :parent_id, options, {}, { "data-slug-target": "input_select", "data-action": "change->slug#setPrePath" } %>
9
- <%= f.text_field :title, { data: { "slug-target": "input_text", action: "focusout->slug#generatePath" } } %>
10
- <%= f.text_field :path, { meta: t(".path.meta"), data: { prefix: Panda::CMS::Current.root, "slug-target": "output_text" } } %>
11
- <%= f.collection_select :panda_cms_template_id, Panda::CMS::Template.available, :id, :name %>
12
- <%= f.button "Create Page" %>
13
- </div>
15
+ <%= f.select :parent_id, options %>
16
+ <%= f.text_field :title %>
17
+ <%= f.text_field :path, { meta: t(".path.meta") } %>
18
+ <%= f.collection_select :panda_cms_template_id, available_templates, :id, :name %>
19
+ <%= f.button "Create Page" %>
14
20
  <% end %>
15
21
  <% end %>
@@ -1,4 +1,14 @@
1
1
  <%= panda_cms_form_with model: post, url: url, method: post.persisted? ? :put : :post do |f| %>
2
+ <% if post.errors.any? %>
3
+ <div class="mb-4 p-4 bg-red-50 border border-red-200 rounded-md">
4
+ <div class="text-sm text-red-600">
5
+ <% post.errors.full_messages.each do |message| %>
6
+ <p><%= message %></p>
7
+ <% end %>
8
+ </div>
9
+ </div>
10
+ <% end %>
11
+
2
12
  <div data-controller="slug" data-slug-add-date-prefix-value="true">
3
13
  <%= f.text_field :title,
4
14
  class: "block w-full rounded-md border-0 p-2 text-gray-900 ring-1 ring-inset ring-mid placeholder:text-gray-300 focus:ring-1 focus:ring-inset focus:ring-dark sm:leading-6 hover:pointer",
@@ -1,6 +1,7 @@
1
1
  <%= render Panda::CMS::Admin::ContainerComponent.new do |component| %>
2
- <% component.with_heading(text: "Edit Post", level: 1) do |heading| %>
2
+ <% component.with_heading(text: post.title, level: 1) do |heading| %>
3
+ <% heading.with_button(action: :view, text: "View Post", link: post_path(post.admin_param)) %>
3
4
  <% end %>
4
5
 
5
- <%= render "form", post: post, url: url, method: :patch %>
6
+ <%= render "form", post: post, url: admin_post_path(post.admin_param), method: :patch %>
6
7
  <% end %>
@@ -14,7 +14,7 @@
14
14
  <% end %>
15
15
  <% table.column("Status") { |post| render Panda::CMS::Admin::TagComponent.new(status: post.status) } %>
16
16
  <% table.column("Published") { |post| render Panda::CMS::Admin::UserActivityComponent.new(at: post.published_at, user: post.author)} %>
17
- <% table.column("Last Updated") { |post| render Panda::CMS::Admin::UserActivityComponent.new(whodunnit_to: post)} %>
17
+ <% table.column("Last Updated") { |post| render Panda::CMS::Admin::UserActivityComponent.new(at: post.updated_at)} %>
18
18
  <% end %>
19
19
 
20
20
  <% end %>
@@ -12,10 +12,12 @@
12
12
 
13
13
  <%= render Panda::CMS::Admin::PanelComponent.new do |panel| %>
14
14
  <% panel.with_heading(text: "Integrations") %>
15
+
16
+ <p class="text-base leading-loose"><i class="mr-2 text-active fa-brands fa-instagram"></i> <span class="font-medium">Instagram:</span> <%= Panda::CMS.config.instagram[:enabled] ? "Connected (@#{Panda::CMS.config.instagram[:username]})" : "Not Connected" %></p>
15
17
  <% end %>
16
18
 
17
19
  <div class="text-center mt-6 space-y-2">
18
20
  <p class="text-sm font-semibold">🐼 Panda CMS version: <%= Panda::CMS::VERSION %></p>
19
- <p class="text-sm">&copy; <%= Date.current.year %> Panda Software Limited. All rights reserved.</p>
21
+ <p class="text-sm">&copy; <%= Date.current.year %> Otaina Limited. All rights reserved.</p>
20
22
  </div>
21
23
  <% end %>
@@ -23,7 +23,7 @@
23
23
  <% end %>
24
24
  </li>
25
25
  <li class="mt-auto">
26
- <%= button_to '#', data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
26
+ <%= link_to edit_admin_my_profile_path, class: nav_highlight_colour_classes(request) + " w-full", title: "Edit my Profile" do %>
27
27
  <% if !current_user.image_url.to_s.empty? %>
28
28
  <span class="text-center"><img src="<%= current_user.image_url %>" class="w-auto h-7 rounded-full"></span>
29
29
  <% else %>
@@ -1,15 +1,25 @@
1
1
  <!DOCTYPE html>
2
- <html data-theme="default" class="<%= html_class ||= "" %>">
2
+ <html
3
+ data-theme="<%= Panda::CMS::Current&.user&.current_theme || "default" %>"
4
+ class="<%= html_class ||= "" %>">
3
5
  <head>
4
6
  <title><%= title_tag %></title>
5
7
  <%= csrf_meta_tags %>
6
8
  <%= csp_meta_tag %>
7
9
  <script src="https://kit.fontawesome.com/7835d81e75.js" defer="true" crossorigin="anonymous"></script>
8
- <script async src="https://ga.jspm.io/npm:es-module-shims@1.10.0/dist/es-module-shims.js" defer="true" crossorigin="anonymous"></script>
9
10
  <%= stylesheet_link_tag "panda.cms", "data-turbo-track": "reload", media: "all" %>
10
- <%= render "panda/cms/shared/importmap" %>
11
+
12
+ <% if Panda::CMS::AssetLoader.use_github_assets? || Rails.env.test? %>
13
+ <!-- Using compiled Panda CMS assets -->
14
+ <%= panda_cms_complete_assets %>
15
+ <% else %>
16
+ <!-- Using development importmap assets -->
17
+ <script async src="https://ga.jspm.io/npm:es-module-shims@1.10.0/dist/es-module-shims.js" defer="true" crossorigin="anonymous"></script>
18
+ <%= render "panda/cms/shared/importmap" %>
19
+ <% end %>
20
+
11
21
  <%= render "panda/cms/shared/favicons" %>
12
22
  <%= yield :head %>
13
23
  </head>
14
- <body class="overflow-hidden h-full">
24
+ <body class="overflow-hidden h-full" data-environment="<%= Rails.env %>">
15
25
  <%= render "panda/cms/admin/shared/flash" %>
@@ -8,7 +8,7 @@
8
8
  # Vendored
9
9
  "@hotwired/turbo": asset_path("panda/cms/@hotwired--turbo.js"),
10
10
  "@hotwired/stimulus": asset_path("panda/cms/@hotwired--stimulus.js"),
11
- "@hotwired/stimulus-loading": asset_path("stimulus-loading.js"),
11
+ "@hotwired/stimulus-loading": asset_path("panda_cms/stimulus-loading.js"),
12
12
  "@editorjs/editorjs": asset_path("panda/cms/@editorjs--editorjs.js"),
13
13
  "tailwindcss-stimulus-components": asset_path("panda/cms/tailwindcss-stimulus-components.js"),
14
14
  # Our page editor
@@ -22,6 +22,7 @@
22
22
  "panda/cms/controllers/slug_controller": asset_path("panda/cms/controllers/slug_controller.js"),
23
23
  "panda/cms/controllers/editor_form_controller": asset_path("panda/cms/controllers/editor_form_controller.js"),
24
24
  "panda/cms/controllers/editor_iframe_controller": asset_path("panda/cms/controllers/editor_iframe_controller.js"),
25
+ "panda/cms/controllers/theme_form_controller": asset_path("panda/cms/controllers/theme_form_controller.js"),
25
26
  # Main controller loader
26
27
  "controllers": asset_path("panda/cms/controllers/index.js"),
27
28
  }
@@ -0,0 +1,3 @@
1
+ <h1>Test Footer</h1>
2
+ </body>
3
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Panda CMS Page</title>
5
+ <% if params[:embed_id].present? %>
6
+ <!-- Include Panda CMS assets for editor functionality when in edit mode -->
7
+ <%= panda_cms_complete_assets %>
8
+ <% end %>
9
+ </head>
10
+ <body>
11
+ <h1>Test Header</h1>
data/config/importmap.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  pin "application_panda_cms", to: "panda_cms/application_panda_cms.js", preload: true
2
4
 
3
5
  pin "@hotwired/turbo", to: "@hotwired--turbo.js", preload: true # @8.0.12
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveSupport::Inflector.inflections(:en) do |inflect|
2
4
  inflect.acronym "CMS"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActionView::Base.field_error_proc = proc do |html_tag, instance|
2
4
  html = ""
3
5
  form_fields = %w[input select textarea trix-editor label].join(", ")
@@ -6,30 +8,27 @@ ActionView::Base.field_error_proc = proc do |html_tag, instance|
6
8
  autofocused = false
7
9
 
8
10
  Nokogiri::HTML::DocumentFragment.parse(html_tag).css(form_fields).each do |element|
9
- if form_fields.include?(element.node_name)
10
- if !autofocused
11
- # element.attribute("autofocus", "true")
12
- autofocused = true
13
- end
11
+ next unless form_fields.include?(element.node_name)
14
12
 
15
- message = "#{instance.object.class.human_attribute_name(instance.send(:sanitized_method_name))} "
16
- message += if instance.error_message.respond_to?(:each)
17
- "#{instance.error_message.uniq.to_sentence}."
18
- else
19
- "#{instance.error_message}."
20
- end
13
+ autofocused ||= true
14
+
15
+ message = "#{instance.object.class.human_attribute_name(instance.send(:sanitized_method_name))} "
16
+ message += if instance.error_message.respond_to?(:each)
17
+ "#{instance.error_message.uniq.to_sentence}."
18
+ else
19
+ "#{instance.error_message}."
20
+ end
21
21
 
22
- if element.node_name.eql?("label")
23
- html = element.to_s
22
+ if element.node_name.eql?("label")
23
+ html = element.to_s
24
+ else
25
+ element.add_class(error_class)
26
+ html = if element.get_attribute("data-prefix")
27
+ "#{element}</div><div class=\"#{message_class}\">#{message}"
28
+ elsif element.get_attribute("type") != "checkbox"
29
+ "#{element}<div class=\"#{message_class}\">#{message}</div>"
24
30
  else
25
- element.add_class(error_class)
26
- html = if element.get_attribute("data-prefix")
27
- "#{element}</div><div class=\"#{message_class}\">#{message}"
28
- elsif element.get_attribute("type") != "checkbox"
29
- "#{element}<div class=\"#{message_class}\">#{message}</div>"
30
- else
31
- element.to_s
32
- end
31
+ element.to_s
33
32
  end
34
33
  end
35
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "silencer/rails/logger"
2
4
 
3
5
  # Don't log requests to the healthcheck endpoint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Panda::CMS.configure do |config|
2
4
  # The main title of your website
3
5
  config.title = "Demo Site"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.autoloaders.main.inflector.inflect(
2
4
  "panda-cms" => "Panda::CMS"
3
5
  )
@@ -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/puma/test.rb CHANGED
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Puma configuration for test environment
2
4
  workers 0
3
5
  threads 1, 1
4
6
 
5
- port ENV.fetch("PORT") { 3001 }
7
+ port ENV.fetch("PORT", 3001)
6
8
  environment "test"
7
9
 
8
10
  # Allow for proper shutdown
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../app/constraints/panda/cms/admin_constraint"
2
4
 
3
5
  Panda::CMS::Engine.routes.draw do
@@ -12,14 +14,13 @@ Panda::CMS::Engine.routes.draw do
12
14
  resources :posts
13
15
 
14
16
  get "settings", to: "settings#index"
17
+
18
+ resource :my_profile, only: %i[edit update], controller: :my_profile
19
+
15
20
  namespace :settings, as: :settings do
16
21
  get "bulk_editor", to: "bulk_editor#new"
17
22
  post "bulk_editor", to: "bulk_editor#create"
18
23
  end
19
-
20
- if Rails.env.development?
21
- mount Lookbook::Engine, at: "/lookbook"
22
- end
23
24
  end
24
25
 
25
26
  get Panda::CMS.route_namespace, to: "admin/dashboard#show", as: :admin_dashboard
@@ -30,8 +31,10 @@ Panda::CMS::Engine.routes.draw do
30
31
  # Authentication routes
31
32
  get Panda::CMS.route_namespace, to: "admin/sessions#new", as: :admin_login
32
33
  # Get and post options here are for OmniAuth coming back in, not going out
33
- match "#{Panda::CMS.route_namespace}/auth/:provider/callback", to: "admin/sessions#create", as: :admin_login_callback, via: %i[get post]
34
- match "#{Panda::CMS.route_namespace}/auth/failure", to: "admin/sessions#failure", as: :admin_login_failure, via: %i[get post]
34
+ match "#{Panda::CMS.route_namespace}/auth/:provider/callback", to: "admin/sessions#create",
35
+ as: :admin_login_callback, via: %i[get post]
36
+ match "#{Panda::CMS.route_namespace}/auth/failure", to: "admin/sessions#failure", as: :admin_login_failure,
37
+ via: %i[get post]
35
38
  # OmniAuth additionally adds a GET route for "#{Panda::CMS.route_namespace}/auth/:provider" but doesn't name it
36
39
  delete Panda::CMS.route_namespace, to: "admin/sessions#destroy", as: :admin_logout
37
40
 
@@ -48,7 +51,7 @@ Panda::CMS::Engine.routes.draw do
48
51
  constraints: {
49
52
  year: /\d{4}/,
50
53
  month: /\d{2}/,
51
- slug: /[^\/]+/,
54
+ slug: %r{[^/]+},
52
55
  format: /html|json|xml/
53
56
  }
54
57
 
@@ -57,7 +60,7 @@ Panda::CMS::Engine.routes.draw do
57
60
  to: "posts#show",
58
61
  as: :post,
59
62
  constraints: {
60
- slug: /[^\/]+/,
63
+ slug: %r{[^/]+},
61
64
  format: /html|json|xml/
62
65
  }
63
66
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSPages < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_pages, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSPageVersions < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_page_versions, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSTemplates < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_templates, id: :uuid do |t|
@@ -6,6 +8,7 @@ class CreatePandaCMSTemplates < ActiveRecord::Migration[7.1]
6
8
  t.timestamps
7
9
  end
8
10
 
9
- add_reference :panda_cms_pages, :panda_cms_template, type: :uuid, foreign_key: {to_table: :panda_cms_templates}, null: false
11
+ add_reference :panda_cms_pages, :panda_cms_template, type: :uuid, foreign_key: {to_table: :panda_cms_templates},
12
+ null: false
10
13
  end
11
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSTemplateVersions < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_template_versions, id: :uuid do |t|
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSBlocks < ActiveRecord::Migration[7.1]
2
4
  def change
3
- create_enum :panda_cms_block_kind, ["plain_text", "rich_text", "image", "video", "audio", "file", "code", "iframe", "quote", "list", "table", "form"]
5
+ create_enum :panda_cms_block_kind,
6
+ %w[plain_text rich_text image video audio file code iframe quote list table form]
4
7
 
5
8
  create_table :panda_cms_blocks, id: :uuid do |t|
6
9
  t.enum :kind, enum_type: :panda_cms_block_kind, default: "plain_text", null: false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSBlockContents < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_block_contents, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSBlockContentVersions < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_block_content_versions, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddPandaCMSMenuTable < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_menus, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddPandaCMSMenuItemTable < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_menu_items, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddParentIdToPandaCMSPages < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  add_reference :panda_cms_pages, :parent, type: :uuid, foreign_key: {to_table: :panda_cms_pages}
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddStatusToPandaCMSPages < ActiveRecord::Migration[7.1]
2
4
  def change
3
- unless column_exists?(:panda_cms_pages, :status)
4
- create_enum :panda_cms_page_status, ["active", "draft", "hidden", "archived"]
5
- add_column :panda_cms_pages, :status, :panda_cms_page_status, default: "active", null: false
6
- add_index :panda_cms_pages, :status
7
- end
5
+ return if column_exists?(:panda_cms_pages, :status)
6
+
7
+ create_enum :panda_cms_page_status, %w[active draft hidden archived]
8
+ add_column :panda_cms_pages, :status, :panda_cms_page_status, default: "active", null: false
9
+ add_index :panda_cms_pages, :status
8
10
  end
9
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddNestedSetsToPandaCMSPages < ActiveRecord::Migration[7.1]
2
4
  def self.up
3
5
  Panda::CMS::Page.where(parent_id: 0).update_all(parent_id: nil)
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddKindToPandaCMSMenus < ActiveRecord::Migration[7.1]
2
4
  def change
3
- create_enum :panda_cms_menu_kind, ["static", "auto"]
5
+ create_enum :panda_cms_menu_kind, %w[static auto]
4
6
  add_column :panda_cms_menus, :kind, :enum, enum_type: :panda_cms_menu_kind, default: "static", null: false
5
7
  end
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddStartPageToPandaCMSMenus < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  add_reference :panda_cms_menus, :start_page, type: :uuid, foreign_key: {to_table: :panda_cms_pages}
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddNestedToPandaCMSMenuItems < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  add_column :panda_cms_menu_items, :parent_id, :uuid
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSUsers < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_users, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddMaxUsesToPandaCMSTemplate < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  add_column :panda_cms_templates, :max_uses, :integer, null: true, default: nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ResetCounterCacheOnPandaCMSTemplate < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  Panda::CMS::Template.find_each { |t| Panda::CMS::Template.reset_counters(t.id, :pages) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSRedirects < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_redirects, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSVisits < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_visits, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This migration comes from active_storage (originally 20170806125915)
2
4
  class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
3
5
  def change
@@ -33,7 +35,8 @@ class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
33
35
  t.datetime :created_at, null: false
34
36
  end
35
37
 
36
- t.index [:record_type, :record_id, :name, :blob_id], name: :index_active_storage_attachments_uniqueness, unique: true
38
+ t.index %i[record_type record_id name blob_id], name: :index_active_storage_attachments_uniqueness,
39
+ unique: true
37
40
  t.foreign_key :active_storage_blobs, column: :blob_id
38
41
  end
39
42
 
@@ -41,7 +44,7 @@ class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
41
44
  t.belongs_to :blob, null: false, index: false, type: foreign_key_type
42
45
  t.string :variation_digest, null: false
43
46
 
44
- t.index [:blob_id, :variation_digest], name: :index_active_storage_variant_records_uniqueness, unique: true
47
+ t.index %i[blob_id variation_digest], name: :index_active_storage_variant_records_uniqueness, unique: true
45
48
  t.foreign_key :active_storage_blobs, column: :blob_id
46
49
  end
47
50
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class DefaultPandaCMSUsersAdminToFalse < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  change_column :panda_cms_users, :admin, :boolean, default: false
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This migration comes from active_storage (originally 20190112182829)
2
4
  class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
3
5
  def up
4
6
  return unless table_exists?(:active_storage_blobs)
5
7
 
6
- unless column_exists?(:active_storage_blobs, :service_name)
7
- add_column :active_storage_blobs, :service_name, :string
8
+ return if column_exists?(:active_storage_blobs, :service_name)
8
9
 
9
- if (configured_service = ActiveStorage::Blob.service.name)
10
- ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
11
- end
10
+ add_column :active_storage_blobs, :service_name, :string
12
11
 
13
- change_column :active_storage_blobs, :service_name, :string, null: false
12
+ if (configured_service = ActiveStorage::Blob.service.name)
13
+ ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
14
14
  end
15
+
16
+ change_column :active_storage_blobs, :service_name, :string, null: false
15
17
  end
16
18
 
17
19
  def down
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This migration comes from active_storage (originally 20191206030411)
2
4
  class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
3
5
  def change
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This migration comes from active_storage (originally 20211119233751)
2
4
  class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0]
3
5
  def change
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSForms < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_forms, id: :uuid do |t|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePandaCMSFormSubmissions < ActiveRecord::Migration[7.1]
2
4
  def change
3
5
  create_table :panda_cms_form_submissions, id: :uuid do |t|