panda_cms 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of panda_cms might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +72 -0
- data/Rakefile +8 -0
- data/app/assets/builds/panda_cms.css +1 -0
- data/app/assets/config/panda_cms_manifest.js +1 -0
- data/app/assets/stylesheets/panda_cms/application.tailwind.css +30 -0
- data/app/builders/panda_cms/form_builder.rb +118 -0
- data/app/components/panda_cms/admin/button_component.rb +65 -0
- data/app/components/panda_cms/admin/container_component.html.erb +13 -0
- data/app/components/panda_cms/admin/container_component.rb +11 -0
- data/app/components/panda_cms/admin/flash_message_component.html.erb +30 -0
- data/app/components/panda_cms/admin/flash_message_component.rb +44 -0
- data/app/components/panda_cms/admin/heading_component.rb +38 -0
- data/app/components/panda_cms/admin/slideover_component.html.erb +9 -0
- data/app/components/panda_cms/admin/slideover_component.rb +13 -0
- data/app/components/panda_cms/admin/tab_bar_component.html.erb +35 -0
- data/app/components/panda_cms/admin/tab_bar_component.rb +13 -0
- data/app/components/panda_cms/grid_component.html.erb +6 -0
- data/app/components/panda_cms/grid_component.rb +13 -0
- data/app/components/panda_cms/menu_component.html.erb +3 -0
- data/app/components/panda_cms/menu_component.rb +18 -0
- data/app/components/panda_cms/page_menu_component.html.erb +24 -0
- data/app/components/panda_cms/page_menu_component.rb +24 -0
- data/app/components/panda_cms/rich_text_component.html.erb +40 -0
- data/app/components/panda_cms/rich_text_component.rb +35 -0
- data/app/components/panda_cms/text_component.rb +63 -0
- data/app/constraints/panda_cms/admin_constraint.rb +16 -0
- data/app/controllers/panda_cms/admin/block_contents_controller.rb +42 -0
- data/app/controllers/panda_cms/admin/dashboard_controller.rb +15 -0
- data/app/controllers/panda_cms/admin/files_controller.rb +17 -0
- data/app/controllers/panda_cms/admin/menus_controller.rb +81 -0
- data/app/controllers/panda_cms/admin/pages_controller.rb +88 -0
- data/app/controllers/panda_cms/admin/sessions_controller.rb +72 -0
- data/app/controllers/panda_cms/application_controller.rb +51 -0
- data/app/controllers/panda_cms/errors_controller.rb +31 -0
- data/app/controllers/panda_cms/pages_controller.rb +33 -0
- data/app/helpers/panda_cms/admin/files_helper.rb +4 -0
- data/app/helpers/panda_cms/admin/pages_helper.rb +4 -0
- data/app/helpers/panda_cms/application_helper.rb +91 -0
- data/app/helpers/panda_cms/pages_helper.rb +4 -0
- data/app/helpers/panda_cms/theme_helper.rb +16 -0
- data/app/javascript/panda_cms/base.js +37 -0
- data/app/javascript/panda_cms/controllers/menu_controller.js +19 -0
- data/app/javascript/panda_cms/controllers/rich_text_editor_controller.js +59 -0
- data/app/javascript/panda_cms/controllers/text_field_update_controller.js +23 -0
- data/app/javascript/panda_cms/vendor/stimulus-components-rails-nested-form.js +2 -0
- data/app/javascript/panda_cms/vendor/tailwindcss-stimulus-components.js +2 -0
- data/app/jobs/panda_cms/application_job.rb +4 -0
- data/app/lib/panda_cms/demo_site_generator.rb +70 -0
- data/app/lib/panda_cms/slug.rb +21 -0
- data/app/mailers/panda_cms/application_mailer.rb +6 -0
- data/app/models/panda_cms/application_record.rb +5 -0
- data/app/models/panda_cms/block.rb +32 -0
- data/app/models/panda_cms/block_content.rb +16 -0
- data/app/models/panda_cms/block_content_version.rb +6 -0
- data/app/models/panda_cms/breadcrumb.rb +10 -0
- data/app/models/panda_cms/current.rb +15 -0
- data/app/models/panda_cms/menu.rb +50 -0
- data/app/models/panda_cms/menu_item.rb +56 -0
- data/app/models/panda_cms/page.rb +86 -0
- data/app/models/panda_cms/page_version.rb +6 -0
- data/app/models/panda_cms/redirect.rb +9 -0
- data/app/models/panda_cms/template.rb +44 -0
- data/app/models/panda_cms/template_version.rb +6 -0
- data/app/models/panda_cms/user.rb +11 -0
- data/app/models/panda_cms/version.rb +6 -0
- data/app/models/panda_cms/visit.rb +7 -0
- data/app/views/layouts/panda_cms/application.html.erb +68 -0
- data/app/views/layouts/panda_cms/public.html.erb +3 -0
- data/app/views/panda_cms/admin/dashboard/show.html.erb +8 -0
- data/app/views/panda_cms/admin/files/index.html.erb +124 -0
- data/app/views/panda_cms/admin/files/show.html.erb +2 -0
- data/app/views/panda_cms/admin/menus/_form.html.erb +21 -0
- data/app/views/panda_cms/admin/menus/_menu_item_fields.html.erb +7 -0
- data/app/views/panda_cms/admin/menus/edit.html.erb +58 -0
- data/app/views/panda_cms/admin/menus/index.html.erb +32 -0
- data/app/views/panda_cms/admin/menus/new.html.erb +5 -0
- data/app/views/panda_cms/admin/pages/edit.html.erb +35 -0
- data/app/views/panda_cms/admin/pages/index.html.erb +46 -0
- data/app/views/panda_cms/admin/pages/new.html.erb +16 -0
- data/app/views/panda_cms/admin/pages/show.html.erb +1 -0
- data/app/views/panda_cms/admin/sessions/new.html.erb +39 -0
- data/app/views/panda_cms/admin/shared/_breadcrumbs.html.erb +25 -0
- data/app/views/panda_cms/admin/shared/_flash.html.erb +5 -0
- data/app/views/panda_cms/admin/shared/_sidebar.html.erb +29 -0
- data/app/views/panda_cms/shared/_favicons.html.erb +9 -0
- data/app/views/panda_cms/shared/_footer.html.erb +2 -0
- data/app/views/panda_cms/shared/_header.html.erb +19 -0
- data/config/importmap.rb +7 -0
- data/config/initializers/panda_cms/form_errors.rb +38 -0
- data/config/initializers/panda_cms.rb +42 -0
- data/config/locales/en.yml +13 -0
- data/config/routes.rb +26 -0
- data/config/tailwind.config.js +31 -0
- data/config/tailwind.embed.config.js +20 -0
- data/db/migrate/20240205223709_create_panda_cms_pages.rb +9 -0
- data/db/migrate/20240219213327_create_panda_cms_page_versions.rb +14 -0
- data/db/migrate/20240303002805_create_panda_cms_templates.rb +11 -0
- data/db/migrate/20240303003434_create_panda_cms_template_versions.rb +14 -0
- data/db/migrate/20240303022441_create_panda_cms_blocks.rb +13 -0
- data/db/migrate/20240303024256_create_panda_cms_block_contents.rb +10 -0
- data/db/migrate/20240303024746_create_panda_cms_block_content_versions.rb +14 -0
- data/db/migrate/20240303233238_add_panda_cms_menu_table.rb +10 -0
- data/db/migrate/20240303234724_add_panda_cms_menu_item_table.rb +12 -0
- data/db/migrate/20240304134343_add_parent_id_to_panda_cms_pages.rb +5 -0
- data/db/migrate/20240315125421_add_nested_sets_to_panda_cms_pages.rb +16 -0
- data/db/migrate/20240316212822_add_kind_to_panda_cms_menus.rb +6 -0
- data/db/migrate/20240316221425_add_start_page_to_panda_cms_menus.rb +5 -0
- data/db/migrate/20240316230706_add_nested_to_panda_cms_menu_items.rb +24 -0
- data/db/migrate/20240317010532_create_panda_cms_users.rb +12 -0
- data/db/migrate/20240317161534_add_max_uses_to_panda_cms_template.rb +7 -0
- data/db/migrate/20240317163053_reset_counter_cache_on_panda_cms_template.rb +5 -0
- data/db/migrate/20240317214827_create_panda_cms_redirects.rb +15 -0
- data/db/migrate/20240317230622_create_panda_cms_visits.rb +13 -0
- data/db/migrate/20240324205703_create_active_storage_tables.active_storage.rb +58 -0
- data/db/migrate/20240408084718_default_panda_cms_users_admin_to_false.rb +5 -0
- data/db/seeds.rb +4 -0
- data/lib/generators/panda_cms/install_generator.rb +32 -0
- data/lib/panda_cms/engine.rb +172 -0
- data/lib/panda_cms/exceptions_app.rb +24 -0
- data/lib/panda_cms/version.rb +3 -0
- data/lib/panda_cms.rb +14 -0
- data/lib/tasks/panda_cms.rake +67 -0
- data/lib/templates/erb/scaffold/_form.html.erb.tt +43 -0
- data/lib/templates/erb/scaffold/edit.html.erb.tt +8 -0
- data/lib/templates/erb/scaffold/index.html.erb.tt +14 -0
- data/lib/templates/erb/scaffold/new.html.erb.tt +7 -0
- data/lib/templates/erb/scaffold/partial.html.erb.tt +22 -0
- data/lib/templates/erb/scaffold/show.html.erb.tt +15 -0
- data/public/panda-cms-assets/android-chrome-192x192.png +0 -0
- data/public/panda-cms-assets/android-chrome-512x512.png +0 -0
- data/public/panda-cms-assets/apple-touch-icon.png +0 -0
- data/public/panda-cms-assets/browserconfig.xml +9 -0
- data/public/panda-cms-assets/editable.js +212 -0
- data/public/panda-cms-assets/favicon-16x16.png +0 -0
- data/public/panda-cms-assets/favicon-32x32.png +0 -0
- data/public/panda-cms-assets/favicon.ico +0 -0
- data/public/panda-cms-assets/mstile-150x150.png +0 -0
- data/public/panda-cms-assets/panda-logo-screenprint.png +0 -0
- data/public/panda-cms-assets/panda-nav.png +0 -0
- data/public/panda-cms-assets/safari-pinned-tab.svg +61 -0
- data/public/panda-cms-assets/site.webmanifest +14 -0
- data/public/panda-cms-assets/stimulus-loading.js +113 -0
- metadata +845 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8 text-center">
|
2
|
+
<div class="sm:mx-auto sm:w-full sm:max-w-sm text-center">
|
3
|
+
<img src="/panda-cms-assets/panda-nav.png" class="py-2 h-32 mx-auto w-auto">
|
4
|
+
<h2 class="mt-10 mb-6 text-center text-2xl font-bold text-white">Sign in to your account</h2>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<% if PandaCms.authentication.dig(:google, :enabled) %>
|
8
|
+
<div class="mt-4 text-center sm:mx-auto sm:w-full sm:max-w-sm">
|
9
|
+
<%= form_tag "#{PandaCms.admin_path}/auth/google", method: "post", data: {turbo: false} do %>
|
10
|
+
<button type="submit" class="min-w-56 mx-auto mb-4 inline-flex items-center gap-x-2 rounded-md bg-white px-3.5 py-2.5 border border-neutral-400">
|
11
|
+
<i class="fa-brands fa-google text-xl mr-1"></i>
|
12
|
+
Sign in with Google
|
13
|
+
</button>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if PandaCms.authentication.dig(:microsoft, :enabled) %>
|
19
|
+
<div class="mt-4 text-center sm:mx-auto sm:w-full sm:max-w-sm">
|
20
|
+
<%= form_tag "#{PandaCms.admin_path}/auth/microsoft", method: "post", data: {turbo: false} do %>
|
21
|
+
<button type="submit" class="min-w-56 mx-auto mb-4 inline-flex items-center gap-x-2 rounded-md bg-white px-3.5 py-2.5 border border-neutral-400">
|
22
|
+
<i class="fa-brands fa-microsoft text-xl mr-1"></i>
|
23
|
+
Sign in with Microsoft
|
24
|
+
</button>
|
25
|
+
<% end %>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<% if PandaCms.authentication.dig(:github, :enabled) %>
|
30
|
+
<div class="mt-4 text-center sm:mx-auto sm:w-full sm:max-w-sm">
|
31
|
+
<%= form_tag "#{PandaCms.admin_path}/auth/github", method: "post", data: {turbo: false} do %>
|
32
|
+
<button type="submit" id="button-sign-in-github" class="min-w-56 mx-auto mb-4 inline-flex items-center gap-x-2 rounded-md bg-white px-3.5 py-2.5 border border-neutral-400">
|
33
|
+
<i class="fa-brands fa-github text-xl mr-1"></i>
|
34
|
+
Sign in with GitHub
|
35
|
+
</button>
|
36
|
+
<% end %>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
<nav class="flex bg-white border-b border-gray-200" aria-label="Breadcrumb" id="panda-breadcrumbs">
|
3
|
+
<ol role="list" class="flex px-4 space-x-2 w-full sm:px-6">
|
4
|
+
<li class="flex">
|
5
|
+
<div class="flex items-center">
|
6
|
+
<a href="/admin" class="text-gray-400 hover:text-gray-500">
|
7
|
+
<svg class="flex-shrink-0 w-5 h-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
8
|
+
<path fill-rule="evenodd" d="M9.293 2.293a1 1 0 011.414 0l7 7A1 1 0 0117 11h-1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-3a1 1 0 00-1-1H9a1 1 0 00-1 1v3a1 1 0 01-1 1H5a1 1 0 01-1-1v-6H3a1 1 0 01-.707-1.707l7-7z" clip-rule="evenodd" />
|
9
|
+
</svg>
|
10
|
+
<span class="sr-only">Home</span>
|
11
|
+
</a>
|
12
|
+
</div>
|
13
|
+
</li>
|
14
|
+
<% breadcrumbs.each do |crumb| %>
|
15
|
+
<li class="flex">
|
16
|
+
<div class="flex items-center">
|
17
|
+
<svg class="flex-shrink-0 w-6 h-full text-gray-200" viewBox="0 0 24 44" preserveAspectRatio="none" fill="currentColor" aria-hidden="true">
|
18
|
+
<path d="M.293 0l22 22-22 22h1.414l22-22-22-22H.293z" />
|
19
|
+
</svg>
|
20
|
+
<a href="<%= crumb.path %>" class="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700"><%= crumb.name %></a>
|
21
|
+
</div>
|
22
|
+
</li>
|
23
|
+
<% end %>
|
24
|
+
</ol>
|
25
|
+
</nav>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<nav class="flex flex-1 flex-col">
|
2
|
+
<ul role="list" class="flex flex-1 flex-col">
|
3
|
+
<li>
|
4
|
+
<img src="/panda-cms-assets/panda-nav.png" class="lg:h-32 h-16 py-2 w-auto inline">
|
5
|
+
<a class="text-white font-medium text-lg ml-2 lg:hidden"><%= PandaCms.title %></a>
|
6
|
+
<a class="text-white right-0 absolute text-lg mt-4 mr-5 lg:hidden" href="#" data-action="click->panda-cms-menu#toggle touch->panda-cms-menu#toggle"><i class="fa-sharp fa-solid fa-bars text-white mr-2"></i> Menu</a>
|
7
|
+
</li>
|
8
|
+
|
9
|
+
<% [
|
10
|
+
{ path: admin_dashboard_path, text: "Dashboard", icon: "fa-house", matcher: :exact },
|
11
|
+
{ path: admin_pages_path, text: "Pages", icon: "fa-page", matcher: :starts_with },
|
12
|
+
{ path: admin_menus_path, text: "Menus", icon: "fa-list-dropdown", matcher: :starts_with },
|
13
|
+
{ path: "#", text: "Settings", icon: "fa-cog" },
|
14
|
+
].each do |link| %>
|
15
|
+
<li>
|
16
|
+
<%= 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
|
+
<span class="text-center"><i class="fa-solid <%= link[:icon] %> text-xl fa-fw"></i></span>
|
18
|
+
<span><%= link[:text] %></span>
|
19
|
+
<% end %>
|
20
|
+
</li>
|
21
|
+
<% end %>
|
22
|
+
<li>
|
23
|
+
<%= button_to admin_logout_path, method: :delete, data: { turbo: false }, class: nav_highlight_colour_classes(request) + " w-full" do %>
|
24
|
+
<span class="text-center"><i class="fa-solid fa-door-open text-xl fa-fw"></i></span>
|
25
|
+
<span>Sign Out</span>
|
26
|
+
<% end %>
|
27
|
+
</li>
|
28
|
+
</ul>
|
29
|
+
</nav>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/panda-cms-assets/apple-touch-icon.png">
|
2
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/panda-cms-assets/favicon-32x32.png">
|
3
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/panda-cms-assets/favicon-16x16.png">
|
4
|
+
<link rel="manifest" href="/panda-cms-assets/site.webmanifest">
|
5
|
+
<link rel="mask-icon" href="/panda-cms-assets/safari-pinned-tab.svg" color="#5bbad5">
|
6
|
+
<link rel="shortcut icon" href="/panda-cms-assets/favicon.ico">
|
7
|
+
<meta name="msapplication-TileColor" content="#b91d47">
|
8
|
+
<meta name="msapplication-config" content="/panda-cms-assets/browserconfig.xml">
|
9
|
+
<meta name="theme-color" content="#ffffff">
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html class="<%= html_class ||= 'bg-gray-50' %>">
|
3
|
+
<head>
|
4
|
+
<title>Panda CMS</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
<script src="https://kit.fontawesome.com/4da51334eb.js" crossorigin="anonymous"></script>
|
8
|
+
<link rel="stylesheet" href="https://use.typekit.net/him4vgh.css">
|
9
|
+
<script async src="https://ga.jspm.io/npm:es-module-shims@1.10.0/dist/es-module-shims.js" crossorigin="anonymous"></script>
|
10
|
+
<%= stylesheet_link_tag "panda_cms", "data-turbo-track": "reload" %>
|
11
|
+
<script type="importmap" data-turbo-track="reload"> <%# erblint:disable AllowedScriptType %>
|
12
|
+
<%= raw(PandaCms::Engine.importmap.to_json(resolver: self)) %>
|
13
|
+
</script>
|
14
|
+
<%= javascript_import_module_tag "panda_cms/base" %>
|
15
|
+
<%= render "panda_cms/shared/favicons" %>
|
16
|
+
</head>
|
17
|
+
|
18
|
+
<body class="overflow-hidden h-full">
|
19
|
+
<%= render "panda_cms/admin/shared/flash" %>
|
data/config/importmap.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:stimulus@3.2.2/dist/stimulus.js"
|
2
|
+
# TODO: Pin to a URL on our CDN
|
3
|
+
pin "@hotwired/stimulus-loading", to: "/panda-cms-assets/stimulus-loading.js" # 3.2.2
|
4
|
+
|
5
|
+
pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms/vendor"), under: "vendor", to: "panda_cms/vendor"
|
6
|
+
pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms"), under: "panda_cms", to: "panda_cms"
|
7
|
+
pin_all_from PandaCms::Engine.root.join("app/javascript/panda_cms/controllers"), under: "panda_cms/controllers", to: "panda_cms/controllers"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
ActionView::Base.field_error_proc = proc do |html_tag, instance|
|
2
|
+
html = ""
|
3
|
+
form_fields = %w[input select textarea trix-editor label].join(", ")
|
4
|
+
error_class = "text-red-600 dark:text-red-500 bg-red-50 border-red-500 border-1 box-shadow-red-500 focus:ring-red-500 focus:border-red-500 dark:bg-red-900 dark:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500"
|
5
|
+
message_class = "block w-full text-sm font-bold p-0 m-0 mt-1 text-red-700"
|
6
|
+
autofocused = false
|
7
|
+
|
8
|
+
Nokogiri::HTML::DocumentFragment.parse(html_tag).css(form_fields).each do |element|
|
9
|
+
if form_fields.include?(element.node_name)
|
10
|
+
if !autofocused
|
11
|
+
# element.attribute("autofocus", "true")
|
12
|
+
autofocused = true
|
13
|
+
end
|
14
|
+
|
15
|
+
message = "#{instance.object.class.human_attribute_name(instance.send(:sanitized_method_name))} "
|
16
|
+
message += if instance.error_message.respond_to?(:each)
|
17
|
+
"#{instance.error_message.uniq.to_sentence}."
|
18
|
+
else
|
19
|
+
"#{instance.error_message}."
|
20
|
+
end
|
21
|
+
|
22
|
+
if element.node_name.eql?("label")
|
23
|
+
html = element.to_s
|
24
|
+
else
|
25
|
+
element.add_class(error_class)
|
26
|
+
html = if element.get_attribute("data-prefix")
|
27
|
+
"#{element}</div><div class=\"#{message_class}\">#{message}"
|
28
|
+
elsif element.get_attribute("type") != "checkbox"
|
29
|
+
"#{element}<div class=\"#{message_class}\">#{message}</div>"
|
30
|
+
else
|
31
|
+
element.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
html.html_safe
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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"
|
27
|
+
},
|
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: true
|
31
|
+
},
|
32
|
+
google: {
|
33
|
+
enabled: false,
|
34
|
+
create_account_on_first_login: true,
|
35
|
+
create_admin_account_on_first_login: false
|
36
|
+
},
|
37
|
+
github: {
|
38
|
+
enabled: true,
|
39
|
+
create_account_on_first_login: true,
|
40
|
+
create_admin_account_on_first_login: false
|
41
|
+
}
|
42
|
+
}
|
data/config/routes.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "../app/constraints/panda_cms/admin_constraint"
|
2
|
+
|
3
|
+
PandaCms::Engine.routes.draw do
|
4
|
+
constraints PandaCms::AdminConstraint.new { |user| user.present? } do
|
5
|
+
namespace PandaCms.admin_path_symbol.to_sym, as: :admin, module: :admin do
|
6
|
+
resources :files
|
7
|
+
resources :pages do
|
8
|
+
resources :block_contents, only: %i[update]
|
9
|
+
end
|
10
|
+
resources :menus
|
11
|
+
end
|
12
|
+
|
13
|
+
get PandaCms.admin_path, to: "admin/dashboard#show", as: :admin_dashboard
|
14
|
+
end
|
15
|
+
|
16
|
+
### PUBLIC ROUTES ###
|
17
|
+
|
18
|
+
# Authentication routes
|
19
|
+
get PandaCms.admin_path, to: "admin/sessions#new", as: :admin_login
|
20
|
+
match "#{PandaCms.admin_path}/auth/:provider/callback", to: "admin/sessions#create", as: :admin_login_callback, via: %i[get post]
|
21
|
+
delete PandaCms.admin_path, to: "admin/sessions#destroy", as: :admin_logout
|
22
|
+
|
23
|
+
### INHERITED ROUTES ###
|
24
|
+
|
25
|
+
# See lib/panda_cms/engine.rb
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module.exports = {
|
2
|
+
content: {
|
3
|
+
relative: true,
|
4
|
+
files: [
|
5
|
+
"../public/*.html",
|
6
|
+
"../app/views/**/*.html.erb",
|
7
|
+
"../app/components/panda_cms/**/*.html.erb",
|
8
|
+
"../app/components/panda_cms/**/*.rb",
|
9
|
+
"../app/helpers/panda_cms/**/*.rb",
|
10
|
+
"../app/javascript/panda_cms/**/*.js",
|
11
|
+
"../vendor/javascript/**/*.js",
|
12
|
+
],
|
13
|
+
},
|
14
|
+
theme: {
|
15
|
+
extend: {
|
16
|
+
colors: {
|
17
|
+
"panda-cms": {
|
18
|
+
light: "#C8F5FF",
|
19
|
+
dark: "#282E32",
|
20
|
+
alternate: "#FB61BD",
|
21
|
+
},
|
22
|
+
},
|
23
|
+
},
|
24
|
+
},
|
25
|
+
plugins: [
|
26
|
+
require("@tailwindcss/forms"),
|
27
|
+
require("@tailwindcss/aspect-ratio"),
|
28
|
+
require("@tailwindcss/typography"),
|
29
|
+
require("@tailwindcss/container-queries"),
|
30
|
+
],
|
31
|
+
};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module.exports = {
|
2
|
+
content: [
|
3
|
+
"./app/helpers/**/*.rb",
|
4
|
+
"./app/components/**/*.rb",
|
5
|
+
"./app/components/**/*.html.erb",
|
6
|
+
],
|
7
|
+
theme: {
|
8
|
+
extend: {
|
9
|
+
colors: {
|
10
|
+
panda: {
|
11
|
+
light: "#86a9db",
|
12
|
+
dark: "#404c5c",
|
13
|
+
alternate: "#ea565d"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
},
|
17
|
+
},
|
18
|
+
plugins: [],
|
19
|
+
prefix: "panda-cms-"
|
20
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreatePandaCmsPageVersions < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_page_versions, id: :uuid do |t|
|
4
|
+
t.string :item_type, null: false
|
5
|
+
t.string :item_id, null: false
|
6
|
+
t.string :event, null: false
|
7
|
+
t.string :whodunnit
|
8
|
+
t.jsonb :object
|
9
|
+
t.jsonb :object_changes
|
10
|
+
t.datetime :created_at
|
11
|
+
end
|
12
|
+
add_index :panda_cms_page_versions, %i[item_type item_id]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreatePandaCmsTemplates < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_templates, id: :uuid do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :file_path
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
add_reference :panda_cms_pages, :panda_cms_template, type: :uuid, foreign_key: {to_table: :panda_cms_templates}, null: false
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreatePandaCmsTemplateVersions < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_template_versions, id: :uuid do |t|
|
4
|
+
t.string :item_type, null: false
|
5
|
+
t.string :item_id, null: false
|
6
|
+
t.string :event, null: false
|
7
|
+
t.string :whodunnit
|
8
|
+
t.jsonb :object
|
9
|
+
t.jsonb :object_changes
|
10
|
+
t.datetime :created_at
|
11
|
+
end
|
12
|
+
add_index :panda_cms_template_versions, %i[item_type item_id]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreatePandaCmsBlocks < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_enum :panda_cms_block_kind, ["plain_text", "rich_text", "image", "video", "audio", "file", "code", "iframe", "quote", "list", "table", "form"]
|
4
|
+
|
5
|
+
create_table :panda_cms_blocks, id: :uuid do |t|
|
6
|
+
t.enum :kind, enum_type: :panda_cms_block_kind, default: "plain_text", null: false
|
7
|
+
t.string :name
|
8
|
+
t.string :key
|
9
|
+
t.references :panda_cms_template, type: :uuid, foreign_key: {to_table: :panda_cms_templates}, null: false
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class CreatePandaCmsBlockContents < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_block_contents, id: :uuid do |t|
|
4
|
+
t.references :panda_cms_page, null: false, foreign_key: true, type: :uuid
|
5
|
+
t.references :panda_cms_block, null: false, foreign_key: true, type: :uuid
|
6
|
+
t.jsonb :content, null: false, default: {}
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreatePandaCmsBlockContentVersions < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_block_content_versions, id: :uuid do |t|
|
4
|
+
t.string :item_type, null: false
|
5
|
+
t.string :item_id, null: false
|
6
|
+
t.string :event, null: false
|
7
|
+
t.string :whodunnit
|
8
|
+
t.jsonb :object
|
9
|
+
t.jsonb :object_changes
|
10
|
+
t.datetime :created_at
|
11
|
+
end
|
12
|
+
add_index :panda_cms_block_content_versions, %i[item_type item_id]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class AddPandaCmsMenuItemTable < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_menu_items, id: :uuid do |t|
|
4
|
+
t.string :text, null: false
|
5
|
+
t.references :panda_cms_menu, null: false, foreign_key: true, type: :uuid
|
6
|
+
t.references :panda_cms_page, null: true, foreign_key: true, type: :uuid
|
7
|
+
t.string :external_url, null: true
|
8
|
+
t.integer :sort_order, default: 1
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class AddNestedSetsToPandaCmsPages < ActiveRecord::Migration[7.1]
|
2
|
+
def self.up
|
3
|
+
PandaCms::Page.where(parent_id: 0).update_all(parent_id: nil)
|
4
|
+
add_column :panda_cms_pages, :lft, :integer
|
5
|
+
add_column :panda_cms_pages, :rgt, :integer
|
6
|
+
|
7
|
+
# This is necessary to update :lft and :rgt columns
|
8
|
+
PandaCms::Page.reset_column_information
|
9
|
+
PandaCms::Page.rebuild!
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
remove_column :panda_cms_pages, :lft
|
14
|
+
remove_column :panda_cms_pages, :rgt
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class AddNestedToPandaCmsMenuItems < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
add_column :panda_cms_menu_items, :parent_id, :uuid
|
4
|
+
add_column :panda_cms_menu_items, :lft, :integer
|
5
|
+
add_column :panda_cms_menu_items, :rgt, :integer
|
6
|
+
add_column :panda_cms_menu_items, :depth, :integer
|
7
|
+
add_column :panda_cms_menu_items, :children_count, :integer, null: false, default: 0
|
8
|
+
|
9
|
+
add_index :panda_cms_menu_items, :lft
|
10
|
+
add_index :panda_cms_menu_items, :rgt
|
11
|
+
|
12
|
+
PandaCms::MenuItem.reset_column_information
|
13
|
+
PandaCms::MenuItem.rebuild!
|
14
|
+
|
15
|
+
# Update pages whilst we're at it
|
16
|
+
add_column :panda_cms_pages, :depth, :integer
|
17
|
+
add_column :panda_cms_pages, :children_count, :integer, null: false, default: 0
|
18
|
+
add_index :panda_cms_pages, :lft
|
19
|
+
add_index :panda_cms_pages, :rgt
|
20
|
+
|
21
|
+
PandaCms::Page.reset_column_information
|
22
|
+
PandaCms::Page.rebuild!
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreatePandaCmsUsers < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_users, id: :uuid do |t|
|
4
|
+
t.string :firstname
|
5
|
+
t.string :lastname
|
6
|
+
t.string :email
|
7
|
+
t.string :image_url
|
8
|
+
t.boolean :admin
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class AddMaxUsesToPandaCmsTemplate < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
add_column :panda_cms_templates, :max_uses, :integer, null: true, default: nil
|
4
|
+
add_column :panda_cms_templates, :pages_count, :integer, default: 0
|
5
|
+
PandaCms::Template.find_by(name: "Homepage")&.update(max_uses: 1)
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreatePandaCmsRedirects < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_redirects, id: :uuid do |t|
|
4
|
+
t.string :origin_path, null: true
|
5
|
+
t.string :destination_path, null: true
|
6
|
+
t.references :origin_panda_cms_page, null: true, foreign_key: {to_table: :panda_cms_pages}, type: :uuid
|
7
|
+
t.references :destination_panda_cms_page, null: true, foreign_key: {to_table: :panda_cms_pages}, type: :uuid
|
8
|
+
t.integer :status_code, default: 301, null: false
|
9
|
+
t.integer :visits, default: 0, null: false
|
10
|
+
t.datetime :last_visited_at, null: true
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreatePandaCmsVisits < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :panda_cms_visits, id: :uuid do |t|
|
4
|
+
t.string :ip_address, null: true
|
5
|
+
t.string :user_agent, null: true
|
6
|
+
|
7
|
+
t.references :panda_cms_page, null: true, foreign_key: true, type: :uuid
|
8
|
+
t.references :panda_cms_redirect, null: true, foreign_key: true, type: :uuid
|
9
|
+
t.references :panda_cms_user, null: true, foreign_key: true, type: :uuid
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# This migration comes from active_storage (originally 20170806125915)
|
2
|
+
class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
|
3
|
+
def change
|
4
|
+
# Use Active Record's configured type for primary and foreign keys
|
5
|
+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
6
|
+
|
7
|
+
create_table :active_storage_blobs, id: primary_key_type do |t|
|
8
|
+
t.string :key, null: false
|
9
|
+
t.string :filename, null: false
|
10
|
+
t.string :content_type
|
11
|
+
t.text :metadata
|
12
|
+
t.string :service_name, null: false
|
13
|
+
t.bigint :byte_size, null: false
|
14
|
+
t.string :checksum
|
15
|
+
|
16
|
+
if connection.supports_datetime_with_precision?
|
17
|
+
t.datetime :created_at, precision: 6, null: false
|
18
|
+
else
|
19
|
+
t.datetime :created_at, null: false
|
20
|
+
end
|
21
|
+
|
22
|
+
t.index [:key], unique: true
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :active_storage_attachments, id: primary_key_type do |t|
|
26
|
+
t.string :name, null: false
|
27
|
+
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
|
28
|
+
t.references :blob, null: false, type: foreign_key_type
|
29
|
+
|
30
|
+
if connection.supports_datetime_with_precision?
|
31
|
+
t.datetime :created_at, precision: 6, null: false
|
32
|
+
else
|
33
|
+
t.datetime :created_at, null: false
|
34
|
+
end
|
35
|
+
|
36
|
+
t.index [:record_type, :record_id, :name, :blob_id], name: :index_active_storage_attachments_uniqueness, unique: true
|
37
|
+
t.foreign_key :active_storage_blobs, column: :blob_id
|
38
|
+
end
|
39
|
+
|
40
|
+
create_table :active_storage_variant_records, id: primary_key_type do |t|
|
41
|
+
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
|
42
|
+
t.string :variation_digest, null: false
|
43
|
+
|
44
|
+
t.index [:blob_id, :variation_digest], name: :index_active_storage_variant_records_uniqueness, unique: true
|
45
|
+
t.foreign_key :active_storage_blobs, column: :blob_id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def primary_and_foreign_key_types
|
52
|
+
config = Rails.configuration.generators
|
53
|
+
setting = config.options[config.orm][:primary_key_type]
|
54
|
+
primary_key_type = setting || :primary_key
|
55
|
+
foreign_key_type = setting || :bigint
|
56
|
+
[primary_key_type, foreign_key_type]
|
57
|
+
end
|
58
|
+
end
|
data/db/seeds.rb
ADDED