panda-cms 0.8.0 → 0.10.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/README.md +83 -4
- data/app/components/panda/cms/code_component.rb +117 -39
- data/app/components/panda/cms/grid_component.rb +26 -6
- data/app/components/panda/cms/menu_component.rb +66 -34
- data/app/components/panda/cms/page_menu_component.rb +94 -13
- data/app/components/panda/cms/rich_text_component.rb +198 -140
- data/app/components/panda/cms/text_component.rb +77 -44
- data/app/controllers/panda/cms/admin/base_controller.rb +19 -3
- data/app/controllers/panda/cms/admin/dashboard_controller.rb +3 -3
- data/app/controllers/panda/cms/admin/files_controller.rb +7 -0
- data/app/controllers/panda/cms/admin/menus_controller.rb +47 -3
- data/app/controllers/panda/cms/admin/pages_controller.rb +6 -1
- data/app/controllers/panda/cms/pages_controller.rb +2 -2
- data/app/helpers/panda/cms/application_helper.rb +15 -1
- data/app/helpers/panda/cms/asset_helper.rb +14 -3
- data/app/javascript/panda/cms/application_panda_cms.js +1 -1
- data/app/javascript/panda/cms/controllers/code_editor_controller.js +95 -0
- data/app/javascript/panda/cms/controllers/file_gallery_controller.js +128 -0
- data/app/javascript/panda/cms/controllers/index.js +48 -13
- data/app/javascript/panda/cms/controllers/inline_code_editor_controller.js +96 -0
- data/app/javascript/panda/cms/controllers/menu_form_controller.js +40 -0
- data/app/javascript/panda/cms/controllers/nested_form_controller.js +35 -0
- data/app/javascript/panda/cms/controllers/tree_controller.js +214 -0
- data/app/javascript/panda/cms/stimulus-loading.js +5 -7
- data/app/models/panda/cms/block_content.rb +9 -0
- data/app/models/panda/cms/page.rb +41 -0
- data/app/models/panda/cms/post.rb +1 -0
- data/app/views/panda/cms/admin/dashboard/show.html.erb +5 -5
- data/app/views/panda/cms/admin/files/_file_details.html.erb +45 -0
- data/app/views/panda/cms/admin/files/index.html.erb +11 -118
- data/app/views/panda/cms/admin/forms/index.html.erb +2 -2
- data/app/views/panda/cms/admin/forms/new.html.erb +1 -2
- data/app/views/panda/cms/admin/forms/show.html.erb +15 -30
- data/app/views/panda/cms/admin/menus/_menu_item_fields.html.erb +11 -0
- data/app/views/panda/cms/admin/menus/edit.html.erb +64 -0
- data/app/views/panda/cms/admin/menus/index.html.erb +3 -2
- data/app/views/panda/cms/admin/menus/new.html.erb +40 -0
- data/app/views/panda/cms/admin/pages/edit.html.erb +15 -9
- data/app/views/panda/cms/admin/pages/index.html.erb +49 -11
- data/app/views/panda/cms/admin/pages/new.html.erb +3 -11
- data/app/views/panda/cms/admin/posts/_form.html.erb +4 -14
- data/app/views/panda/cms/admin/posts/edit.html.erb +2 -2
- data/app/views/panda/cms/admin/posts/index.html.erb +3 -3
- 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/config/importmap.rb +4 -6
- data/config/initializers/panda/cms/healthcheck_log_silencer.rb.disabled +31 -0
- data/config/initializers/panda/cms.rb +52 -10
- data/config/routes.rb +4 -2
- data/db/migrate/20240305000000_convert_html_content_to_editor_js.rb +9 -2
- data/db/migrate/20240315125421_add_nested_sets_to_panda_cms_pages.rb +6 -1
- data/db/migrate/20250809231125_migrate_users_to_panda_core.rb +23 -21
- data/db/migrate/20251104150640_add_cached_last_updated_at_to_panda_cms_pages.rb +22 -0
- data/db/migrate/20251104172242_add_page_type_to_panda_cms_pages.rb +6 -0
- data/db/migrate/20251104172638_set_page_types_for_existing_pages.rb +27 -0
- data/db/migrate/20251105000001_add_pending_review_status_to_pages_and_posts.panda_cms.rb +21 -0
- data/lib/generators/panda/cms/install_generator.rb +2 -5
- data/lib/panda/cms/asset_loader.rb +36 -16
- data/lib/panda/cms/debug.rb +29 -0
- data/lib/panda/cms/engine.rb +107 -48
- data/lib/panda/cms/features.rb +52 -0
- data/lib/panda-cms/version.rb +1 -1
- data/lib/panda-cms.rb +5 -6
- data/lib/tasks/assets.rake +5 -52
- data/lib/tasks/panda_cms_tasks.rake +16 -0
- metadata +22 -29
- data/app/components/panda/cms/admin/container_component.html.erb +0 -13
- data/app/components/panda/cms/admin/flash_message_component.html.erb +0 -31
- data/app/components/panda/cms/admin/panel_component.html.erb +0 -7
- data/app/components/panda/cms/admin/slideover_component.html.erb +0 -9
- data/app/components/panda/cms/admin/slideover_component.rb +0 -15
- data/app/components/panda/cms/admin/statistics_component.html.erb +0 -4
- data/app/components/panda/cms/admin/statistics_component.rb +0 -16
- data/app/components/panda/cms/admin/tab_bar_component.html.erb +0 -35
- data/app/components/panda/cms/admin/tab_bar_component.rb +0 -15
- data/app/components/panda/cms/admin/table_component.html.erb +0 -29
- data/app/components/panda/cms/admin/user_activity_component.html.erb +0 -7
- data/app/components/panda/cms/admin/user_activity_component.rb +0 -20
- data/app/components/panda/cms/admin/user_display_component.html.erb +0 -17
- data/app/components/panda/cms/admin/user_display_component.rb +0 -21
- data/app/components/panda/cms/grid_component.html.erb +0 -6
- data/app/components/panda/cms/menu_component.html.erb +0 -6
- data/app/components/panda/cms/page_menu_component.html.erb +0 -21
- data/app/components/panda/cms/rich_text_component.html.erb +0 -90
- data/app/views/layouts/panda/cms/application.html.erb +0 -42
- data/app/views/panda/cms/admin/shared/_breadcrumbs.html.erb +0 -28
- data/app/views/panda/cms/admin/shared/_flash.html.erb +0 -5
- data/app/views/panda/cms/admin/shared/_sidebar.html.erb +0 -41
- data/app/views/panda/cms/shared/_footer.html.erb +0 -2
- data/app/views/panda/cms/shared/_header.html.erb +0 -25
- data/config/initializers/panda/cms/healthcheck_log_silencer.rb +0 -13
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: panda-cms
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
- Otaina Limited
|
|
7
|
+
- Otaina Limited
|
|
8
8
|
- James Inman
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
@@ -263,7 +263,7 @@ dependencies:
|
|
|
263
263
|
- !ruby/object:Gem::Version
|
|
264
264
|
version: '0'
|
|
265
265
|
email:
|
|
266
|
-
-
|
|
266
|
+
- james@otaina.co.uk
|
|
267
267
|
executables: []
|
|
268
268
|
extensions: []
|
|
269
269
|
extra_rdoc_files: []
|
|
@@ -276,28 +276,10 @@ files:
|
|
|
276
276
|
- app/assets/stylesheets/panda/cms/editor.css
|
|
277
277
|
- app/assets/tailwind/application.css
|
|
278
278
|
- app/assets/tailwind/tailwind.config.js
|
|
279
|
-
- app/components/panda/cms/admin/container_component.html.erb
|
|
280
|
-
- app/components/panda/cms/admin/flash_message_component.html.erb
|
|
281
|
-
- app/components/panda/cms/admin/panel_component.html.erb
|
|
282
|
-
- app/components/panda/cms/admin/slideover_component.html.erb
|
|
283
|
-
- app/components/panda/cms/admin/slideover_component.rb
|
|
284
|
-
- app/components/panda/cms/admin/statistics_component.html.erb
|
|
285
|
-
- app/components/panda/cms/admin/statistics_component.rb
|
|
286
|
-
- app/components/panda/cms/admin/tab_bar_component.html.erb
|
|
287
|
-
- app/components/panda/cms/admin/tab_bar_component.rb
|
|
288
|
-
- app/components/panda/cms/admin/table_component.html.erb
|
|
289
|
-
- app/components/panda/cms/admin/user_activity_component.html.erb
|
|
290
|
-
- app/components/panda/cms/admin/user_activity_component.rb
|
|
291
|
-
- app/components/panda/cms/admin/user_display_component.html.erb
|
|
292
|
-
- app/components/panda/cms/admin/user_display_component.rb
|
|
293
279
|
- app/components/panda/cms/code_component.rb
|
|
294
|
-
- app/components/panda/cms/grid_component.html.erb
|
|
295
280
|
- app/components/panda/cms/grid_component.rb
|
|
296
|
-
- app/components/panda/cms/menu_component.html.erb
|
|
297
281
|
- app/components/panda/cms/menu_component.rb
|
|
298
|
-
- app/components/panda/cms/page_menu_component.html.erb
|
|
299
282
|
- app/components/panda/cms/page_menu_component.rb
|
|
300
|
-
- app/components/panda/cms/rich_text_component.html.erb
|
|
301
283
|
- app/components/panda/cms/rich_text_component.rb
|
|
302
284
|
- app/components/panda/cms/text_component.rb
|
|
303
285
|
- app/controllers/panda/cms/admin/base_controller.rb
|
|
@@ -328,11 +310,17 @@ files:
|
|
|
328
310
|
- app/javascript/panda/cms/@hotwired--turbo.js
|
|
329
311
|
- app/javascript/panda/cms/@rails--actioncable--src.js
|
|
330
312
|
- app/javascript/panda/cms/application_panda_cms.js
|
|
313
|
+
- app/javascript/panda/cms/controllers/code_editor_controller.js
|
|
331
314
|
- app/javascript/panda/cms/controllers/dashboard_controller.js
|
|
332
315
|
- app/javascript/panda/cms/controllers/editor_form_controller.js
|
|
333
316
|
- app/javascript/panda/cms/controllers/editor_iframe_controller.js
|
|
317
|
+
- app/javascript/panda/cms/controllers/file_gallery_controller.js
|
|
334
318
|
- app/javascript/panda/cms/controllers/index.js
|
|
319
|
+
- app/javascript/panda/cms/controllers/inline_code_editor_controller.js
|
|
320
|
+
- app/javascript/panda/cms/controllers/menu_form_controller.js
|
|
321
|
+
- app/javascript/panda/cms/controllers/nested_form_controller.js
|
|
335
322
|
- app/javascript/panda/cms/controllers/slug_controller.js
|
|
323
|
+
- app/javascript/panda/cms/controllers/tree_controller.js
|
|
336
324
|
- app/javascript/panda/cms/stimulus-loading.js
|
|
337
325
|
- app/javascript/panda/cms/tailwindcss-stimulus-components.js
|
|
338
326
|
- app/javascript/panda_cms/stimulus-loading.js
|
|
@@ -360,16 +348,19 @@ files:
|
|
|
360
348
|
- app/views/layouts/different_page.html.erb
|
|
361
349
|
- app/views/layouts/homepage.html.erb
|
|
362
350
|
- app/views/layouts/page.html.erb
|
|
363
|
-
- app/views/layouts/panda/cms/application.html.erb
|
|
364
351
|
- app/views/layouts/panda/cms/public.html.erb
|
|
365
352
|
- app/views/panda/cms/admin/dashboard/show.html.erb
|
|
353
|
+
- app/views/panda/cms/admin/files/_file_details.html.erb
|
|
366
354
|
- app/views/panda/cms/admin/files/index.html.erb
|
|
367
355
|
- app/views/panda/cms/admin/files/show.html.erb
|
|
368
356
|
- app/views/panda/cms/admin/forms/edit.html.erb
|
|
369
357
|
- app/views/panda/cms/admin/forms/index.html.erb
|
|
370
358
|
- app/views/panda/cms/admin/forms/new.html.erb
|
|
371
359
|
- app/views/panda/cms/admin/forms/show.html.erb
|
|
360
|
+
- app/views/panda/cms/admin/menus/_menu_item_fields.html.erb
|
|
361
|
+
- app/views/panda/cms/admin/menus/edit.html.erb
|
|
372
362
|
- app/views/panda/cms/admin/menus/index.html.erb
|
|
363
|
+
- app/views/panda/cms/admin/menus/new.html.erb
|
|
373
364
|
- app/views/panda/cms/admin/pages/edit.html.erb
|
|
374
365
|
- app/views/panda/cms/admin/pages/index.html.erb
|
|
375
366
|
- app/views/panda/cms/admin/pages/new.html.erb
|
|
@@ -381,14 +372,9 @@ files:
|
|
|
381
372
|
- app/views/panda/cms/admin/settings/bulk_editor/new.html.erb
|
|
382
373
|
- app/views/panda/cms/admin/settings/index.html.erb
|
|
383
374
|
- app/views/panda/cms/admin/settings/insta.html
|
|
384
|
-
- app/views/panda/cms/admin/shared/_breadcrumbs.html.erb
|
|
385
|
-
- app/views/panda/cms/admin/shared/_flash.html.erb
|
|
386
|
-
- app/views/panda/cms/admin/shared/_sidebar.html.erb
|
|
387
375
|
- app/views/panda/cms/form_mailer/notification_email.html.erb
|
|
388
376
|
- app/views/panda/cms/shared/_editor.html.erb
|
|
389
377
|
- app/views/panda/cms/shared/_favicons.html.erb
|
|
390
|
-
- app/views/panda/cms/shared/_footer.html.erb
|
|
391
|
-
- app/views/panda/cms/shared/_header.html.erb
|
|
392
378
|
- app/views/panda/cms/shared/_importmap.html.erb
|
|
393
379
|
- app/views/shared/_footer.html.erb
|
|
394
380
|
- app/views/shared/_header.html.erb
|
|
@@ -396,7 +382,7 @@ files:
|
|
|
396
382
|
- config/initializers/inflections.rb
|
|
397
383
|
- config/initializers/panda/cms.rb
|
|
398
384
|
- config/initializers/panda/cms/form_errors.rb
|
|
399
|
-
- config/initializers/panda/cms/healthcheck_log_silencer.rb
|
|
385
|
+
- config/initializers/panda/cms/healthcheck_log_silencer.rb.disabled
|
|
400
386
|
- config/initializers/zeitwork.rb
|
|
401
387
|
- config/locales/en.yml
|
|
402
388
|
- config/puma/test.rb
|
|
@@ -447,6 +433,10 @@ files:
|
|
|
447
433
|
- db/migrate/20250126234001_create_panda_social_instagram_posts.rb
|
|
448
434
|
- db/migrate/20250809231125_migrate_users_to_panda_core.rb
|
|
449
435
|
- db/migrate/20250811111000_make_post_user_references_nullable.rb
|
|
436
|
+
- db/migrate/20251104150640_add_cached_last_updated_at_to_panda_cms_pages.rb
|
|
437
|
+
- db/migrate/20251104172242_add_page_type_to_panda_cms_pages.rb
|
|
438
|
+
- db/migrate/20251104172638_set_page_types_for_existing_pages.rb
|
|
439
|
+
- db/migrate/20251105000001_add_pending_review_status_to_pages_and_posts.panda_cms.rb
|
|
450
440
|
- db/migrate/migrate
|
|
451
441
|
- db/seeds.rb
|
|
452
442
|
- lib/generators/panda/cms/install_generator.rb
|
|
@@ -455,9 +445,11 @@ files:
|
|
|
455
445
|
- lib/panda/cms.rb
|
|
456
446
|
- lib/panda/cms/asset_loader.rb
|
|
457
447
|
- lib/panda/cms/bulk_editor.rb
|
|
448
|
+
- lib/panda/cms/debug.rb
|
|
458
449
|
- lib/panda/cms/demo_site_generator.rb
|
|
459
450
|
- lib/panda/cms/engine.rb
|
|
460
451
|
- lib/panda/cms/exceptions_app.rb
|
|
452
|
+
- lib/panda/cms/features.rb
|
|
461
453
|
- lib/panda/cms/railtie.rb
|
|
462
454
|
- lib/panda/cms/slug.rb
|
|
463
455
|
- lib/tasks/assets.rake
|
|
@@ -465,6 +457,7 @@ files:
|
|
|
465
457
|
- lib/tasks/panda/cms/migrations.rake
|
|
466
458
|
- lib/tasks/panda/social/instagram.rake
|
|
467
459
|
- lib/tasks/panda_cms.rake
|
|
460
|
+
- lib/tasks/panda_cms_tasks.rake
|
|
468
461
|
- lib/templates/erb/scaffold/_form.html.erb.tt
|
|
469
462
|
- lib/templates/erb/scaffold/edit.html.erb.tt
|
|
470
463
|
- lib/templates/erb/scaffold/index.html.erb.tt
|
|
@@ -519,7 +512,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
519
512
|
- !ruby/object:Gem::Version
|
|
520
513
|
version: '0'
|
|
521
514
|
requirements: []
|
|
522
|
-
rubygems_version: 3.
|
|
515
|
+
rubygems_version: 3.7.2
|
|
523
516
|
specification_version: 4
|
|
524
517
|
summary: Better websites on Rails.
|
|
525
518
|
test_files: []
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<main class="overflow-auto flex-1 h-full min-h-full max-h-full">
|
|
2
|
-
<div class="overflow-auto px-2 pt-4 mx-auto sm:px-6 lg:px-6">
|
|
3
|
-
<%= heading %>
|
|
4
|
-
<%= tab_bar %>
|
|
5
|
-
<%# I mean, you can edit this CSS if you want, but I hope you want to lose 2 hours to iFrame joy? %>
|
|
6
|
-
<section class="flex-auto h-[calc(100vh-10rem)]">
|
|
7
|
-
<div class="flex-1 mt-4 w-full h-full">
|
|
8
|
-
<%= content %>
|
|
9
|
-
</div>
|
|
10
|
-
<%= slideover %>
|
|
11
|
-
</section>
|
|
12
|
-
</div>
|
|
13
|
-
</main>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<div class="fixed top-2 right-2 z-[9999] p-2 space-y-4 w-full max-w-sm sm:items-end"
|
|
2
|
-
data-controller="alert"
|
|
3
|
-
<% if @temporary %> data-alert-dismiss-after-value="3000"<% end %>
|
|
4
|
-
data-transition-enter="ease-in-out duration-500"
|
|
5
|
-
data-transition-enter-from="translate-x-full opacity-0"
|
|
6
|
-
data-transition-enter-to="translate-x-0 opacity-100"
|
|
7
|
-
data-transition-leave="ease-in-out duration-500"
|
|
8
|
-
data-transition-leave-from="translate-x-0 opacity-100"
|
|
9
|
-
data-transition-leave-to="translate-x-full opacity-0">
|
|
10
|
-
<div class="overflow-hidden w-full max-w-sm bg-white rounded-lg ring-1 ring-black ring-opacity-5 shadow-lg">
|
|
11
|
-
<div class="p-4">
|
|
12
|
-
<div class="flex items-start">
|
|
13
|
-
<div class="flex-shrink-0">
|
|
14
|
-
<i class="fa-regular text-xl <%= icon_css %> <%= text_colour_css %>"></i>
|
|
15
|
-
</div>
|
|
16
|
-
<div class="flex-1 pt-0.5 ml-3 w-0">
|
|
17
|
-
<p class="mb-1 text-sm font-medium flash-message-title <%= text_colour_css %>"><%= kind.to_s.titleize %></p>
|
|
18
|
-
<p class="mt-1 mb-0 text-sm text-gray-500 flash-message-text"><%= message %></p>
|
|
19
|
-
</div>
|
|
20
|
-
<div class="flex flex-shrink-0 ml-4">
|
|
21
|
-
<button data-action="alert#close" type="button" class="inline-flex text-gray-400 bg-white rounded-md transition duration-150 ease-in-out hover:text-gray-500 focus:ring-2 focus:ring-offset-2 focus:outline-none focus:ring-sky-500">
|
|
22
|
-
<span class="sr-only">Close</span>
|
|
23
|
-
<svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
24
|
-
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
|
|
25
|
-
</svg>
|
|
26
|
-
</button>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Panda
|
|
4
|
-
module CMS
|
|
5
|
-
module Admin
|
|
6
|
-
class StatisticsComponent < ViewComponent::Base
|
|
7
|
-
attr_reader :metric, :value
|
|
8
|
-
|
|
9
|
-
def initialize(metric:, value:)
|
|
10
|
-
@metric = metric
|
|
11
|
-
@value = value
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<div class="mt-3 sm:mt-2">
|
|
2
|
-
<div class="sm:hidden">
|
|
3
|
-
<label for="tabs" class="sr-only">Select a tab</label>
|
|
4
|
-
<!-- Use an "onChange" listener to redirect the user to the selected tab URL. -->
|
|
5
|
-
<select id="tabs" name="tabs" class="block py-1.5 pr-10 pl-3 w-full text-gray-900 rounded-md border-0 ring-1 ring-inset focus:ring-2 focus:ring-inset ring-mid focus:border-panda-dark focus:ring-panda-dark">
|
|
6
|
-
<% tabs.each do |tab| %>
|
|
7
|
-
<option><%= tab %></option>
|
|
8
|
-
<% end %>
|
|
9
|
-
</select>
|
|
10
|
-
</div>
|
|
11
|
-
<div class="hidden sm:block">
|
|
12
|
-
<div class="flex items-center border-b border-gray-200">
|
|
13
|
-
<nav class="flex flex-1 -mb-px space-x-6 xl:space-x-8" aria-label="Tabs">
|
|
14
|
-
<!-- Current: "border-panda-dark text-panda-dark", Default: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700" -->
|
|
15
|
-
<a href="#" aria-current="page" class="py-4 px-1 text-sm font-medium whitespace-nowrap border-b-2 border-panda-dark text-panda-dark">Recently Viewed</a>
|
|
16
|
-
<a href="#" class="py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300">Recently Added</a>
|
|
17
|
-
<a href="#" class="py-4 px-1 text-sm font-medium text-gray-500 whitespace-nowrap border-b-2 border-transparent hover:text-gray-700 hover:border-gray-300">Favourited</a>
|
|
18
|
-
</nav>
|
|
19
|
-
<div class="hidden items-center p-0.5 ml-6 bg-gray-100 rounded-lg sm:flex">
|
|
20
|
-
<button type="button" class="p-1.5 text-gray-400 rounded-md hover:bg-white hover:shadow-sm focus:ring-2 focus:ring-inset focus:outline-none focus:ring-panda-dark">
|
|
21
|
-
<svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
22
|
-
<path fill-rule="evenodd" d="M2 3.75A.75.75 0 012.75 3h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 3.75zm0 4.167a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75a.75.75 0 01-.75-.75zm0 4.166a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75a.75.75 0 01-.75-.75zm0 4.167a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75a.75.75 0 01-.75-.75z" clip-rule="evenodd" />
|
|
23
|
-
</svg>
|
|
24
|
-
<span class="sr-only">Use list view</span>
|
|
25
|
-
</button>
|
|
26
|
-
<button type="button" class="p-1.5 ml-0.5 text-gray-400 bg-white rounded-md shadow-sm focus:ring-2 focus:ring-inset focus:outline-none focus:ring-panda-dark">
|
|
27
|
-
<svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
28
|
-
<path fill-rule="evenodd" d="M4.25 2A2.25 2.25 0 002 4.25v2.5A2.25 2.25 0 004.25 9h2.5A2.25 2.25 0 009 6.75v-2.5A2.25 2.25 0 006.75 2h-2.5zm0 9A2.25 2.25 0 002 13.25v2.5A2.25 2.25 0 004.25 18h2.5A2.25 2.25 0 009 15.75v-2.5A2.25 2.25 0 006.75 11h-2.5zm9-9A2.25 2.25 0 0011 4.25v2.5A2.25 2.25 0 0013.25 9h2.5A2.25 2.25 0 0018 6.75v-2.5A2.25 2.25 0 0015.75 2h-2.5zm0 9A2.25 2.25 0 0011 13.25v2.5A2.25 2.25 0 0013.25 18h2.5A2.25 2.25 0 0018 15.75v-2.5A2.25 2.25 0 0015.75 11h-2.5z" clip-rule="evenodd" />
|
|
29
|
-
</svg>
|
|
30
|
-
<span class="sr-only">Use grid view</span>
|
|
31
|
-
</button>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<div class="table overflow-x-auto mb-12 w-full rounded-lg border border-mid">
|
|
2
|
-
<div class="table-header-group">
|
|
3
|
-
<div class="table-row text-base font-medium text-white bg-mid">
|
|
4
|
-
<% columns.each_with_index do |column, i| %>
|
|
5
|
-
<div class="table-cell sticky top-0 z-10 p-4 <% if i.zero? %>rounded-tl-md<% elsif i == columns.size - 1 %>rounded-tr-md<% end %>"><%= column.label %></div>
|
|
6
|
-
<% end %>
|
|
7
|
-
</div>
|
|
8
|
-
</div>
|
|
9
|
-
|
|
10
|
-
<% if @rows.any? %>
|
|
11
|
-
<div class="table-row-group">
|
|
12
|
-
<% @rows.each do |row| %>
|
|
13
|
-
<div class="table-row relative bg-mid/5 hover:bg-mid/20" data-post-id="<%= row.id %>">
|
|
14
|
-
<% @columns.each do |column| %>
|
|
15
|
-
<div class="table-cell py-5 px-3 h-20 text-sm align-middle whitespace-nowrap border-b border-mid/20">
|
|
16
|
-
<%= view_context.capture(row, &column.cell) %>
|
|
17
|
-
</div>
|
|
18
|
-
<% end %>
|
|
19
|
-
</div>
|
|
20
|
-
<% end %>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
<% else %>
|
|
24
|
-
</div>
|
|
25
|
-
<div class="text-center mx-12 block border border-dashed py-12 rounded-lg">
|
|
26
|
-
<h3 class="py-1 text-xl font-semibold text-gray-900">No <%= @term.pluralize %></h3>
|
|
27
|
-
<p class="py-1 text-base text-gray-500">Get started by creating a new <%= @term %>.</p>
|
|
28
|
-
</div>
|
|
29
|
-
<% end %>
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<% if user.is_a?(Panda::Core::User) && time %>
|
|
2
|
-
<%= render Panda::CMS::Admin::UserDisplayComponent.new(user: user, metadata: "#{time_ago_in_words(time)} ago") %>
|
|
3
|
-
<% elsif user.is_a?(Panda::Core::User) %>
|
|
4
|
-
<%= render Panda::CMS::Admin::UserDisplayComponent.new(user: user, metadata: "Not published") %>
|
|
5
|
-
<% elsif time %>
|
|
6
|
-
<div class="text-black/60"><%= time_ago_in_words(time) %> ago</div>
|
|
7
|
-
<% end %>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Panda
|
|
4
|
-
module CMS
|
|
5
|
-
module Admin
|
|
6
|
-
class UserActivityComponent < ViewComponent::Base
|
|
7
|
-
attr_accessor :model, :time, :user
|
|
8
|
-
|
|
9
|
-
# @param model [ActiveRecord::Base] Model instance to which the user activity is related
|
|
10
|
-
# @param at [ActiveSupport::TimeWithZone] Time of the activity
|
|
11
|
-
# @param user [Panda::Core::User] User who performed the activity
|
|
12
|
-
def initialize(model: nil, at: nil, user: nil)
|
|
13
|
-
@model = model
|
|
14
|
-
@user = user if user.is_a?(::Panda::Core::User)
|
|
15
|
-
@time = at if at.is_a?(::ActiveSupport::TimeWithZone)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<div class="block flex-shrink-0 group">
|
|
2
|
-
<div class="flex items-center">
|
|
3
|
-
<% unless user.image_url.empty? %>
|
|
4
|
-
<div>
|
|
5
|
-
<img class="inline-block w-10 h-10 rounded-full" src="<%= user.image_url %>" alt="">
|
|
6
|
-
</div>
|
|
7
|
-
<% else %>
|
|
8
|
-
<div class="inline-block w-10 h-10 bg-gray-200 rounded-full">
|
|
9
|
-
<span class="text-center"><i class="text-mid/50 text-4xl fa-sharp fa-circle-user fa-fw"></i></span>
|
|
10
|
-
</div>
|
|
11
|
-
<% end %>
|
|
12
|
-
<div class="ml-3">
|
|
13
|
-
<p class="text-sm text-black"><%= user.name %></p>
|
|
14
|
-
<% if metadata %><p class="text-sm text-black/60"><%= metadata %></p><% end %>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Panda
|
|
4
|
-
module CMS
|
|
5
|
-
module Admin
|
|
6
|
-
class UserDisplayComponent < ViewComponent::Base
|
|
7
|
-
attr_accessor :user_id, :user, :metadata
|
|
8
|
-
|
|
9
|
-
def initialize(user_id: nil, user: nil, metadata: "")
|
|
10
|
-
@user = if user.nil? && user_id.present? && Panda::Core::User.find(user_id)
|
|
11
|
-
Panda::Core::User.find(user_id)
|
|
12
|
-
else
|
|
13
|
-
user
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
@metadata = metadata
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<% @menu_items.each do |menu_item| %>
|
|
2
|
-
<a href="<%= menu_item.resolved_link %>" class="<%= menu_item.css_classes %>"><%= menu_item.text %></a>
|
|
3
|
-
<% if @render_page_menu && menu_item.page %>
|
|
4
|
-
<%= render Panda::CMS::PageMenuComponent.new(page: menu_item.page, start_depth: 1, styles: @page_menu_styles, show_heading: false) %>
|
|
5
|
-
<% end %>
|
|
6
|
-
<% end %>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<nav class="<%= styles[:container] %>">
|
|
2
|
-
<ul role="list" class="p-0 m-0">
|
|
3
|
-
<% if @show_heading %>
|
|
4
|
-
<li>
|
|
5
|
-
<a href="<%= menu_item.page.path %>" class="<%= menu_item.page == Panda::CMS::Current.page ? styles[:current_page_active] : styles[:current_page_inactive] %>">
|
|
6
|
-
<%= menu_item.text %>
|
|
7
|
-
</a>
|
|
8
|
-
</li>
|
|
9
|
-
<% end %>
|
|
10
|
-
<ul>
|
|
11
|
-
<% Panda::CMS::MenuItem.includes(:page).each_with_level(menu_item.descendants) do |submenu_item, level| %>
|
|
12
|
-
<% next if Panda::CMS::Current.page == menu_item.page && level > 1 # If we're on the "top" menu item, only show its direct ancestors %>
|
|
13
|
-
<% next if submenu_item.page&.path[/\:/] %>
|
|
14
|
-
<% next if submenu_item&.page.nil? || Panda::CMS::Current.page.nil? || (submenu_item.page&.depth&.to_i > Panda::CMS::Current.page&.depth&.to_i && !Panda::CMS::Current.page&.in?(submenu_item.page.ancestors)) %>
|
|
15
|
-
<li data-level="<%= level %>" data-page-id="<%= submenu_item.page.id %>" class="<%= submenu_item.page == Panda::CMS::Current.page ? @styles[:active] : @styles[:inactive] %>">
|
|
16
|
-
<a href="<%= submenu_item.page&.path %>" class="<%= helpers.menu_indent(submenu_item, indent_with: @styles[:indent_with]) %>"><%= submenu_item.page&.title %></a>
|
|
17
|
-
</li>
|
|
18
|
-
<% end %>
|
|
19
|
-
</ul>
|
|
20
|
-
</ul>
|
|
21
|
-
</nav>
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
<%
|
|
2
|
-
editor_data = if @editable
|
|
3
|
-
begin
|
|
4
|
-
content = if @content.is_a?(String)
|
|
5
|
-
if @content.start_with?("{")
|
|
6
|
-
JSON.parse(@content)
|
|
7
|
-
else
|
|
8
|
-
# If it's HTML content, convert it to EditorJS format
|
|
9
|
-
{
|
|
10
|
-
"time" => Time.current.to_i * 1000,
|
|
11
|
-
"blocks" => [
|
|
12
|
-
{
|
|
13
|
-
"type" => "paragraph",
|
|
14
|
-
"data" => {
|
|
15
|
-
"text" => @content.to_s
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
"version" => "2.28.2"
|
|
20
|
-
}
|
|
21
|
-
end
|
|
22
|
-
else
|
|
23
|
-
@content
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
content = content.deep_transform_keys(&:to_s)
|
|
27
|
-
content["blocks"] = (content["blocks"] || []).map do |block|
|
|
28
|
-
case block["type"]
|
|
29
|
-
when "paragraph"
|
|
30
|
-
block["data"] = block["data"].merge(
|
|
31
|
-
"text" => block["data"]["text"].to_s.presence || ""
|
|
32
|
-
)
|
|
33
|
-
when "header"
|
|
34
|
-
block["data"] = block["data"].merge(
|
|
35
|
-
"text" => block["data"]["text"].to_s.presence || "",
|
|
36
|
-
"level" => block["data"]["level"].to_i
|
|
37
|
-
)
|
|
38
|
-
when "list"
|
|
39
|
-
block["data"] = block["data"].merge(
|
|
40
|
-
"items" => (block["data"]["items"] || []).map { |item| item.to_s.presence || "" }
|
|
41
|
-
)
|
|
42
|
-
end
|
|
43
|
-
block
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
content["version"] ||= "2.28.2"
|
|
47
|
-
content["time"] ||= Time.current.to_i * 1000
|
|
48
|
-
|
|
49
|
-
Base64.strict_encode64(content.to_json)
|
|
50
|
-
rescue StandardError => e
|
|
51
|
-
Rails.logger.error("Error encoding editor data: #{e.message}")
|
|
52
|
-
Rails.logger.error("Original content: #{@content.inspect}")
|
|
53
|
-
# Fall back to a simple paragraph with the original content
|
|
54
|
-
fallback_content = {
|
|
55
|
-
"time" => Time.current.to_i * 1000,
|
|
56
|
-
"blocks" => [
|
|
57
|
-
{
|
|
58
|
-
"type" => "paragraph",
|
|
59
|
-
"data" => {
|
|
60
|
-
"text" => @content.to_s
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
"version" => "2.28.2"
|
|
65
|
-
}
|
|
66
|
-
Base64.strict_encode64(fallback_content.to_json)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
%>
|
|
70
|
-
<% if @editable %>
|
|
71
|
-
<div class="panda-cms-content"
|
|
72
|
-
data-editable-previous-data="<%= editor_data %>"
|
|
73
|
-
data-editable-content="<%= editor_data %>"
|
|
74
|
-
data-editable-initialized="false"
|
|
75
|
-
data-editable-version="2.28.2"
|
|
76
|
-
data-editable-autosave="false"
|
|
77
|
-
data-editable-tools='{"paragraph":true,"header":true,"list":true,"quote":true,"table":true}'
|
|
78
|
-
id="editor-<%= @options[:id] %>"
|
|
79
|
-
data-editable-kind="rich_text"
|
|
80
|
-
data-editable-block-content-id="<%= @options[:id] %>"
|
|
81
|
-
data-editable-page-id="<%= @options[:data][:page_id] %>"
|
|
82
|
-
data-controller="editor-js"
|
|
83
|
-
data-editor-js-initialized-value="false"
|
|
84
|
-
data-editor-js-content-value="<%= editor_data %>">
|
|
85
|
-
</div>
|
|
86
|
-
<% else %>
|
|
87
|
-
<div class="panda-cms-content">
|
|
88
|
-
<%= @content.presence || "<p></p>".html_safe %>
|
|
89
|
-
</div>
|
|
90
|
-
<% end %>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<%= render "panda/cms/shared/header", html_class: "h-full bg-white" %>
|
|
2
|
-
<div class="flex h-full" id="panda-container">
|
|
3
|
-
<div class="absolute top-0 w-full lg:flex lg:fixed lg:inset-y-0 lg:z-50 lg:flex-col lg:w-72">
|
|
4
|
-
<div class="flex overflow-y-auto flex-col gap-y-5 px-4 pb-4 max-h-16 bg-gradient-to-br lg:max-h-full grow from-dark to-mid" data-transition-enter="transition-all ease-in-out duration-300" data-transition-enter-from="m-h-16" data-transition-enter-to="max-h-full" data-transition-leave="transition-all ease-in-out duration-300" data-transition-leave-from="max-h-full" data-transition-leave-to="max-h-16">
|
|
5
|
-
<%= render "panda/cms/admin/shared/sidebar" %>
|
|
6
|
-
</div>
|
|
7
|
-
</div>
|
|
8
|
-
<div class="flex flex-col flex-1 mt-16 ml-0 lg:mt-0 lg:ml-72" id="panda-inner-container" <% if content_for :sidebar %> data-controller="toggle" data-action="keydown.esc->modal#close" tabindex="-1"<% end %>>
|
|
9
|
-
<section id="panda-main" class="flex flex-row h-full">
|
|
10
|
-
<div class="flex-1 h-full" id="panda-cms-primary-content">
|
|
11
|
-
<%= render "panda/cms/admin/shared/breadcrumbs" %>
|
|
12
|
-
<%= render "panda/cms/admin/shared/flash" %>
|
|
13
|
-
<%= yield %>
|
|
14
|
-
</div>
|
|
15
|
-
<% if content_for :sidebar %>
|
|
16
|
-
<div data-toggle-target="toggleable" class="hidden flex absolute right-0 flex-col h-full bg-white divide-y divide-gray-200 shadow-xl basis-3/12"
|
|
17
|
-
data-transition-enter="transform transition ease-in-out duration-500"
|
|
18
|
-
data-transition-enter-from="translate-x-full"
|
|
19
|
-
data-transition-enter-to="translate-x-0"
|
|
20
|
-
data-transition-leave="transform transition ease-in-out duration-500"
|
|
21
|
-
data-transition-leave-from="translate-x-full"
|
|
22
|
-
data-transition-leave-to="translate-x-0"
|
|
23
|
-
id="slideover">
|
|
24
|
-
<div class="overflow-y-auto flex-1 h-0">
|
|
25
|
-
<div class="py-3 px-4 mb-4 bg-black">
|
|
26
|
-
<div class="flex justify-between items-center">
|
|
27
|
-
<h2 class="text-base font-semibold leading-6 text-white" id="slideover-title"><i class="mr-2 fa-light fa-gear"></i> <%= yield :sidebar_title %> </h2>
|
|
28
|
-
<button type="button" data-action="click->toggle#toggle touch->toggle#toggle"><i class="font-bold text-white fa-regular fa-xmark right"></i></button>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="flex flex-col flex-1 justify-between">
|
|
32
|
-
<div class="px-4 space-y-6">
|
|
33
|
-
<%= yield :sidebar %>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
<% end %>
|
|
39
|
-
</section>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
<%= render "panda/cms/shared/footer" %>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<% breadcrumb_styles = "text-black/60 hover:text-black/80" %>
|
|
2
|
-
|
|
3
|
-
<div class="flex mt-1 -mb-1">
|
|
4
|
-
<nav aria-label="Breadcrumb" id="panda-breadcrumbs" class="grow">
|
|
5
|
-
<ol role="list" class="px-4 w-full sm:px-6">
|
|
6
|
-
<li class="inline-block">
|
|
7
|
-
<a href="/admin" class="<%= breadcrumb_styles %>">
|
|
8
|
-
<i class="fa fa-regular fa-house"></i>
|
|
9
|
-
<span class="sr-only">Home</span>
|
|
10
|
-
</a>
|
|
11
|
-
</li>
|
|
12
|
-
<% breadcrumbs.each do |crumb| %>
|
|
13
|
-
<li class="inline-block">
|
|
14
|
-
<i class="fa fa-regular fa-chevron-right font-light <%= breadcrumb_styles %> py-5 px-2"></i>
|
|
15
|
-
<a href="<%= crumb.path %>" class="text-sm font-normal <%= breadcrumb_styles %>"><%= crumb.name %></a>
|
|
16
|
-
</li>
|
|
17
|
-
<% end %>
|
|
18
|
-
</ol>
|
|
19
|
-
</nav>
|
|
20
|
-
|
|
21
|
-
<% if content_for :sidebar %>
|
|
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
|
-
<i class="mr-1 fa-light fa-gear"></i> <%= yield :sidebar_title %>
|
|
25
|
-
</button>
|
|
26
|
-
</div>
|
|
27
|
-
<% end %>
|
|
28
|
-
</div>
|