panda_cms 0.5.10 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/Rakefile +0 -1
  4. data/app/assets/builds/panda_cms.css +2432 -1
  5. data/app/assets/config/panda_cms_manifest.js +3 -0
  6. data/app/assets/stylesheets/panda_cms/application.tailwind.css +3 -27
  7. data/app/builders/panda_cms/form_builder.rb +1 -1
  8. data/app/components/panda_cms/admin/button_component.rb +6 -3
  9. data/app/components/panda_cms/admin/flash_message_component.rb +1 -1
  10. data/app/components/panda_cms/admin/tag_component.rb +1 -1
  11. data/app/components/panda_cms/code_component.rb +62 -0
  12. data/app/components/panda_cms/menu_component.html.erb +3 -0
  13. data/app/components/panda_cms/menu_component.rb +8 -1
  14. data/app/components/panda_cms/page_menu_component.html.erb +12 -8
  15. data/app/components/panda_cms/page_menu_component.rb +24 -13
  16. data/app/components/panda_cms/rich_text_component.html.erb +6 -38
  17. data/app/components/panda_cms/rich_text_component.rb +32 -7
  18. data/app/components/panda_cms/text_component.rb +25 -22
  19. data/app/controllers/panda_cms/admin/block_contents_controller.rb +1 -1
  20. data/app/controllers/panda_cms/admin/dashboard_controller.rb +14 -6
  21. data/app/controllers/panda_cms/admin/menus_controller.rb +1 -54
  22. data/app/controllers/panda_cms/admin/pages_controller.rb +2 -1
  23. data/app/controllers/panda_cms/admin/sessions_controller.rb +13 -6
  24. data/app/controllers/panda_cms/application_controller.rb +1 -1
  25. data/app/controllers/panda_cms/pages_controller.rb +1 -1
  26. data/app/controllers/panda_cms/posts_controller.rb +1 -1
  27. data/app/helpers/panda_cms/application_helper.rb +2 -2
  28. data/app/javascript/panda_cms/@editorjs--editorjs.js +2577 -0
  29. data/app/javascript/panda_cms/@hotwired--stimulus.js +4 -0
  30. data/app/javascript/panda_cms/@hotwired--turbo.js +160 -0
  31. data/app/javascript/panda_cms/@rails--actioncable--src.js +4 -0
  32. data/app/javascript/panda_cms/application_panda_cms.js +4 -0
  33. data/app/javascript/panda_cms/controllers/dashboard_controller.js +7 -0
  34. data/app/javascript/panda_cms/controllers/editor_controller.js +247 -0
  35. data/app/javascript/panda_cms/controllers/index.js +45 -0
  36. data/app/javascript/panda_cms/controllers/slug_controller.js +48 -0
  37. data/app/javascript/panda_cms/editor/plain_text_editor.js +102 -0
  38. data/app/javascript/panda_cms/editor/resource_loader.js +69 -0
  39. data/app/javascript/panda_cms/editor/rich_text_editor.js +89 -0
  40. data/app/javascript/panda_cms/tailwindcss-stimulus-components.js +4 -0
  41. data/app/lib/panda_cms/demo_site_generator.rb +1 -3
  42. data/app/lib/panda_cms/editor_js/blocks/alert.rb +32 -0
  43. data/app/lib/panda_cms/editor_js/blocks/base.rb +28 -0
  44. data/app/lib/panda_cms/editor_js/blocks/header.rb +13 -0
  45. data/app/lib/panda_cms/editor_js/blocks/image.rb +34 -0
  46. data/app/lib/panda_cms/editor_js/blocks/list.rb +30 -0
  47. data/app/lib/panda_cms/editor_js/blocks/paragraph.rb +13 -0
  48. data/app/lib/panda_cms/editor_js/blocks/quote.rb +27 -0
  49. data/app/lib/panda_cms/editor_js/blocks/table.rb +48 -0
  50. data/app/lib/panda_cms/editor_js/renderer.rb +120 -0
  51. data/app/lib/panda_cms/slug.rb +1 -1
  52. data/app/models/panda_cms/block.rb +2 -2
  53. data/app/models/panda_cms/block_content.rb +12 -2
  54. data/app/models/panda_cms/page.rb +9 -3
  55. data/app/models/panda_cms/post.rb +1 -1
  56. data/app/models/panda_cms/template.rb +4 -2
  57. data/app/models/panda_cms/user.rb +9 -1
  58. data/app/views/panda_cms/admin/dashboard/show.html.erb +11 -9
  59. data/app/views/panda_cms/admin/forms/new.html.erb +6 -7
  60. data/app/views/panda_cms/admin/menus/index.html.erb +0 -2
  61. data/app/views/panda_cms/admin/pages/edit.html.erb +22 -19
  62. data/app/views/panda_cms/admin/pages/new.html.erb +6 -7
  63. data/app/views/panda_cms/admin/posts/_form.html.erb +4 -4
  64. data/app/views/panda_cms/admin/sessions/new.html.erb +1 -2
  65. data/app/views/panda_cms/admin/shared/_sidebar.html.erb +12 -16
  66. data/app/views/panda_cms/shared/_header.html.erb +13 -14
  67. data/app/views/panda_cms/shared/_importmap.html.erb +32 -0
  68. data/config/importmap.rb +13 -10
  69. data/config/initializers/panda_cms.rb +57 -55
  70. data/config/routes.rb +9 -9
  71. data/config/tailwind.config.js +1 -0
  72. data/db/migrate/20240205223709_create_panda_cms_pages.rb +6 -4
  73. data/db/migrate/20240315125411_add_status_to_panda_cms_pages.rb +9 -0
  74. data/db/migrate/20241031205109_add_cached_content_to_panda_cms_block_contents.rb +5 -0
  75. data/db/seeds.rb +1 -0
  76. data/lib/generators/panda_cms/install_generator.rb +3 -0
  77. data/lib/panda_cms/engine.rb +42 -29
  78. data/lib/panda_cms/version.rb +1 -1
  79. data/lib/panda_cms.rb +58 -10
  80. data/lib/tasks/panda_cms.rake +41 -57
  81. data/public/panda-cms-assets/rich_text_editor.css +568 -0
  82. metadata +228 -304
  83. data/app/javascript/base.js +0 -37
  84. data/app/javascript/controllers/menu_controller.js +0 -19
  85. data/app/javascript/controllers/text_controller.js +0 -78
  86. data/app/javascript/controllers/text_field_update_controller.js +0 -51
  87. data/app/javascript/vendor/stimulus-components-rails-nested-form.js +0 -2
  88. data/app/javascript/vendor/tailwindcss-stimulus-components.js +0 -2
  89. data/app/views/panda_cms/admin/menus/_form.html.erb +0 -21
  90. data/app/views/panda_cms/admin/menus/_menu_item_fields.html.erb +0 -7
  91. data/app/views/panda_cms/admin/menus/edit.html.erb +0 -58
  92. data/app/views/panda_cms/admin/menus/new.html.erb +0 -5
  93. data/db/migrate/20240804110225_add_status_to_panda_cms_pages.rb +0 -7
  94. data/public/panda-cms-assets/javascripts/base.js +0 -37
  95. data/public/panda-cms-assets/javascripts/controllers/menu_controller.js +0 -19
  96. data/public/panda-cms-assets/javascripts/controllers/text_field_update_controller.js +0 -23
  97. data/public/panda-cms-assets/javascripts/embed/editable.js +0 -358
  98. data/public/panda-cms-assets/javascripts/embed/rich_text.css +0 -1294
  99. data/public/panda-cms-assets/javascripts/vendor/stimulus-components-rails-nested-form.js +0 -2
  100. data/public/panda-cms-assets/javascripts/vendor/stimulus-loading.js +0 -113
  101. data/public/panda-cms-assets/javascripts/vendor/tailwindcss-stimulus-components.js +0 -2
@@ -1,7 +1,6 @@
1
1
  <nav class="flex flex-col flex-1">
2
2
  <ul role="list" class="flex flex-col flex-1">
3
- <a class="block p-0 mt-4 mb-4 ml-2 text-xl font-medium text-white"><%= PandaCms.title %></a>
4
-
3
+ <a class="block p-0 mt-4 mb-4 ml-2 text-xl font-medium text-white"><%= PandaCms.config.title %></a>
5
4
  <% [
6
5
  { path: admin_dashboard_path, text: "Dashboard", icon: "fa-house", matcher: :exact },
7
6
  { path: admin_pages_path, text: "Pages", icon: "fa-page", matcher: :starts_with },
@@ -10,32 +9,29 @@
10
9
  { path: admin_menus_path, text: "Menus", icon: "fa-list-dropdown", matcher: :starts_with },
11
10
  { path: admin_settings_path, text: "Settings", icon: "fa-cog", matcher: :starts_with },
12
11
  ].each do |link| %>
13
- <li>
14
- <%= link_to link[:path], class: "#{active_link?(link[:path], match: link[:matcher]) ? selected_nav_highlight_colour_classes(request) : nav_highlight_colour_classes(request)}" do %>
15
- <span class="text-center"><i class="fa-regular <%= link[:icon] %> text-xl fa-fw"></i></span>
16
- <span class="mt-1"><%= link[:text] %></span>
17
- <% end %>
18
- </li>
12
+ <li>
13
+ <%= link_to link[:path], class: "#{active_link?(link[:path], match: link[:matcher]) ? selected_nav_highlight_colour_classes(request) : nav_highlight_colour_classes(request)}" do %>
14
+ <span class="text-center"><i class="fa-regular <%= link[:icon] %> text-xl fa-fw"></i></span>
15
+ <span class="mt-1"><%= link[:text] %></span>
16
+ <% end %>
17
+ </li>
19
18
  <% end %>
20
19
  <li>
21
- <%= button_to admin_logout_path, method: :delete, data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
20
+ <%= button_to admin_logout_path, method: :delete, id: "logout-link", data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
22
21
  <span class="text-center"><i class="text-xl fa-regular fa-door-open fa-fw"></i></span>
23
- <span class="mt-1">Sign Out</span>
22
+ <span class="mt-1">Logout</span>
24
23
  <% end %>
25
24
  </li>
26
-
27
25
  <li class="mt-auto">
28
26
  <%= button_to '#', data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
29
- <% if !current_user.image_url.empty? %>
30
- <span class="text-center"><img src="<%= current_user.image_url %>" class="w-auto h-7 rounded-full"></span>
27
+ <% if !current_user.image_url.to_s.empty? %>
28
+ <span class="text-center"><img src="<%= current_user.image_url %>" class="w-auto h-7 rounded-full"></span>
31
29
  <% else %>
32
- <span class="text-center"><i class="text-xl fa-regular fa-circle-user fa-fw"></i></span>
30
+ <span class="text-center"><i class="text-xl fa-regular fa-circle-user fa-fw"></i></span>
33
31
  <% end %>
34
-
35
32
  <span class="mt-0.5"><%= current_user.firstname %> <%= current_user.lastname %></span>
36
33
  <% end %>
37
34
  </li>
38
-
39
35
  <li class="">
40
36
  <img src="/panda-cms-assets/panda-nav.png" class="inline py-2 mr-1 ml-0.5 w-auto h-14">
41
37
  <span class="text-xs text-white">v<%= PandaCms::VERSION %> | <span class="font-semibold">License:</span> Perpetual</span>
@@ -1,16 +1,15 @@
1
1
  <!DOCTYPE html>
2
2
  <html data-theme="default" class="<%= html_class ||= "" %>">
3
- <head>
4
- <title><%= title_tag %></title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
- <script src="https://kit.fontawesome.com/7835d81e75.js" crossorigin="anonymous"></script>
8
- <script async src="https://ga.jspm.io/npm:es-module-shims@1.10.0/dist/es-module-shims.js" crossorigin="anonymous"></script>
9
- <%= stylesheet_link_tag "panda_cms", "data-turbo-track": "reload" %>
10
- <%= javascript_importmap_tags "panda_cms/base" %>
11
- <%= render "panda_cms/shared/favicons" %>
12
- <%= yield :head %>
13
- </head>
14
-
15
- <body class="overflow-hidden h-full">
16
- <%= render "panda_cms/admin/shared/flash" %>
3
+ <head>
4
+ <title><%= title_tag %></title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <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
+ <%= stylesheet_link_tag "panda_cms", "data-turbo-track": "reload", media: "all" %>
10
+ <%= render "panda_cms/shared/importmap" %>
11
+ <%= render "panda_cms/shared/favicons" %>
12
+ <%= yield :head %>
13
+ </head>
14
+ <body class="overflow-hidden h-full">
15
+ <%= render "panda_cms/admin/shared/flash" %>
@@ -0,0 +1,32 @@
1
+ <%#= javascript_importmap_tags "application_panda_cms" %>
2
+ <script type="importmap" data-turbo-track="reload">
3
+ <%=
4
+ # This ended up being the best solution to not drag in the importmap from the host app when we're editing the site
5
+ JSON.pretty_generate({
6
+ imports: {
7
+ # Main loader
8
+ "application_panda_cms": asset_path("panda_cms/application_panda_cms.js"),
9
+ # Vendored
10
+ "@hotwired/turbo": asset_path("panda_cms/@hotwired--turbo.js"),
11
+ "@hotwired/stimulus": asset_path("panda_cms/@hotwired--stimulus.js"),
12
+ "@hotwired/stimulus-loading": asset_path("stimulus-loading.js"),
13
+ "@editorjs/editorjs": asset_path("panda_cms/@editorjs--editorjs.js"),
14
+ "tailwindcss-stimulus-components": asset_path("panda_cms/tailwindcss-stimulus-components.js"),
15
+ # Our controllers
16
+ "panda_cms_controllers/dashboard_controller": asset_path("panda_cms/controllers/dashboard_controller.js"),
17
+ "panda_cms_controllers/slug_controller": asset_path("panda_cms/controllers/slug_controller.js"),
18
+ # Add other controllers here
19
+ # Our page editor
20
+ "panda_cms_controllers/editor_controller": asset_path("panda_cms/controllers/editor_controller.js"),
21
+ "panda_cms_editor/plain_text_editor": asset_path("panda_cms/editor/plain_text_editor.js"),
22
+ "panda_cms_editor/rich_text_editor": asset_path("panda_cms/editor/rich_text_editor.js"),
23
+ "panda_cms_editor/resource_loader": asset_path("panda_cms/editor/resource_loader.js"),
24
+ # Main controller loader
25
+ "controllers": asset_path("panda_cms/controllers/index.js"),
26
+ }
27
+ }).html_safe
28
+ %>
29
+ </script>
30
+ <script type="module">
31
+ import "application_panda_cms"
32
+ </script>
data/config/importmap.rb CHANGED
@@ -1,11 +1,14 @@
1
- pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:stimulus@3.2.2/dist/stimulus.js"
2
- pin "@hotwired/stimulus-loading", to: "/panda-cms-assets/javascripts/vendor/stimulus-loading.js" # 3.2.2
3
- pin "@hotwired/turbo-rails", to: "turbo.min.js"
4
- pin "@rails/activestorage", to: "https://ga.jspm.io/npm:@rails/activestorage@7.2.0/app/assets/javascripts/activestorage.esm.js"
1
+ pin "application_panda_cms", to: "panda_cms/application_panda_cms.js", preload: true
5
2
 
6
- pin "panda_cms/vendor/stimulus-components-rails-nested-form", to: "/panda-cms-assets/javascripts/vendor/stimulus-components-rails-nested-form.js", preload: false
7
- pin "panda_cms/vendor/tailwindcss-stimulus-components", to: "/panda-cms-assets/javascripts/vendor/tailwindcss-stimulus-components.js", preload: false
8
- pin "panda_cms/controllers/menu_controller", to: "/panda-cms-assets/javascripts/controllers/menu_controller.js", preload: false
9
- pin "panda_cms/controllers/text_field_update_controller", to: "/panda-cms-assets/javascripts/controllers/text_field_update_controller.js", preload: false
10
- pin "panda_cms/embed/editable", to: "/panda-cms-assets/javascripts/embed/editable.js", preload: false
11
- pin "panda_cms/base", to: "/panda-cms-assets/javascripts/base.js", preload: false
3
+ pin "@hotwired/turbo", to: "@hotwired--turbo.js", preload: true # @8.0.12
4
+ pin "@rails/actioncable/src", to: "@rails--actioncable--src.js", preload: true # @7.2.101
5
+ pin "@hotwired/stimulus", to: "@hotwired--stimulus.js" # @3.2.2
6
+ pin "@hotwired/stimulus-loading", to: "panda_cms/stimulus-loading.js", preload: true
7
+ pin "tailwindcss-stimulus-components" # @6.1.2
8
+ pin "@editorjs/editorjs", to: "@editorjs--editorjs.js" # @2.30.6
9
+
10
+ # pin "@rails/activestorage", to: "@rails--activestorage.js" # @7.2.100
11
+ # pin "@rails/actioncable", to: "@rails--actioncable.js" # @7.2.100
12
+
13
+ pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms/controllers"), under: "panda_cms_controllers", to: "panda_cms/controllers"
14
+ pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms/editor"), under: "editor", to: "panda_cms/editor"
@@ -1,58 +1,60 @@
1
- # The main title of your website
2
- # The default is "Demo Site"
3
- PandaCms.title = "Demo Site"
4
- # The path to the administration panel, which must start with a /
5
- # The default is "/admin"
6
- PandaCms.admin_path = "/admin"
7
- # Is login required to access the site?
8
- PandaCms.require_login_to_view = false
9
- # Authentication providers
10
- PandaCms.authentication = {
11
- microsoft: {
12
- enabled: false,
13
- # Setup at the following URL:
14
- # https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
15
- client_id: Rails.application.credentials.dig(:microsoft, :client_id),
16
- client_secret: Rails.application.credentials.dig(:microsoft, :client_secret),
17
- # Don't change this or the sky will fall on your head
18
- # https://github.com/synth/omniauth-microsoft_graph/tree/main?tab=readme-ov-file#domain-verification
19
- skip_domain_verification: false,
20
- # If your application is single-tenanted, replace "common" with your tenant (directory) ID
21
- # from https://portal.azure.com/#settings/directory, otherwise you'll likely want to leave
22
- # these settings unchanged
23
- client_options: {
24
- site: "https://login.microsoftonline.com/",
25
- token_url: "common/oauth2/v2.0/token",
26
- authorize_url: "common/oauth2/v2.0/authorize"
1
+ PandaCms.configure do |config|
2
+ # The main title of your website
3
+ # The default is "Demo Site"
4
+ config.title = "Demo Site"
5
+ # The path to the administration panel, which must start with a /
6
+ # The default is "/admin"
7
+ config.admin_path = "/admin"
8
+ # Is login required to access the site? (Else, show maintenance page)
9
+ config.require_login_to_view = false
10
+ # Authentication providers
11
+ config.authentication = {
12
+ microsoft: {
13
+ enabled: true,
14
+ # Setup at the following URL:
15
+ # https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
16
+ client_id: Rails.application.credentials.dig(:microsoft, :client_id),
17
+ client_secret: Rails.application.credentials.dig(:microsoft, :client_secret),
18
+ # Don't change this or the sky will fall on your head
19
+ # https://github.com/synth/omniauth-microsoft_graph/tree/main?tab=readme-ov-file#domain-verification
20
+ skip_domain_verification: false,
21
+ # If your application is single-tenanted, replace "common" with your tenant (directory) ID
22
+ # from https://portal.azure.com/#settings/directory, otherwise you'll likely want to leave
23
+ # these settings unchanged
24
+ client_options: {
25
+ site: "https://login.microsoftonline.com/",
26
+ token_url: "common/oauth2/v2.0/token",
27
+ authorize_url: "common/oauth2/v2.0/authorize"
28
+ },
29
+ # If you assign specific users or groups, you will likely want to set this to true to enable
30
+ # auto-provisioning
31
+ create_account_on_first_login: false,
32
+ redirect_uri: Rails.application.credentials.dig(:microsoft, :redirect_uri)
27
33
  },
28
- # If you assign specific users or groups, you will likely want to set this to true to enable
29
- # auto-provisioning
30
- create_account_on_first_login: false,
31
- redirect_uri: Rails.application.credentials.dig(:microsoft, :redirect_uri)
32
- },
33
- google: {
34
- enabled: false,
35
- create_account_on_first_login: false,
36
- create_admin_account_on_first_login: false,
37
- # client_id: Rails.application.credentials.dig(:google, :client_id),
38
- # client_secret: Rails.application.credentials.dig(:google, :client_secret),
39
- client_id: "552337866923-o1jd9ushva70su79c2ke8ftnu623chsl.apps.googleusercontent.com", # Will only work on localhost
40
- client_secret: "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", # Will only work on localhost
41
- redirect_uri: Rails.application.credentials.dig(:google, :redirect_uri)
42
- },
43
- github: {
34
+ google: {
35
+ enabled: true,
36
+ create_account_on_first_login: false,
37
+ create_admin_account_on_first_login: false,
38
+ # client_id: Rails.application.credentials.dig(:google, :client_id),
39
+ # client_secret: Rails.application.credentials.dig(:google, :client_secret),
40
+ client_id: "552337866923-o1jd9ushva70su79c2ke8ftnu623chsl.apps.googleusercontent.com", # Will only work on localhost
41
+ client_secret: "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", # Will only work on localhost
42
+ redirect_uri: Rails.application.credentials.dig(:google, :redirect_uri)
43
+ },
44
+ github: {
45
+ enabled: true,
46
+ create_account_on_first_login: false,
47
+ create_admin_account_on_first_login: false,
48
+ # client_id: Rails.application.credentials.dig(:github, :client_id),
49
+ # client_secret: Rails.application.credentials.dig(:github, :client_secret),
50
+ client_id: "Ov23li9k0LpMXtq8FShb", # Will only work on localhost
51
+ client_secret: "07233b63472b7f287ac11854e627670ddc096a22", # Will only work on localhost
52
+ redirect_uri: Rails.application.credentials.dig(:github, :redirect_uri)
53
+ }
54
+ }
55
+ # Blog
56
+ config.posts = {
44
57
  enabled: true,
45
- create_account_on_first_login: false,
46
- create_admin_account_on_first_login: false,
47
- # client_id: Rails.application.credentials.dig(:github, :client_id),
48
- # client_secret: Rails.application.credentials.dig(:github, :client_secret),
49
- client_id: "Ov23li9k0LpMXtq8FShb", # Will only work on localhost
50
- client_secret: "07233b63472b7f287ac11854e627670ddc096a22", # Will only work on localhost
51
- redirect_uri: Rails.application.credentials.dig(:github, :redirect_uri)
58
+ prefix: "blog"
52
59
  }
53
- }
54
- # Blog
55
- PandaCms.posts = {
56
- enabled: true,
57
- prefix: "blog"
58
- }
60
+ end
data/config/routes.rb CHANGED
@@ -2,7 +2,7 @@ require_relative "../app/constraints/panda_cms/admin_constraint"
2
2
 
3
3
  PandaCms::Engine.routes.draw do
4
4
  constraints PandaCms::AdminConstraint.new(&:present?) do
5
- namespace PandaCms.admin_path_symbol.to_sym, as: :admin, module: :admin do
5
+ namespace PandaCms.route_namespace, as: :admin, module: :admin do
6
6
  resources :files
7
7
  resources :forms, only: %i[index show]
8
8
  resources :menus
@@ -22,24 +22,24 @@ PandaCms::Engine.routes.draw do
22
22
  end
23
23
  end
24
24
 
25
- get PandaCms.admin_path, to: "admin/dashboard#show", as: :admin_dashboard
25
+ get PandaCms.route_namespace, to: "admin/dashboard#show", as: :admin_dashboard
26
26
  end
27
27
 
28
28
  ### PUBLIC ROUTES ###
29
29
 
30
30
  # Authentication routes
31
- get PandaCms.admin_path, to: "admin/sessions#new", as: :admin_login
31
+ get PandaCms.route_namespace, to: "admin/sessions#new", as: :admin_login
32
32
  # Get and post options here are for OmniAuth coming back in, not going out
33
- match "#{PandaCms.admin_path}/auth/:provider/callback", to: "admin/sessions#create", as: :admin_login_callback, via: %i[get post]
34
- match "#{PandaCms.admin_path}/auth/failure", to: "admin/sessions#failure", as: :admin_login_failure, via: %i[get post]
35
- # OmniAuth additionally adds a GET route for "#{PandaCms.admin_path}/auth/:provider" but doesn't name it
36
- delete PandaCms.admin_path, to: "admin/sessions#destroy", as: :admin_logout
33
+ match "#{PandaCms.route_namespace}/auth/:provider/callback", to: "admin/sessions#create", as: :admin_login_callback, via: %i[get post]
34
+ match "#{PandaCms.route_namespace}/auth/failure", to: "admin/sessions#failure", as: :admin_login_failure, via: %i[get post]
35
+ # OmniAuth additionally adds a GET route for "#{PandaCms.route_namespace}/auth/:provider" but doesn't name it
36
+ delete PandaCms.route_namespace, to: "admin/sessions#destroy", as: :admin_logout
37
37
 
38
- if PandaCms.posts
38
+ if PandaCms.config.posts[:enabled]
39
39
  # TODO: Allow multiple types of post in future
40
40
  # TODO: This now requires a page to be created, make it explicit (with a rendering posts helper?)
41
41
  # get PandaCms.posts[:prefix], to: "posts#index", as: :posts
42
- get "#{PandaCms.posts[:prefix]}/:slug", to: "posts#show", as: :post
42
+ get "#{PandaCms.config.posts[:prefix]}/:slug", to: "posts#show", as: :post
43
43
  end
44
44
 
45
45
  ### APPENDED ROUTES ###
@@ -23,6 +23,7 @@ module.exports = {
23
23
  dark: "rgb(var(--color-dark) / <alpha-value>)",
24
24
  highlight: "rgb(var(--color-highlight) / <alpha-value>)",
25
25
  active: "rgb(var(--color-active) / <alpha-value>)",
26
+ inactive: "rgb(var(--color-active) / <alpha-value>)",
26
27
  warning: "rgb(var(--color-warning) / <alpha-value>)",
27
28
  error: "rgb(var(--color-error) / <alpha-value>)",
28
29
  },
@@ -1,9 +1,11 @@
1
1
  class CreatePandaCmsPages < ActiveRecord::Migration[7.1]
2
2
  def change
3
- create_table :panda_cms_pages, id: :uuid do |t|
4
- t.string :title
5
- t.string :path
6
- t.timestamps
3
+ unless table_exists?(:panda_cms_pages)
4
+ create_table :panda_cms_pages, id: :uuid do |t|
5
+ t.string :title
6
+ t.string :path
7
+ t.timestamps
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -0,0 +1,9 @@
1
+ class AddStatusToPandaCmsPages < ActiveRecord::Migration[7.1]
2
+ 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
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AddCachedContentToPandaCmsBlockContents < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :panda_cms_block_contents, :cached_content, :jsonb
4
+ end
5
+ end
data/db/seeds.rb CHANGED
@@ -2,3 +2,4 @@ generator = PandaCms::DemoSiteGenerator.new
2
2
  generator.create_templates
3
3
  generator.create_pages
4
4
  generator.create_menus
5
+ PandaCms::Template.generate_missing_blocks
@@ -18,6 +18,9 @@ module Generators
18
18
  existing_seeds = File.read("#{::Rails.root}/db/seeds.rb")
19
19
  IO.write("#{::Rails.root}/db/seeds.rb", "PandaCms::Engine.load_seed\n\n#{existing_seeds}")
20
20
  end
21
+
22
+ `rails db:migrate`
23
+ `rails db:seed`
21
24
  end
22
25
  end
23
26
  end
@@ -1,22 +1,16 @@
1
- require "groupdate"
2
1
  require "importmap-rails"
3
- require "paper_trail"
2
+ require "turbo-rails"
3
+ require "stimulus-rails"
4
4
  require "view_component"
5
- require "lookbook"
6
-
7
- require "omniauth"
8
- require "omniauth/rails_csrf_protection"
9
- require "omniauth/strategies/microsoft_graph"
10
- require "omniauth/strategies/google_oauth2"
11
- require "omniauth/strategies/github"
12
-
13
- require "panda_cms/exceptions_app"
14
5
 
15
6
  module PandaCms
16
7
  class Engine < ::Rails::Engine
17
8
  isolate_namespace PandaCms
18
9
  engine_name "panda_cms"
19
10
 
11
+ initializer "panda_cms" do |app|
12
+ end
13
+
20
14
  config.to_prepare do
21
15
  ApplicationController.helper(::ApplicationHelper)
22
16
  end
@@ -30,19 +24,27 @@ module PandaCms
30
24
  g.templates.unshift File.expand_path("../../templates", __FILE__)
31
25
  end
32
26
 
33
- # Make files in public available to the main app (e.g. favicon.ico)
27
+ # Make files in public available to the main app (e.g. /panda-cms-assets/favicon.ico)
34
28
  config.app_middleware.use(
35
29
  Rack::Static,
36
30
  urls: ["/panda-cms-assets"],
37
31
  root: PandaCms::Engine.root.join("public")
38
32
  )
39
33
 
40
- config.exceptions_app = PandaCms::ExceptionsApp.new(exceptions_app: routes)
34
+ # Custom error handling
35
+ # config.exceptions_app = PandaCms::ExceptionsApp.new(exceptions_app: routes)
36
+
37
+ initializer "panda_cms.assets" do |app|
38
+ if Rails.configuration.respond_to?(:assets)
39
+ app.config.assets.paths << root.join("app/javascript")
40
+ app.config.assets.precompile += %w[panda_cms_manifest]
41
+ end
42
+ end
41
43
 
42
- # Create an importmap for the engine's JS
44
+ # Add importmap paths from the engine
43
45
  initializer "panda_cms.importmap", before: "importmap" do |app|
44
- app.config.importmap.cache_sweeper(watches: PandaCms::Engine.root.join("public/panda-cms-assets"))
45
- app.config.importmap.paths << PandaCms::Engine.root.join("config/importmap.rb")
46
+ app.config.importmap.paths << root.join("config/importmap.rb")
47
+ app.config.importmap.cache_sweepers << root.join("app/javascript")
46
48
  end
47
49
 
48
50
  config.after_initialize do |app|
@@ -54,6 +56,9 @@ module PandaCms
54
56
  get "/*path", to: "panda_cms/pages#show", as: :panda_cms_page
55
57
  root to: "panda_cms/pages#root"
56
58
  end
59
+
60
+ # Ensure we don't have any missing blocks from new templates
61
+ PandaCms::Template.generate_missing_blocks
57
62
  end
58
63
 
59
64
  # Add the migrations to the main app
@@ -67,13 +72,13 @@ module PandaCms
67
72
 
68
73
  # Set up ViewComponent and Lookbook
69
74
  # config.view_component.component_parent_class = "PandaCms::BaseComponent"
70
- config.view_component.view_component_path = PandaCms::Engine.root.join("lib/components").to_s
71
- config.eager_load_paths << PandaCms::Engine.root.join("lib/components").to_s
72
- config.view_component.generate.sidecar = true
73
- config.view_component.generate.preview = true
74
- config.view_component.preview_paths ||= []
75
- config.view_component.preview_paths << PandaCms::Engine.root.join("lib/component_previews").to_s
76
- config.view_component.generate.preview_path = "lib/component_previews"
75
+ # config.view_component.view_component_path = PandaCms::Engine.root.join("lib/components").to_s
76
+ # config.eager_load_paths << PandaCms::Engine.root.join("lib/components").to_s
77
+ # config.view_component.generate.sidecar = true
78
+ # config.view_component.generate.preview = true
79
+ # config.view_component.preview_paths ||= []
80
+ # config.view_component.preview_paths << PandaCms::Engine.root.join("lib/component_previews").to_s
81
+ # config.view_component.generate.preview_path = "lib/component_previews"
77
82
 
78
83
  # Set up authentication
79
84
  initializer "panda_cms.omniauth", before: "omniauth" do |app|
@@ -82,11 +87,11 @@ module PandaCms
82
87
  app.config.middleware.use ActionDispatch::Session::CookieStore, app.config.session_options
83
88
 
84
89
  OmniAuth.config.logger = Rails.logger
85
- auth_path = "#{PandaCms.admin_path}/auth"
86
- callback_path = "/callback"
87
90
 
88
91
  # TODO: Move this to somewhere more sensible
89
92
  # Define the mapping of our provider "names" to the OmniAuth strategies and configuration
93
+ auth_path = "#{PandaCms.route_namespace}/auth"
94
+ callback_path = "/callback"
90
95
  available_providers = {
91
96
  microsoft: {
92
97
  strategy: :microsoft_graph,
@@ -157,13 +162,17 @@ module PandaCms
157
162
  }
158
163
 
159
164
  available_providers.each do |provider, options|
160
- if PandaCms.authentication.dig(provider, :enabled)
165
+ if PandaCms.config.authentication.dig(provider, :enabled)
166
+ auth_path = auth_path.starts_with?("/") ? auth_path : "/#{auth_path}"
161
167
  options[:defaults][:path_prefix] = auth_path
162
- options[:defaults][:redirect_uri] = "#{PandaCms.url}#{auth_path}/#{provider}#{callback_path}"
163
168
 
164
- provider_config = options[:defaults].merge(PandaCms.authentication[provider])
169
+ options[:defaults][:redirect_uri] = if Rails.env.test?
170
+ "#{Capybara.app_host}#{auth_path}/#{provider}#{callback_path}"
171
+ else
172
+ "#{PandaCms.config.url}#{auth_path}/#{provider}#{callback_path}"
173
+ end
165
174
 
166
- Rails.logger.info("Configuring OmniAuth for #{provider} with #{provider_config}")
175
+ provider_config = options[:defaults].merge(PandaCms.config.authentication[provider])
167
176
 
168
177
  app.config.middleware.use OmniAuth::Builder do
169
178
  provider options[:strategy], provider_config
@@ -172,4 +181,8 @@ module PandaCms
172
181
  end
173
182
  end
174
183
  end
184
+
185
+ class MissingBlockError < StandardError; end
186
+
187
+ class BlockError < StandardError; end
175
188
  end
@@ -1,3 +1,3 @@
1
1
  module PandaCms
2
- VERSION = "0.5.10"
2
+ VERSION = "0.6.1"
3
3
  end
data/lib/panda_cms.rb CHANGED
@@ -1,15 +1,63 @@
1
- require "panda_cms/version"
1
+ require "dry-configurable"
2
+ require "importmap-rails"
3
+ require "lookbook"
4
+ require "omniauth"
5
+ require "omniauth/rails_csrf_protection"
6
+ require "omniauth/strategies/microsoft_graph"
7
+ require "omniauth/strategies/google_oauth2"
8
+ require "omniauth/strategies/github"
9
+ require "paper_trail"
10
+ require "view_component"
11
+
12
+ require "panda_cms/exceptions_app"
13
+
2
14
  require "panda_cms/engine"
15
+ require "panda_cms/version"
3
16
 
4
17
  module PandaCms
5
- mattr_accessor :admin_path
6
- mattr_accessor :authentication
7
- mattr_accessor :require_login_to_view
8
- mattr_accessor :title
9
- mattr_accessor :url
10
- mattr_accessor :posts
11
-
12
- def self.admin_path_symbol
13
- @@admin_path.delete_prefix("/")
18
+ extend Dry::Configurable
19
+
20
+ setting :admin_path, default: "/admin"
21
+ setting :authentication, default: {}
22
+ setting :posts, default: {}
23
+ setting :title, default: "Demo Site"
24
+ setting :url, default: "http://localhost:3000"
25
+ setting :require_login_to_view, default: false
26
+ setting :error_reporting do
27
+ setting :sentry do
28
+ setting :enabled, default: false
29
+ setting :dsn
30
+ end
31
+ end
32
+
33
+ #
34
+ # Defines the namespace for the admin routes
35
+ #
36
+ # @return [Symbol] The namespace for the admin routes
37
+ # @visibility public
38
+ # @example
39
+ # "/admin" => :admin
40
+ def self.route_namespace
41
+ PandaCms.config.admin_path.delete_prefix("/").to_sym
42
+ end
43
+
44
+ #
45
+ # Returns the root path for the admin routes
46
+ #
47
+ # @return [Symbol] The root path for the admin routes
48
+ # @visibility public
49
+ # @example "/admin"
50
+ def self.root_path
51
+ PandaCms.config.admin_path
52
+ end
53
+
54
+ #
55
+ # Returns the title for the website
56
+ #
57
+ # @return [Symbol] The title for the website
58
+ # @visibility public
59
+ # @example "Demo Site"
60
+ def self.title
61
+ PandaCms.config.title
14
62
  end
15
63
  end