panda_cms 0.5.10 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) 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 +2415 -1
  5. data/app/assets/config/panda_cms_manifest.js +2 -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 +60 -0
  12. data/app/components/panda_cms/page_menu_component.html.erb +6 -4
  13. data/app/components/panda_cms/page_menu_component.rb +21 -12
  14. data/app/components/panda_cms/rich_text_component.html.erb +6 -38
  15. data/app/components/panda_cms/rich_text_component.rb +24 -7
  16. data/app/components/panda_cms/text_component.rb +25 -22
  17. data/app/controllers/panda_cms/admin/dashboard_controller.rb +14 -6
  18. data/app/controllers/panda_cms/admin/menus_controller.rb +1 -54
  19. data/app/controllers/panda_cms/admin/pages_controller.rb +2 -1
  20. data/app/controllers/panda_cms/admin/sessions_controller.rb +13 -6
  21. data/app/controllers/panda_cms/application_controller.rb +1 -1
  22. data/app/controllers/panda_cms/pages_controller.rb +1 -1
  23. data/app/controllers/panda_cms/posts_controller.rb +1 -1
  24. data/app/helpers/panda_cms/application_helper.rb +2 -2
  25. data/app/javascript/panda_cms/@hotwired--stimulus.js +4 -0
  26. data/app/javascript/panda_cms/@hotwired--turbo.js +160 -0
  27. data/app/javascript/panda_cms/@rails--actioncable--src.js +4 -0
  28. data/app/javascript/panda_cms/application_panda_cms.js +4 -0
  29. data/app/javascript/panda_cms/controllers/dashboard_controller.js +7 -0
  30. data/app/javascript/panda_cms/controllers/index.js +42 -0
  31. data/app/javascript/panda_cms/controllers/slug_controller.js +48 -0
  32. data/app/javascript/panda_cms/panda_cms_editable.js +248 -0
  33. data/app/javascript/panda_cms/tailwindcss-stimulus-components.js +4 -0
  34. data/app/lib/panda_cms/demo_site_generator.rb +1 -1
  35. data/app/lib/panda_cms/slug.rb +1 -1
  36. data/app/models/panda_cms/block.rb +2 -2
  37. data/app/models/panda_cms/page.rb +9 -3
  38. data/app/models/panda_cms/post.rb +1 -1
  39. data/app/models/panda_cms/template.rb +4 -2
  40. data/app/models/panda_cms/user.rb +9 -1
  41. data/app/views/panda_cms/admin/dashboard/show.html.erb +11 -9
  42. data/app/views/panda_cms/admin/forms/new.html.erb +6 -7
  43. data/app/views/panda_cms/admin/menus/index.html.erb +0 -2
  44. data/app/views/panda_cms/admin/pages/edit.html.erb +18 -16
  45. data/app/views/panda_cms/admin/pages/new.html.erb +6 -7
  46. data/app/views/panda_cms/admin/posts/_form.html.erb +4 -4
  47. data/app/views/panda_cms/admin/sessions/new.html.erb +1 -2
  48. data/app/views/panda_cms/admin/shared/_sidebar.html.erb +12 -16
  49. data/app/views/panda_cms/shared/_header.html.erb +14 -14
  50. data/app/views/panda_cms/shared/_importmap.html.erb +22 -0
  51. data/config/importmap.rb +11 -10
  52. data/config/initializers/panda_cms.rb +57 -55
  53. data/config/routes.rb +9 -9
  54. data/config/tailwind.config.js +1 -0
  55. data/db/migrate/20240205223709_create_panda_cms_pages.rb +6 -4
  56. data/lib/generators/panda_cms/install_generator.rb +3 -0
  57. data/lib/panda_cms/engine.rb +27 -22
  58. data/lib/panda_cms/version.rb +1 -1
  59. data/lib/panda_cms.rb +58 -10
  60. data/lib/tasks/panda_cms.rake +41 -57
  61. data/public/panda-cms-assets/rich_text_editor.css +568 -0
  62. metadata +216 -278
  63. data/app/javascript/base.js +0 -37
  64. data/app/javascript/controllers/menu_controller.js +0 -19
  65. data/app/javascript/controllers/text_controller.js +0 -78
  66. data/app/javascript/controllers/text_field_update_controller.js +0 -51
  67. data/app/javascript/vendor/stimulus-components-rails-nested-form.js +0 -2
  68. data/app/javascript/vendor/tailwindcss-stimulus-components.js +0 -2
  69. data/app/views/panda_cms/admin/menus/_form.html.erb +0 -21
  70. data/app/views/panda_cms/admin/menus/_menu_item_fields.html.erb +0 -7
  71. data/app/views/panda_cms/admin/menus/edit.html.erb +0 -58
  72. data/app/views/panda_cms/admin/menus/new.html.erb +0 -5
  73. data/public/panda-cms-assets/javascripts/base.js +0 -37
  74. data/public/panda-cms-assets/javascripts/controllers/menu_controller.js +0 -19
  75. data/public/panda-cms-assets/javascripts/controllers/text_field_update_controller.js +0 -23
  76. data/public/panda-cms-assets/javascripts/embed/editable.js +0 -358
  77. data/public/panda-cms-assets/javascripts/embed/rich_text.css +0 -1294
  78. data/public/panda-cms-assets/javascripts/vendor/stimulus-components-rails-nested-form.js +0 -2
  79. data/public/panda-cms-assets/javascripts/vendor/stimulus-loading.js +0 -113
  80. data/public/panda-cms-assets/javascripts/vendor/tailwindcss-stimulus-components.js +0 -2
  81. /data/db/migrate/{20240804110225_add_status_to_panda_cms_pages.rb → 20240315125411_add_status_to_panda_cms_pages.rb} +0 -0
@@ -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,16 @@
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" 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", media: "all" %>
10
+ <%= render "panda_cms/shared/importmap" %>
11
+ <%#= turbo_refreshes_with method: :morph, scroll: :preserve %>
12
+ <%= render "panda_cms/shared/favicons" %>
13
+ <%= yield :head %>
14
+ </head>
15
+ <body class="overflow-hidden h-full">
16
+ <%= render "panda_cms/admin/shared/flash" %>
@@ -0,0 +1,22 @@
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
+ "application_panda_cms": asset_path("panda_cms/application_panda_cms.js"),
8
+ "@hotwired/turbo": asset_path("panda_cms/@hotwired--turbo.js"),
9
+ "@hotwired/stimulus": asset_path("panda_cms/@hotwired--stimulus.js"),
10
+ "@hotwired/stimulus-loading": asset_path("stimulus-loading.js"),
11
+ "tailwindcss-stimulus-components": asset_path("panda_cms/tailwindcss-stimulus-components.js"),
12
+ "controllers/dashboard_controller": asset_path("panda_cms/controllers/dashboard_controller.js"),
13
+ "controllers/slug_controller": asset_path("panda_cms/controllers/slug_controller.js"),
14
+ # Add other controllers here
15
+ "controllers": asset_path("panda_cms/controllers/index.js")
16
+ }
17
+ }).html_safe
18
+ %>
19
+ </script>
20
+ <script type="module">
21
+ import "application_panda_cms"
22
+ </script>
data/config/importmap.rb CHANGED
@@ -1,11 +1,12 @@
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
+
9
+ # pin "@rails/activestorage", to: "@rails--activestorage.js" # @7.2.100
10
+ # pin "@rails/actioncable", to: "@rails--actioncable.js" # @7.2.100
11
+
12
+ pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms/controllers"), under: "controllers", to: "panda_cms/controllers"
@@ -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
@@ -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,15 @@
1
- require "groupdate"
2
1
  require "importmap-rails"
3
- require "paper_trail"
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"
2
+ require "turbo-rails"
3
+ require "stimulus-rails"
14
4
 
15
5
  module PandaCms
16
6
  class Engine < ::Rails::Engine
17
7
  isolate_namespace PandaCms
18
8
  engine_name "panda_cms"
19
9
 
10
+ initializer "panda_cms" do |app|
11
+ end
12
+
20
13
  config.to_prepare do
21
14
  ApplicationController.helper(::ApplicationHelper)
22
15
  end
@@ -30,19 +23,27 @@ module PandaCms
30
23
  g.templates.unshift File.expand_path("../../templates", __FILE__)
31
24
  end
32
25
 
33
- # Make files in public available to the main app (e.g. favicon.ico)
26
+ # Make files in public available to the main app (e.g. /panda-cms-assets/favicon.ico)
34
27
  config.app_middleware.use(
35
28
  Rack::Static,
36
29
  urls: ["/panda-cms-assets"],
37
30
  root: PandaCms::Engine.root.join("public")
38
31
  )
39
32
 
33
+ # Custom error handling
40
34
  config.exceptions_app = PandaCms::ExceptionsApp.new(exceptions_app: routes)
41
35
 
42
- # Create an importmap for the engine's JS
36
+ initializer "panda_cms.assets" do |app|
37
+ if Rails.configuration.respond_to?(:assets)
38
+ app.config.assets.paths << root.join("app/javascript")
39
+ app.config.assets.precompile += %w[panda_cms_manifest]
40
+ end
41
+ end
42
+
43
+ # Add importmap paths from the engine
43
44
  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")
45
+ app.config.importmap.paths << root.join("config/importmap.rb")
46
+ app.config.importmap.cache_sweepers << root.join("app/javascript")
46
47
  end
47
48
 
48
49
  config.after_initialize do |app|
@@ -82,11 +83,11 @@ module PandaCms
82
83
  app.config.middleware.use ActionDispatch::Session::CookieStore, app.config.session_options
83
84
 
84
85
  OmniAuth.config.logger = Rails.logger
85
- auth_path = "#{PandaCms.admin_path}/auth"
86
- callback_path = "/callback"
87
86
 
88
87
  # TODO: Move this to somewhere more sensible
89
88
  # Define the mapping of our provider "names" to the OmniAuth strategies and configuration
89
+ auth_path = "#{PandaCms.route_namespace}/auth"
90
+ callback_path = "/callback"
90
91
  available_providers = {
91
92
  microsoft: {
92
93
  strategy: :microsoft_graph,
@@ -157,13 +158,17 @@ module PandaCms
157
158
  }
158
159
 
159
160
  available_providers.each do |provider, options|
160
- if PandaCms.authentication.dig(provider, :enabled)
161
+ if PandaCms.config.authentication.dig(provider, :enabled)
162
+ auth_path = auth_path.starts_with?("/") ? auth_path : "/#{auth_path}"
161
163
  options[:defaults][:path_prefix] = auth_path
162
- options[:defaults][:redirect_uri] = "#{PandaCms.url}#{auth_path}/#{provider}#{callback_path}"
163
164
 
164
- provider_config = options[:defaults].merge(PandaCms.authentication[provider])
165
+ options[:defaults][:redirect_uri] = if Rails.env.test?
166
+ "#{Capybara.app_host}#{auth_path}/#{provider}#{callback_path}"
167
+ else
168
+ "#{PandaCms.config.url}#{auth_path}/#{provider}#{callback_path}"
169
+ end
165
170
 
166
- Rails.logger.info("Configuring OmniAuth for #{provider} with #{provider_config}")
171
+ provider_config = options[:defaults].merge(PandaCms.config.authentication[provider])
167
172
 
168
173
  app.config.middleware.use OmniAuth::Builder do
169
174
  provider options[:strategy], provider_config
@@ -1,3 +1,3 @@
1
1
  module PandaCms
2
- VERSION = "0.5.10"
2
+ VERSION = "0.6.0"
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
@@ -1,4 +1,10 @@
1
+ # desc "Explaining what the task does"
2
+ # task :panda_cms do
3
+ # # Task goes here
4
+ # end
5
+
1
6
  require "tailwindcss-rails"
7
+ require "tailwindcss/ruby"
2
8
  require "shellwords"
3
9
 
4
10
  require "panda_cms/engine"
@@ -6,6 +12,18 @@ require "panda_cms/engine"
6
12
  ENV["TAILWIND_PATH"] ||= Tailwindcss::Engine.root.join("exe/tailwindcss").to_s
7
13
 
8
14
  namespace :panda_cms do
15
+ desc "Watch admin assets for Panda CMS"
16
+ # We only care about this in development
17
+ task :watch_admin do
18
+ run_tailwind(
19
+ root_path: PandaCms::Engine.root,
20
+ input_path: "app/assets/stylesheets/panda_cms/application.tailwind.css",
21
+ output_path: "app/assets/builds/panda_cms.css",
22
+ watch: true,
23
+ minify: false
24
+ )
25
+ end
26
+
9
27
  desc "Generate missing blocks from template files"
10
28
  task generate_missing_blocks: [:environment] do
11
29
  PandaCms::Template.generate_missing_blocks
@@ -18,75 +36,41 @@ namespace :panda_cms do
18
36
  end
19
37
  end
20
38
 
21
- namespace :assets do
22
- desc "Compile assets for release"
23
- task :compile do
24
- # Copy all the JS files into public
25
- admin_js_path = PandaCms::Engine.root.join("app/javascript/panda_cms")
26
- FileUtils.cp_r "#{admin_js_path}/.", PandaCms::Engine.root.join("public/panda-cms-assets/javascripts")
27
- end
28
-
29
- desc "Build admin assets for Panda CMS"
30
- task :admin do
31
- # This is enough for development
32
- run_tailwind(
33
- root_path: PandaCms::Engine.root,
34
- input_path: "app/assets/stylesheets/panda_cms/application.tailwind.css",
35
- output_path: "app/assets/builds/panda_cms.css"
36
- )
37
- end
38
-
39
- desc "Build dummy assets for Panda CMS"
40
- # We only care about this in development
41
- task :dummy do
42
- run_tailwind(
43
- root_path: Rails.application.root,
44
- input_path: "app/assets/stylesheets/application.tailwind.css",
45
- output_path: "app/assets/builds/application.css",
46
- config_path: "config/tailwind.config.js"
47
- )
48
- end
49
-
50
- desc "Watch admin assets for Panda CMS"
51
- # We only care about this in development
52
- task :watch_admin do
53
- run_tailwind(
54
- root_path: PandaCms::Engine.root,
55
- input_path: "app/assets/stylesheets/panda_cms/application.tailwind.css",
56
- output_path: "app/assets/builds/panda_cms.css",
57
- watch: true
58
- )
59
- end
39
+ # namespace :assets do
40
+ # desc "Compile assets for release"
41
+ # task :compile do
42
+ # # Copy all the JS files into public
43
+ # admin_js_path = PandaCms::Engine.root.join("app/javascript/panda_cms")
44
+ # FileUtils.cp_r "#{admin_js_path}/.", PandaCms::Engine.root.join("public/panda-cms-assets/javascripts")
45
+ # end
60
46
 
61
- desc "Watch dummy assets for Panda CMS"
62
- # We only care about this in development
63
- task :watch_dummy do
64
- run_tailwind(
65
- root_path: Rails.application.root,
66
- input_path: "app/assets/stylesheets/application.tailwind.css",
67
- output_path: "app/assets/builds/application.css",
68
- config_path: "config/tailwind.config.js",
69
- watch: true
70
- )
71
- end
72
- end
47
+ # desc "Build admin assets for Panda CMS"
48
+ # task :admin do
49
+ # # This is enough for development
50
+ # run_tailwind(
51
+ # root_path: PandaCms::Engine.root,
52
+ # input_path: "app/assets/stylesheets/panda_cms/application.tailwind.css",
53
+ # output_path: "app/assets/builds/panda_cms.css"
54
+ # )
55
+ # end
56
+ # end
73
57
  end
74
58
 
75
59
  task default: [:spec, :panda_cms]
76
60
 
77
- def run_tailwind(root_path:, input_path: nil, output_path: nil, config_path: nil, watch: false)
78
- Rails.logger = Logger.new($stdout)
61
+ def run_tailwind(root_path:, input_path: nil, output_path: nil, config_path: nil, watch: false, minify: true)
79
62
  config_path ||= root_path.join("config/tailwind.config.js")
80
63
 
81
64
  command = [
82
- ENV["TAILWIND_PATH"],
65
+ Tailwindcss::Ruby.executable,
83
66
  "-i #{root_path.join(input_path)}",
84
67
  "-o #{root_path.join(output_path)}",
85
- "-c #{root_path.join(config_path)}",
86
- "-m"
68
+ "-c #{root_path.join(config_path)}"
87
69
  ]
88
70
 
89
71
  command << "-w" if watch
72
+ command << "-m" if minify
90
73
 
91
- exec command.join(" ")
74
+ command = command.join(" ")
75
+ system command
92
76
  end