panda-cms 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/components/panda/cms/admin/user_activity_component.html.erb +2 -2
- data/app/components/panda/cms/admin/user_activity_component.rb +2 -2
- data/app/components/panda/cms/admin/user_display_component.html.erb +1 -1
- data/app/components/panda/cms/admin/user_display_component.rb +2 -2
- data/app/components/panda/cms/rich_text_component.rb +5 -5
- data/app/controllers/panda/cms/admin/base_controller.rb +18 -0
- data/app/controllers/panda/cms/admin/block_contents_controller.rb +1 -2
- data/app/controllers/panda/cms/admin/dashboard_controller.rb +5 -4
- data/app/controllers/panda/cms/admin/files_controller.rb +1 -3
- data/app/controllers/panda/cms/admin/forms_controller.rb +3 -4
- data/app/controllers/panda/cms/admin/menus_controller.rb +2 -3
- data/app/controllers/panda/cms/admin/pages_controller.rb +7 -7
- data/app/controllers/panda/cms/admin/posts_controller.rb +9 -10
- data/app/controllers/panda/cms/admin/settings/bulk_editor_controller.rb +4 -4
- data/app/controllers/panda/cms/admin/settings_controller.rb +2 -3
- data/app/controllers/panda/cms/application_controller.rb +13 -5
- data/app/controllers/panda/cms/pages_controller.rb +2 -2
- data/app/helpers/panda/cms/application_helper.rb +3 -3
- data/app/helpers/panda/cms/asset_helper.rb +14 -1
- data/app/javascript/panda/cms/application_panda_cms.js +2 -34
- data/app/javascript/panda/cms/controllers/index.js +5 -15
- data/app/models/panda/cms/block_content.rb +1 -1
- data/app/models/panda/cms/current.rb +3 -12
- data/app/models/panda/cms/post.rb +3 -3
- data/app/models/panda/cms/visit.rb +1 -1
- data/app/views/layouts/panda/cms/application.html.erb +1 -1
- data/app/views/panda/cms/admin/dashboard/show.html.erb +2 -2
- data/app/views/panda/cms/admin/files/index.html.erb +1 -1
- data/app/views/panda/cms/admin/forms/index.html.erb +4 -4
- data/app/views/panda/cms/admin/forms/new.html.erb +2 -2
- data/app/views/panda/cms/admin/forms/show.html.erb +1 -1
- data/app/views/panda/cms/admin/menus/index.html.erb +4 -4
- data/app/views/panda/cms/admin/pages/edit.html.erb +6 -6
- data/app/views/panda/cms/admin/pages/index.html.erb +5 -5
- data/app/views/panda/cms/admin/pages/new.html.erb +2 -2
- data/app/views/panda/cms/admin/posts/_form.html.erb +1 -1
- data/app/views/panda/cms/admin/posts/edit.html.erb +2 -2
- data/app/views/panda/cms/admin/posts/index.html.erb +5 -5
- data/app/views/panda/cms/admin/posts/new.html.erb +1 -1
- data/app/views/panda/cms/admin/settings/bulk_editor/new.html.erb +1 -1
- data/app/views/panda/cms/admin/settings/index.html.erb +3 -3
- data/app/views/panda/cms/admin/shared/_breadcrumbs.html.erb +3 -3
- data/app/views/panda/cms/admin/shared/_flash.html.erb +1 -1
- data/app/views/panda/cms/admin/shared/_sidebar.html.erb +8 -8
- data/config/initializers/panda/cms.rb +6 -3
- data/config/routes.rb +8 -16
- data/db/migrate/20250106223303_add_author_id_to_panda_cms_posts.rb +3 -1
- data/db/migrate/20250126234001_create_panda_social_instagram_posts.rb +2 -0
- data/db/migrate/20250809231125_migrate_users_to_panda_core.rb +111 -0
- data/db/migrate/20250811111000_make_post_user_references_nullable.rb +11 -0
- data/lib/panda/cms/asset_loader.rb +4 -4
- data/lib/panda/cms/engine.rb +42 -98
- data/lib/panda-cms/version.rb +1 -1
- data/lib/panda-cms.rb +50 -40
- data/lib/tasks/assets.rake +162 -122
- data/lib/tasks/panda/cms/migrations.rake +13 -0
- metadata +19 -36
- data/app/builders/panda/cms/form_builder.rb +0 -225
- data/app/components/panda/cms/admin/button_component.rb +0 -70
- data/app/components/panda/cms/admin/container_component.rb +0 -13
- data/app/components/panda/cms/admin/flash_message_component.rb +0 -47
- data/app/components/panda/cms/admin/heading_component.rb +0 -46
- data/app/components/panda/cms/admin/panel_component.rb +0 -13
- data/app/components/panda/cms/admin/table_component.rb +0 -46
- data/app/components/panda/cms/admin/tag_component.rb +0 -35
- data/app/constraints/panda/cms/admin_constraint.rb +0 -21
- data/app/controllers/panda/cms/admin/my_profile_controller.rb +0 -44
- data/app/controllers/panda/cms/admin/sessions_controller.rb +0 -92
- data/app/javascript/panda/cms/controllers/theme_form_controller.js +0 -25
- data/app/javascript/panda/cms/editor/css_extractor.js +0 -80
- data/app/javascript/panda/cms/editor/editor_js_config.js +0 -306
- data/app/javascript/panda/cms/editor/editor_js_initializer.js +0 -334
- data/app/javascript/panda/cms/editor/plain_text_editor.js +0 -110
- data/app/javascript/panda/cms/editor/resource_loader.js +0 -204
- data/app/javascript/panda/cms/editor/rich_text_editor.js +0 -162
- data/app/models/panda/cms/breadcrumb.rb +0 -14
- data/app/models/panda/cms/user.rb +0 -33
- data/app/services/panda/cms/html_to_editor_js_converter.rb +0 -195
- data/app/views/panda/cms/admin/my_profile/edit.html.erb +0 -35
- data/app/views/panda/cms/admin/sessions/new.html.erb +0 -17
- data/db/migrate/20250504221812_add_current_theme_to_panda_cms_users.rb +0 -7
- data/lib/panda/cms/editor_js/blocks/alert.rb +0 -36
- data/lib/panda/cms/editor_js/blocks/base.rb +0 -35
- data/lib/panda/cms/editor_js/blocks/header.rb +0 -17
- data/lib/panda/cms/editor_js/blocks/image.rb +0 -39
- data/lib/panda/cms/editor_js/blocks/list.rb +0 -34
- data/lib/panda/cms/editor_js/blocks/paragraph.rb +0 -18
- data/lib/panda/cms/editor_js/blocks/quote.rb +0 -44
- data/lib/panda/cms/editor_js/blocks/table.rb +0 -52
- data/lib/panda/cms/editor_js/renderer.rb +0 -127
- data/lib/panda/cms/editor_js.rb +0 -18
- data/lib/panda/cms/editor_js_content.rb +0 -61
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="" data-controller="dashboard">
|
2
|
-
<%= render Panda::
|
2
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |container| %>
|
3
3
|
<% container.with_heading(text: "Dashboard", level: 1) do |heading| %>
|
4
|
-
<% heading.with_button(action: :add, text: "Add Page", link:
|
4
|
+
<% heading.with_button(action: :add, text: "Add Page", link: new_admin_cms_page_path) %>
|
5
5
|
<% end %>
|
6
6
|
<dl class="grid grid-cols-1 gap-5 mt-5 sm:grid-cols-3">
|
7
7
|
<%= render Panda::CMS::Admin::StatisticsComponent.new(metric: "Views Today", value: Panda::CMS::Visit.group_by_day(:visited_at, last: 1).count.values.first) %>
|
@@ -1,10 +1,10 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Forms", level: 1) do |heading| %>
|
3
3
|
<% end %>
|
4
4
|
|
5
|
-
<%= render Panda::
|
6
|
-
<% table.column("Name") { |form| block_link_to form.name,
|
7
|
-
<% table.column("Status") { |form| render Panda::
|
5
|
+
<%= render Panda::Core::Admin::TableComponent.new(term: "form", rows: forms) do |table| %>
|
6
|
+
<% table.column("Name") { |form| block_link_to form.name, admin_cms_form_path(form) } %>
|
7
|
+
<% table.column("Status") { |form| render Panda::Core::Admin::TagComponent.new(status: :active) } %>
|
8
8
|
<% table.column("Last Submission") do |form| %>
|
9
9
|
<%= "#{time_ago_in_words(form.form_submissions&.last&.created_at)} ago" if form.form_submissions&.last %>
|
10
10
|
<% end %>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Add Page", level: 1) do |heading| %>
|
3
3
|
<% end %>
|
4
|
-
<%= panda_cms_form_with model: page, url:
|
4
|
+
<%= panda_cms_form_with model: page, url: admin_cms_pages_path, method: :post do |f| %>
|
5
5
|
<% options = nested_set_options(Panda::CMS::Page, page) { |i| "#{"-" * i.level} #{i.title} (#{i.path})" } %>
|
6
6
|
<div data-controller="slug">
|
7
7
|
<input type="hidden" value="<%= Panda::CMS::Current.root %>" data-slug-target="existing_root">
|
@@ -1,8 +1,8 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Menus", level: 1) do |heading| %>
|
3
3
|
<% end %>
|
4
|
-
<%= render Panda::
|
5
|
-
<% table.column("Name") { |menu| link_to menu.name,
|
6
|
-
<% table.column("Kind") { |menu| render Panda::
|
4
|
+
<%= render Panda::Core::Admin::TableComponent.new(term: "menu", rows: menus) do |table| %>
|
5
|
+
<% table.column("Name") { |menu| link_to menu.name, edit_admin_cms_menu_path(menu) } %>
|
6
|
+
<% table.column("Kind") { |menu| render Panda::Core::Admin::TagComponent.new(status: :active, text: menu.kind.titleize) } %>
|
7
7
|
<% end %>
|
8
8
|
<% end %>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "#{page.title}", level: 1) %>
|
3
3
|
<% component.with_slideover(title: "Page Details") do %>
|
4
|
-
<%= panda_cms_form_with model: page, url:
|
4
|
+
<%= panda_cms_form_with model: page, url: admin_cms_page_path, method: :put do |f| %>
|
5
5
|
<%= f.text_field :title, 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" %>
|
6
6
|
<%= f.text_field :template, value: template.name, readonly: true, class: "read-only:bg-gray-100 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" %>
|
7
7
|
<%= f.select :status, options_for_select([["Active", "active"], ["Draft", "draft"], ["Hidden", "hidden"], ["Archived", "archived"]], selected: page.status), {}, class: "block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-mid focus:ring-1 focus:ring-inset focus:ring-dark sm:leading-6 hover:pointer" %>
|
@@ -9,17 +9,17 @@
|
|
9
9
|
<% end %>
|
10
10
|
<% end %>
|
11
11
|
<div id="successMessage" class="hidden">
|
12
|
-
<%= render Panda::
|
12
|
+
<%= render Panda::Core::Admin::FlashMessageComponent.new(kind: "success", message: "This page was successfully updated!", temporary: false) %>
|
13
13
|
</div>
|
14
14
|
<div id="errorMessage" class="hidden">
|
15
|
-
<%= render Panda::
|
15
|
+
<%= render Panda::Core::Admin::FlashMessageComponent.new(kind: "error", message: "There was an error updating this page.", temporary: false) %>
|
16
16
|
</div>
|
17
17
|
<div class="grid grid-cols-2 mb-4 -mt-5">
|
18
18
|
<div>
|
19
19
|
<a class="inline-block mb-2 text-sm text-black/60" target="_blank" href="<%= @page.path %>"><%= @page.path %> <i class="ml-2 fa-solid fa-arrow-up-right-from-square"></i></a>
|
20
20
|
</div>
|
21
21
|
<div class="relative -mt-5">
|
22
|
-
<span class="absolute right-0"><%= render Panda::
|
22
|
+
<span class="absolute right-0"><%= render Panda::Core::Admin::ButtonComponent.new(text: "Save Changes", action: :save_inactive, icon: "check", link: "#", size: :regular, id: "saveEditableButton") %></span>
|
23
23
|
</div>
|
24
24
|
</div>
|
25
25
|
<%= content_tag :iframe, nil,
|
@@ -30,7 +30,7 @@
|
|
30
30
|
data: {
|
31
31
|
controller: "editor-iframe",
|
32
32
|
editor_iframe_page_id_value: @page.id,
|
33
|
-
editor_iframe_admin_path_value: "#{
|
33
|
+
editor_iframe_admin_path_value: "#{admin_cms_dashboard_url}",
|
34
34
|
editor_iframe_autosave_value: false
|
35
35
|
} %>
|
36
36
|
<% end %>
|
@@ -1,17 +1,17 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Pages", level: 1) do |heading| %>
|
3
|
-
<% heading.with_button(action: :add, text: "Add Page", link:
|
3
|
+
<% heading.with_button(action: :add, text: "Add Page", link: new_admin_cms_page_path) %>
|
4
4
|
<% end %>
|
5
5
|
|
6
6
|
<% if root_page %>
|
7
|
-
<%= render Panda::
|
7
|
+
<%= render Panda::Core::Admin::TableComponent.new(term: "page", rows: root_page.self_and_descendants) do |table| %>
|
8
8
|
<% table.column("Name") do |page| %>
|
9
9
|
<div class="<%= table_indent(page) %>">
|
10
|
-
<%= link_to page.title,
|
10
|
+
<%= link_to page.title, edit_admin_cms_page_path(page), class: "block h-full w-full" %>
|
11
11
|
<span class="block text-xs text-black/60"><%= page.path %></span>
|
12
12
|
</div>
|
13
13
|
<% end %>
|
14
|
-
<% table.column("Status") { |page| render Panda::
|
14
|
+
<% table.column("Status") { |page| render Panda::Core::Admin::TagComponent.new(status: page.status) } %>
|
15
15
|
<% table.column("Last Updated") { |page| render Panda::CMS::Admin::UserActivityComponent.new(model: page) } %>
|
16
16
|
<% end %>
|
17
17
|
<% else %>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Add Page", level: 1) do |heading| %>
|
3
3
|
<% end %>
|
4
|
-
<%= panda_cms_form_with model: page, url:
|
4
|
+
<%= panda_cms_form_with model: page, url: admin_cms_pages_path, method: :post do |f| %>
|
5
5
|
<% if page.errors.any? %>
|
6
6
|
<div class="mb-4 p-4 bg-red-50 border border-red-200 rounded-md">
|
7
7
|
<div class="text-sm text-red-600">
|
@@ -22,7 +22,7 @@
|
|
22
22
|
"slug-target": "output_text"
|
23
23
|
} %>
|
24
24
|
</div>
|
25
|
-
<%= f.select :author_id, Panda::
|
25
|
+
<%= f.select :author_id, Panda::Core::User.admin.map { |u| [u.name, u.id] }, {}, class: "block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-mid focus:ring-1 focus:ring-inset focus:ring-dark sm:leading-6 hover:pointer" %>
|
26
26
|
<%= f.datetime_field :published_at, 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" %>
|
27
27
|
<%= f.select :status, options_for_select([["Active", "active"], ["Draft", "draft"], ["Hidden", "hidden"], ["Archived", "archived"]], selected: post.status), {}, class: "block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-mid focus:ring-1 focus:ring-inset focus:ring-dark sm:leading-6 hover:pointer" %>
|
28
28
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: post.title, level: 1) do |heading| %>
|
3
3
|
<% heading.with_button(action: :view, text: "View Post", link: post_path(post.admin_param)) %>
|
4
4
|
<% end %>
|
5
5
|
|
6
|
-
<%= render "form", post: post, url:
|
6
|
+
<%= render "form", post: post, url: admin_cms_post_path(post.admin_param), method: :patch %>
|
7
7
|
<% end %>
|
@@ -1,18 +1,18 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Posts", level: 1) do |heading| %>
|
3
|
-
<% heading.with_button(action: :add, text: "Add Post", link:
|
3
|
+
<% heading.with_button(action: :add, text: "Add Post", link: new_admin_cms_post_path) %>
|
4
4
|
<% end %>
|
5
5
|
|
6
|
-
<%= render Panda::
|
6
|
+
<%= render Panda::Core::Admin::TableComponent.new(term: "post", rows: posts) do |table| %>
|
7
7
|
<% table.column("Title") do |post| %>
|
8
8
|
<div>
|
9
|
-
<%= link_to post.title,
|
9
|
+
<%= link_to post.title, edit_admin_cms_post_path(post.admin_param), class: "block h-full w-full" %>
|
10
10
|
<span class="block text-xs text-black/60">
|
11
11
|
<%= CGI.unescape("#{Panda::CMS.config.posts[:prefix]}#{post.slug}") %>
|
12
12
|
</span>
|
13
13
|
</div>
|
14
14
|
<% end %>
|
15
|
-
<% table.column("Status") { |post| render Panda::
|
15
|
+
<% table.column("Status") { |post| render Panda::Core::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
17
|
<% table.column("Last Updated") { |post| render Panda::CMS::Admin::UserActivityComponent.new(at: post.updated_at)} %>
|
18
18
|
<% end %>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<%= render Panda::
|
1
|
+
<%= render Panda::Core::Admin::ContainerComponent.new do |component| %>
|
2
2
|
<% component.with_heading(text: "Settings", level: 1) %>
|
3
3
|
|
4
|
-
<%= render Panda::
|
4
|
+
<%= render Panda::Core::Admin::PanelComponent.new do |panel| %>
|
5
5
|
<% panel.with_heading(text: "System Status") %>
|
6
6
|
|
7
7
|
<p class="text-base leading-loose"><i class="mr-2 text-active fa fa-check-circle"></i> <span class="font-medium">Panda CMS:</span> v<%= Panda::CMS::VERSION %></p>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<p class="text-base leading-loose"><i class="mr-2 text-active fa fa-check-circle"></i> <span class="font-medium">Environment:</span> <%= Rails.env.titleize %></p>
|
11
11
|
<% end %>
|
12
12
|
|
13
|
-
<%= render Panda::
|
13
|
+
<%= render Panda::Core::Admin::PanelComponent.new do |panel| %>
|
14
14
|
<% panel.with_heading(text: "Integrations") %>
|
15
15
|
|
16
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>
|
@@ -19,10 +19,10 @@
|
|
19
19
|
</nav>
|
20
20
|
|
21
21
|
<% if content_for :sidebar %>
|
22
|
-
<div class="pt-4 pr-8 text-black/80" tabindex="-1">
|
23
|
-
<
|
22
|
+
<div class="pt-4 pr-8 text-black/80" tabindex="-1" data-controller="toggle">
|
23
|
+
<button type="button" id="slideover-toggle" data-action="click->toggle#toggle touch->toggle#toggle" class="text-sm font-light">
|
24
24
|
<i class="mr-1 fa-light fa-gear"></i> <%= yield :sidebar_title %>
|
25
|
-
</
|
25
|
+
</button>
|
26
26
|
</div>
|
27
27
|
<% end %>
|
28
28
|
</div>
|
@@ -2,12 +2,12 @@
|
|
2
2
|
<ul role="list" class="flex flex-col flex-1">
|
3
3
|
<a class="block p-0 mt-4 mb-4 ml-2 text-xl font-medium text-white"><%= Panda::CMS.config.title %></a>
|
4
4
|
<% [
|
5
|
-
{ path:
|
6
|
-
{ path:
|
7
|
-
{ path:
|
8
|
-
{ path:
|
9
|
-
{ path:
|
10
|
-
{ path:
|
5
|
+
{ path: admin_cms_dashboard_path, text: "Dashboard", icon: "fa-house", matcher: :exact },
|
6
|
+
{ path: admin_cms_pages_path, text: "Pages", icon: "fa-page", matcher: :starts_with },
|
7
|
+
{ path: admin_cms_posts_path, text: "Posts", icon: "fa-notebook", matcher: :starts_with },
|
8
|
+
{ path: admin_cms_forms_path, text: "Forms", icon: "fa-cabinet-filing", matcher: :starts_with },
|
9
|
+
{ path: admin_cms_menus_path, text: "Menus", icon: "fa-list-dropdown", matcher: :starts_with },
|
10
|
+
{ path: admin_cms_settings_path, text: "Settings", icon: "fa-cog", matcher: :starts_with },
|
11
11
|
].each do |link| %>
|
12
12
|
<li>
|
13
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 %>
|
@@ -17,13 +17,13 @@
|
|
17
17
|
</li>
|
18
18
|
<% end %>
|
19
19
|
<li>
|
20
|
-
<%= button_to admin_logout_path, method: :delete, id: "logout-link", data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
|
20
|
+
<%= button_to panda_core.admin_logout_path, method: :delete, id: "logout-link", data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
|
21
21
|
<span class="text-center"><i class="text-xl fa-regular fa-door-open fa-fw"></i></span>
|
22
22
|
<span class="mt-1">Logout</span>
|
23
23
|
<% end %>
|
24
24
|
</li>
|
25
25
|
<li class="mt-auto">
|
26
|
-
<%= link_to edit_admin_my_profile_path, class: nav_highlight_colour_classes(request) + " w-full", title: "Edit my Profile" do %>
|
26
|
+
<%= link_to panda_core.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 %>
|
@@ -4,9 +4,12 @@ Panda::CMS.configure do |config|
|
|
4
4
|
# The main title of your website
|
5
5
|
config.title = "Demo Site"
|
6
6
|
|
7
|
-
# The path to the administration panel
|
8
|
-
config.admin_path = "/admin"
|
9
|
-
|
10
7
|
# Site access control
|
11
8
|
config.require_login_to_view = false
|
12
9
|
end
|
10
|
+
|
11
|
+
# Admin path is now configured via Panda::Core
|
12
|
+
Panda::Core.configure do |config|
|
13
|
+
# The path to the administration panel
|
14
|
+
config.admin_path = "/admin"
|
15
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "../app/constraints/panda/cms/admin_constraint"
|
4
|
-
|
5
3
|
Panda::CMS::Engine.routes.draw do
|
6
|
-
constraints Panda::
|
7
|
-
|
4
|
+
constraints Panda::Core::AdminConstraint.new(&:present?) do
|
5
|
+
# CMS-specific dashboard (using Core's admin_path)
|
6
|
+
admin_path = Panda::Core.configuration.admin_path
|
7
|
+
get "#{admin_path}/cms", to: "admin/dashboard#show", as: :admin_cms_dashboard
|
8
|
+
|
9
|
+
namespace admin_path.delete_prefix("/").to_sym, path: "#{admin_path}/cms", as: :admin_cms, module: :admin do
|
8
10
|
resources :files
|
9
11
|
resources :forms, only: %i[index show]
|
10
12
|
resources :menus
|
@@ -15,28 +17,18 @@ Panda::CMS::Engine.routes.draw do
|
|
15
17
|
|
16
18
|
get "settings", to: "settings#index"
|
17
19
|
|
18
|
-
|
20
|
+
# Profile management moved to panda-core at /admin/my_profile
|
19
21
|
|
20
22
|
namespace :settings, as: :settings do
|
21
23
|
get "bulk_editor", to: "bulk_editor#new"
|
22
24
|
post "bulk_editor", to: "bulk_editor#create"
|
23
25
|
end
|
24
26
|
end
|
25
|
-
|
26
|
-
get Panda::CMS.route_namespace, to: "admin/dashboard#show", as: :admin_dashboard
|
27
27
|
end
|
28
28
|
|
29
29
|
### PUBLIC ROUTES ###
|
30
30
|
|
31
|
-
# Authentication routes
|
32
|
-
get Panda::CMS.route_namespace, to: "admin/sessions#new", as: :admin_login
|
33
|
-
# Get and post options here are for OmniAuth coming back in, not going out
|
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]
|
38
|
-
# OmniAuth additionally adds a GET route for "#{Panda::CMS.route_namespace}/auth/:provider" but doesn't name it
|
39
|
-
delete Panda::CMS.route_namespace, to: "admin/sessions#destroy", as: :admin_logout
|
31
|
+
# Authentication routes are now handled by Panda::Core
|
40
32
|
|
41
33
|
### APPENDED ROUTES ###
|
42
34
|
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
class AddAuthorIdToPandaCMSPosts < ActiveRecord::Migration[8.0]
|
4
4
|
def change
|
5
|
-
|
5
|
+
unless column_exists?(:panda_cms_posts, :author_id)
|
6
|
+
add_reference :panda_cms_posts, :author, type: :uuid, foreign_key: {to_table: :panda_core_users}
|
7
|
+
end
|
6
8
|
end
|
7
9
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
class MigrateUsersToPandaCore < ActiveRecord::Migration[8.0]
|
2
|
+
def up
|
3
|
+
# First ensure panda_core_users table exists (from Core engine)
|
4
|
+
# It should already exist from the Core migration
|
5
|
+
|
6
|
+
# Migrate data from panda_cms_users to panda_core_users if needed
|
7
|
+
if table_exists?(:panda_cms_users) && table_exists?(:panda_core_users)
|
8
|
+
# Check if there's any data to migrate
|
9
|
+
cms_user_count = ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM panda_cms_users")
|
10
|
+
return if cms_user_count == 0
|
11
|
+
# Copy all user data
|
12
|
+
execute <<-SQL
|
13
|
+
INSERT INTO panda_core_users (
|
14
|
+
id, name, email, image_url, is_admin, created_at, updated_at
|
15
|
+
)
|
16
|
+
SELECT
|
17
|
+
id,
|
18
|
+
COALESCE(name, CONCAT(firstname, ' ', lastname), 'Unknown User'),
|
19
|
+
email,
|
20
|
+
image_url,
|
21
|
+
COALESCE(admin, false),
|
22
|
+
created_at,
|
23
|
+
updated_at
|
24
|
+
FROM panda_cms_users
|
25
|
+
WHERE NOT EXISTS (
|
26
|
+
SELECT 1 FROM panda_core_users WHERE panda_core_users.id = panda_cms_users.id
|
27
|
+
)
|
28
|
+
SQL
|
29
|
+
|
30
|
+
# Update foreign key references in other tables
|
31
|
+
|
32
|
+
# Posts author_id
|
33
|
+
if column_exists?(:panda_cms_posts, :author_id)
|
34
|
+
remove_foreign_key :panda_cms_posts, column: :author_id if foreign_key_exists?(:panda_cms_posts, :panda_cms_users, column: :author_id)
|
35
|
+
add_foreign_key :panda_cms_posts, :panda_core_users, column: :author_id, primary_key: :id
|
36
|
+
end
|
37
|
+
|
38
|
+
# Posts user_id (legacy column)
|
39
|
+
if column_exists?(:panda_cms_posts, :user_id)
|
40
|
+
remove_foreign_key :panda_cms_posts, column: :user_id if foreign_key_exists?(:panda_cms_posts, :panda_cms_users, column: :user_id)
|
41
|
+
add_foreign_key :panda_cms_posts, :panda_core_users, column: :user_id, primary_key: :id
|
42
|
+
end
|
43
|
+
|
44
|
+
# Visits user_id
|
45
|
+
if column_exists?(:panda_cms_visits, :user_id)
|
46
|
+
remove_foreign_key :panda_cms_visits, column: :user_id if foreign_key_exists?(:panda_cms_visits, :panda_cms_users, column: :user_id)
|
47
|
+
add_foreign_key :panda_cms_visits, :panda_core_users, column: :user_id, primary_key: :id
|
48
|
+
end
|
49
|
+
|
50
|
+
# Drop the old table
|
51
|
+
drop_table :panda_cms_users
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def down
|
56
|
+
# Recreate panda_cms_users table
|
57
|
+
create_table :panda_cms_users, id: :uuid do |t|
|
58
|
+
t.string :name
|
59
|
+
t.string :firstname
|
60
|
+
t.string :lastname
|
61
|
+
t.string :email, null: false
|
62
|
+
t.string :image_url
|
63
|
+
t.boolean :admin, default: false
|
64
|
+
t.string :current_theme, default: "default"
|
65
|
+
t.timestamps
|
66
|
+
end
|
67
|
+
|
68
|
+
add_index :panda_cms_users, :email, unique: true
|
69
|
+
|
70
|
+
# Migrate data back
|
71
|
+
if table_exists?(:panda_core_users) && table_exists?(:panda_cms_users)
|
72
|
+
execute <<-SQL
|
73
|
+
INSERT INTO panda_cms_users (
|
74
|
+
id, firstname, lastname, name, email, image_url, admin, current_theme, created_at, updated_at
|
75
|
+
)
|
76
|
+
SELECT
|
77
|
+
id,
|
78
|
+
split_part(name, ' ', 1),
|
79
|
+
CASE
|
80
|
+
WHEN position(' ' IN name) > 0
|
81
|
+
THEN substring(name FROM position(' ' IN name) + 1)
|
82
|
+
ELSE ''
|
83
|
+
END,
|
84
|
+
name,
|
85
|
+
email,
|
86
|
+
image_url,
|
87
|
+
is_admin,
|
88
|
+
'default',
|
89
|
+
created_at,
|
90
|
+
updated_at
|
91
|
+
FROM panda_core_users
|
92
|
+
SQL
|
93
|
+
|
94
|
+
# Restore foreign keys to panda_cms_users
|
95
|
+
if column_exists?(:panda_cms_posts, :author_id)
|
96
|
+
remove_foreign_key :panda_cms_posts, column: :author_id if foreign_key_exists?(:panda_cms_posts, column: :author_id)
|
97
|
+
add_foreign_key :panda_cms_posts, :panda_cms_users, column: :author_id, primary_key: :id
|
98
|
+
end
|
99
|
+
|
100
|
+
if column_exists?(:panda_cms_posts, :user_id)
|
101
|
+
remove_foreign_key :panda_cms_posts, column: :user_id if foreign_key_exists?(:panda_cms_posts, column: :user_id)
|
102
|
+
add_foreign_key :panda_cms_posts, :panda_cms_users, column: :user_id, primary_key: :id
|
103
|
+
end
|
104
|
+
|
105
|
+
if column_exists?(:panda_cms_visits, :user_id)
|
106
|
+
remove_foreign_key :panda_cms_visits, column: :user_id if foreign_key_exists?(:panda_cms_visits, column: :user_id)
|
107
|
+
add_foreign_key :panda_cms_visits, :panda_cms_users, column: :user_id, primary_key: :id
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class MakePostUserReferencesNullable < ActiveRecord::Migration[8.0]
|
4
|
+
def change
|
5
|
+
# Make user_id and author_id nullable for posts
|
6
|
+
# This is needed because fixtures can't reference users from another gem
|
7
|
+
# Tests that need users will set them programmatically
|
8
|
+
change_column_null :panda_cms_posts, :user_id, true
|
9
|
+
change_column_null :panda_cms_posts, :author_id, true
|
10
|
+
end
|
11
|
+
end
|
@@ -111,15 +111,15 @@ module Panda
|
|
111
111
|
version = asset_version
|
112
112
|
js_url = "/panda-cms-assets/panda-cms-#{version}.js"
|
113
113
|
css_url = "/panda-cms-assets/panda-cms-#{version}.css"
|
114
|
-
|
114
|
+
|
115
115
|
tags = []
|
116
|
-
|
116
|
+
|
117
117
|
# JavaScript tag
|
118
118
|
tags << content_tag(:script, "", {
|
119
119
|
src: js_url,
|
120
120
|
defer: true
|
121
121
|
})
|
122
|
-
|
122
|
+
|
123
123
|
# CSS tag if exists
|
124
124
|
if cached_asset_exists?(css_url)
|
125
125
|
tags << tag(:link, {
|
@@ -127,7 +127,7 @@ module Panda
|
|
127
127
|
href: css_url
|
128
128
|
})
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
tags.join("\n").html_safe
|
132
132
|
else
|
133
133
|
# In development, just use a simple script tag
|