not_pressed-core 0.1.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 +7 -0
- data/LICENSE.txt +41 -0
- data/README.md +285 -0
- data/app/assets/javascripts/not_pressed/lightbox.js +110 -0
- data/app/assets/stylesheets/not_pressed/admin.css +1161 -0
- data/app/assets/stylesheets/not_pressed/content.css +193 -0
- data/app/assets/stylesheets/not_pressed/gallery.css +117 -0
- data/app/assets/stylesheets/not_pressed/themes/starter.css +118 -0
- data/app/controllers/not_pressed/admin/base_controller.rb +21 -0
- data/app/controllers/not_pressed/admin/categories_controller.rb +53 -0
- data/app/controllers/not_pressed/admin/content_blocks_controller.rb +73 -0
- data/app/controllers/not_pressed/admin/dashboard_controller.rb +19 -0
- data/app/controllers/not_pressed/admin/forms_controller.rb +86 -0
- data/app/controllers/not_pressed/admin/media_attachments_controller.rb +94 -0
- data/app/controllers/not_pressed/admin/pages_controller.rb +122 -0
- data/app/controllers/not_pressed/admin/plugins_controller.rb +121 -0
- data/app/controllers/not_pressed/admin/settings_controller.rb +19 -0
- data/app/controllers/not_pressed/admin/tags_controller.rb +37 -0
- data/app/controllers/not_pressed/admin/themes_controller.rb +104 -0
- data/app/controllers/not_pressed/application_controller.rb +6 -0
- data/app/controllers/not_pressed/blog_controller.rb +83 -0
- data/app/controllers/not_pressed/form_submissions_controller.rb +70 -0
- data/app/controllers/not_pressed/pages_controller.rb +36 -0
- data/app/controllers/not_pressed/robots_controller.rb +34 -0
- data/app/controllers/not_pressed/sitemaps_controller.rb +12 -0
- data/app/helpers/not_pressed/admin_helper.rb +41 -0
- data/app/helpers/not_pressed/application_helper.rb +6 -0
- data/app/helpers/not_pressed/code_injection_helper.rb +29 -0
- data/app/helpers/not_pressed/content_helper.rb +13 -0
- data/app/helpers/not_pressed/form_helper.rb +80 -0
- data/app/helpers/not_pressed/media_helper.rb +28 -0
- data/app/helpers/not_pressed/seo_helper.rb +69 -0
- data/app/helpers/not_pressed/theme_helper.rb +42 -0
- data/app/mailers/not_pressed/application_mailer.rb +10 -0
- data/app/mailers/not_pressed/form_mailer.rb +15 -0
- data/app/models/concerns/not_pressed/sluggable.rb +43 -0
- data/app/models/not_pressed/category.rb +16 -0
- data/app/models/not_pressed/content_block.rb +46 -0
- data/app/models/not_pressed/form.rb +55 -0
- data/app/models/not_pressed/form_field.rb +23 -0
- data/app/models/not_pressed/form_submission.rb +19 -0
- data/app/models/not_pressed/media_attachment.rb +68 -0
- data/app/models/not_pressed/page.rb +182 -0
- data/app/models/not_pressed/page_version.rb +15 -0
- data/app/models/not_pressed/setting.rb +20 -0
- data/app/models/not_pressed/tag.rb +15 -0
- data/app/models/not_pressed/tagging.rb +12 -0
- data/app/plugins/not_pressed/analytics_plugin.rb +106 -0
- data/app/plugins/not_pressed/callout_block_plugin.rb +43 -0
- data/app/themes/not_pressed/starter_theme.rb +26 -0
- data/app/views/layouts/not_pressed/admin.html.erb +745 -0
- data/app/views/layouts/not_pressed/application.html.erb +12 -0
- data/app/views/layouts/not_pressed/page.html.erb +22 -0
- data/app/views/not_pressed/admin/categories/index.html.erb +58 -0
- data/app/views/not_pressed/admin/content_blocks/_block.html.erb +18 -0
- data/app/views/not_pressed/admin/content_blocks/_block_picker.html.erb +32 -0
- data/app/views/not_pressed/admin/content_blocks/create.turbo_stream.erb +3 -0
- data/app/views/not_pressed/admin/content_blocks/destroy.turbo_stream.erb +1 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_callout.html.erb +38 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_code.html.erb +26 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_divider.html.erb +4 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_form.html.erb +16 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_gallery.html.erb +75 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_heading.html.erb +26 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_html.html.erb +13 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_image.html.erb +56 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_quote.html.erb +24 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_text.html.erb +28 -0
- data/app/views/not_pressed/admin/content_blocks/editors/_video.html.erb +25 -0
- data/app/views/not_pressed/admin/dashboard/index.html.erb +60 -0
- data/app/views/not_pressed/admin/forms/_field_row.html.erb +33 -0
- data/app/views/not_pressed/admin/forms/_form.html.erb +75 -0
- data/app/views/not_pressed/admin/forms/edit.html.erb +1 -0
- data/app/views/not_pressed/admin/forms/index.html.erb +32 -0
- data/app/views/not_pressed/admin/forms/new.html.erb +1 -0
- data/app/views/not_pressed/admin/forms/submissions.html.erb +34 -0
- data/app/views/not_pressed/admin/media_attachments/_media_card.html.erb +21 -0
- data/app/views/not_pressed/admin/media_attachments/_picker.html.erb +19 -0
- data/app/views/not_pressed/admin/media_attachments/edit.html.erb +57 -0
- data/app/views/not_pressed/admin/media_attachments/index.html.erb +48 -0
- data/app/views/not_pressed/admin/pages/_form.html.erb +177 -0
- data/app/views/not_pressed/admin/pages/_page_tree_node.html.erb +32 -0
- data/app/views/not_pressed/admin/pages/edit.html.erb +69 -0
- data/app/views/not_pressed/admin/pages/index.html.erb +21 -0
- data/app/views/not_pressed/admin/pages/new.html.erb +1 -0
- data/app/views/not_pressed/admin/pages/preview.html.erb +17 -0
- data/app/views/not_pressed/admin/plugins/_settings_form.html.erb +59 -0
- data/app/views/not_pressed/admin/plugins/index.html.erb +48 -0
- data/app/views/not_pressed/admin/plugins/show.html.erb +54 -0
- data/app/views/not_pressed/admin/settings/code_injection.html.erb +21 -0
- data/app/views/not_pressed/admin/shared/_breadcrumbs.html.erb +14 -0
- data/app/views/not_pressed/admin/shared/_flash.html.erb +7 -0
- data/app/views/not_pressed/admin/shared/_modal.html.erb +9 -0
- data/app/views/not_pressed/admin/shared/_sidebar.html.erb +18 -0
- data/app/views/not_pressed/admin/tags/index.html.erb +52 -0
- data/app/views/not_pressed/admin/themes/index.html.erb +60 -0
- data/app/views/not_pressed/admin/themes/show.html.erb +66 -0
- data/app/views/not_pressed/blog/_post_card.html.erb +24 -0
- data/app/views/not_pressed/blog/feed.rss.builder +22 -0
- data/app/views/not_pressed/blog/index.html.erb +56 -0
- data/app/views/not_pressed/blog/show.html.erb +41 -0
- data/app/views/not_pressed/form_mailer/submission_notification.text.erb +8 -0
- data/app/views/not_pressed/pages/show.html.erb +4 -0
- data/app/views/themes/starter/layouts/not_pressed/default.html.erb +36 -0
- data/app/views/themes/starter/layouts/not_pressed/full_width.html.erb +36 -0
- data/app/views/themes/starter/layouts/not_pressed/sidebar.html.erb +41 -0
- data/config/routes.rb +81 -0
- data/db/migrate/20260310000001_create_not_pressed_pages.rb +20 -0
- data/db/migrate/20260310000002_create_not_pressed_content_blocks.rb +17 -0
- data/db/migrate/20260310000003_create_not_pressed_media_attachments.rb +14 -0
- data/db/migrate/20260310000004_add_content_type_to_not_pressed_pages.rb +8 -0
- data/db/migrate/20260310000005_add_publishing_fields_to_not_pressed_pages.rb +8 -0
- data/db/migrate/20260310000006_create_not_pressed_page_versions.rb +16 -0
- data/db/migrate/20260310000007_add_settings_fields_to_not_pressed_pages.rb +11 -0
- data/db/migrate/20260311000001_create_not_pressed_forms.rb +42 -0
- data/db/migrate/20260311000002_add_seo_fields_to_not_pressed_pages.rb +10 -0
- data/db/migrate/20260311000003_add_code_injection_to_not_pressed_pages.rb +8 -0
- data/db/migrate/20260311000004_create_not_pressed_settings.rb +14 -0
- data/db/migrate/20260312000001_create_not_pressed_categories.rb +16 -0
- data/db/migrate/20260312000002_create_not_pressed_tags.rb +15 -0
- data/db/migrate/20260312000003_create_not_pressed_taggings.rb +14 -0
- data/db/migrate/20260312000004_add_category_id_to_not_pressed_pages.rb +7 -0
- data/lib/generators/not_pressed/install/install_generator.rb +52 -0
- data/lib/generators/not_pressed/install/templates/initializer.rb.tt +89 -0
- data/lib/generators/not_pressed/install/templates/seeds.rb.tt +131 -0
- data/lib/generators/not_pressed/plugin/plugin_generator.rb +37 -0
- data/lib/generators/not_pressed/plugin/templates/plugin.rb.tt +23 -0
- data/lib/not_pressed/admin/authentication.rb +48 -0
- data/lib/not_pressed/admin/menu_registry.rb +100 -0
- data/lib/not_pressed/configuration.rb +77 -0
- data/lib/not_pressed/content_type.rb +23 -0
- data/lib/not_pressed/content_type_builder.rb +51 -0
- data/lib/not_pressed/content_type_registry.rb +45 -0
- data/lib/not_pressed/engine.rb +132 -0
- data/lib/not_pressed/hooks.rb +166 -0
- data/lib/not_pressed/navigation/builder.rb +148 -0
- data/lib/not_pressed/navigation/menu.rb +54 -0
- data/lib/not_pressed/navigation/menu_item.rb +33 -0
- data/lib/not_pressed/navigation/node.rb +45 -0
- data/lib/not_pressed/navigation/partial_parser.rb +96 -0
- data/lib/not_pressed/navigation/route_inspector.rb +98 -0
- data/lib/not_pressed/navigation.rb +6 -0
- data/lib/not_pressed/plugin.rb +354 -0
- data/lib/not_pressed/plugin_importer.rb +133 -0
- data/lib/not_pressed/plugin_manager.rb +196 -0
- data/lib/not_pressed/plugin_packager.rb +129 -0
- data/lib/not_pressed/rendering/block_renderer.rb +222 -0
- data/lib/not_pressed/rendering/renderer_registry.rb +154 -0
- data/lib/not_pressed/rendering.rb +8 -0
- data/lib/not_pressed/seo/sitemap_builder.rb +61 -0
- data/lib/not_pressed/theme.rb +191 -0
- data/lib/not_pressed/theme_importer.rb +133 -0
- data/lib/not_pressed/theme_packager.rb +180 -0
- data/lib/not_pressed/theme_registry.rb +123 -0
- data/lib/not_pressed/version.rb +5 -0
- data/lib/not_pressed.rb +65 -0
- metadata +258 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<%= form_with model: @form, url: @form.new_record? ? admin_forms_path : admin_form_path(@form), class: "np-form" do |f| %>
|
|
2
|
+
<% if @form.errors.any? %>
|
|
3
|
+
<div class="np-form-errors">
|
|
4
|
+
<h3><%= pluralize(@form.errors.count, "error") %> prevented this form from being saved:</h3>
|
|
5
|
+
<ul>
|
|
6
|
+
<% @form.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
</div>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<fieldset class="np-fieldset">
|
|
14
|
+
<legend class="np-legend">General</legend>
|
|
15
|
+
|
|
16
|
+
<div class="np-form-group">
|
|
17
|
+
<%= f.label :name, class: "np-label" %>
|
|
18
|
+
<%= f.text_field :name, class: "np-input" %>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="np-form-group">
|
|
22
|
+
<%= f.label :description, class: "np-label" %>
|
|
23
|
+
<%= f.text_area :description, class: "np-input", rows: 3 %>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="np-form-group">
|
|
27
|
+
<%= f.label :status, class: "np-label" %>
|
|
28
|
+
<%= f.select :status, NotPressed::Form.statuses.keys.map { |s| [s.humanize, s] }, {}, class: "np-input" %>
|
|
29
|
+
</div>
|
|
30
|
+
</fieldset>
|
|
31
|
+
|
|
32
|
+
<fieldset class="np-fieldset">
|
|
33
|
+
<legend class="np-legend">Settings</legend>
|
|
34
|
+
|
|
35
|
+
<div class="np-form-group">
|
|
36
|
+
<%= f.label :email_recipient, class: "np-label" %>
|
|
37
|
+
<%= f.email_field :email_recipient, class: "np-input", placeholder: "notifications@example.com" %>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="np-form-group">
|
|
41
|
+
<%= f.label :redirect_url, "Redirect URL", class: "np-label" %>
|
|
42
|
+
<%= f.text_field :redirect_url, class: "np-input", placeholder: "/thank-you" %>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="np-form-group">
|
|
46
|
+
<%= f.label :success_message, class: "np-label" %>
|
|
47
|
+
<%= f.text_area :success_message, class: "np-input", rows: 2, placeholder: "Thank you for your submission!" %>
|
|
48
|
+
</div>
|
|
49
|
+
</fieldset>
|
|
50
|
+
|
|
51
|
+
<fieldset class="np-fieldset" data-controller="np-form-fields">
|
|
52
|
+
<legend class="np-legend">Fields</legend>
|
|
53
|
+
|
|
54
|
+
<div class="np-field-list" data-np-form-fields-target="list">
|
|
55
|
+
<% @form.form_fields.ordered.each.with_index do |field, index| %>
|
|
56
|
+
<%= f.fields_for :form_fields, field, child_index: index do |ff| %>
|
|
57
|
+
<%= render "not_pressed/admin/forms/field_row", ff: ff, index: index %>
|
|
58
|
+
<% end %>
|
|
59
|
+
<% end %>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<template data-np-form-fields-target="template">
|
|
63
|
+
<%= f.fields_for :form_fields, NotPressed::FormField.new, child_index: "NEW_INDEX" do |ff| %>
|
|
64
|
+
<%= render "not_pressed/admin/forms/field_row", ff: ff, index: "NEW_INDEX" %>
|
|
65
|
+
<% end %>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<button type="button" class="np-btn" data-action="np-form-fields#addField" style="margin-top: 0.5rem;">+ Add Field</button>
|
|
69
|
+
</fieldset>
|
|
70
|
+
|
|
71
|
+
<div class="np-form-actions">
|
|
72
|
+
<%= f.submit @form.persisted? ? "Update Form" : "Create Form", class: "np-btn np-btn--primary" %>
|
|
73
|
+
<%= link_to "Cancel", admin_forms_path, class: "np-btn" %>
|
|
74
|
+
</div>
|
|
75
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render "form" %>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<div class="np-actions" style="margin-bottom: 1.5rem;">
|
|
2
|
+
<%= link_to "New Form", new_admin_form_path, class: "np-btn np-btn--primary" %>
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<% if @forms.any? %>
|
|
6
|
+
<table class="np-table">
|
|
7
|
+
<thead>
|
|
8
|
+
<tr>
|
|
9
|
+
<th>Name</th>
|
|
10
|
+
<th>Status</th>
|
|
11
|
+
<th>Submissions</th>
|
|
12
|
+
<th>Actions</th>
|
|
13
|
+
</tr>
|
|
14
|
+
</thead>
|
|
15
|
+
<tbody>
|
|
16
|
+
<% @forms.each do |form| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td><%= link_to form.name, edit_admin_form_path(form) %></td>
|
|
19
|
+
<td><%= status_badge(form.status) %></td>
|
|
20
|
+
<td><%= form.form_submissions.count %></td>
|
|
21
|
+
<td>
|
|
22
|
+
<%= link_to "Edit", edit_admin_form_path(form), class: "np-btn np-btn--small" %>
|
|
23
|
+
<%= link_to "Submissions", submissions_admin_form_path(form), class: "np-btn np-btn--small" %>
|
|
24
|
+
<%= link_to "Delete", admin_form_path(form), data: { turbo_method: :delete, turbo_confirm: "Are you sure you want to delete this form?" }, class: "np-btn np-btn--small np-btn--danger" %>
|
|
25
|
+
</td>
|
|
26
|
+
</tr>
|
|
27
|
+
<% end %>
|
|
28
|
+
</tbody>
|
|
29
|
+
</table>
|
|
30
|
+
<% else %>
|
|
31
|
+
<p>No forms yet. <%= link_to "Create your first form", new_admin_form_path %>.</p>
|
|
32
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render "form" %>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<div class="np-actions" style="margin-bottom: 1.5rem;">
|
|
2
|
+
<%= link_to "Back to Forms", admin_forms_path, class: "np-btn" %>
|
|
3
|
+
<%= link_to "Edit Form", edit_admin_form_path(@form), class: "np-btn" %>
|
|
4
|
+
<% if @submissions.any? %>
|
|
5
|
+
<%= link_to "Export CSV", export_csv_admin_form_path(@form), class: "np-btn np-btn--primary" %>
|
|
6
|
+
<% end %>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<h2>Submissions for "<%= @form.name %>"</h2>
|
|
10
|
+
|
|
11
|
+
<% if @submissions.any? %>
|
|
12
|
+
<table class="np-table">
|
|
13
|
+
<thead>
|
|
14
|
+
<tr>
|
|
15
|
+
<% @field_labels.each do |label| %>
|
|
16
|
+
<th><%= label %></th>
|
|
17
|
+
<% end %>
|
|
18
|
+
<th>Submitted At</th>
|
|
19
|
+
</tr>
|
|
20
|
+
</thead>
|
|
21
|
+
<tbody>
|
|
22
|
+
<% @submissions.each do |submission| %>
|
|
23
|
+
<tr>
|
|
24
|
+
<% @field_labels.each do |label| %>
|
|
25
|
+
<td><%= submission.data[label] %></td>
|
|
26
|
+
<% end %>
|
|
27
|
+
<td><%= submission.submitted_at&.strftime("%Y-%m-%d %H:%M:%S") %></td>
|
|
28
|
+
</tr>
|
|
29
|
+
<% end %>
|
|
30
|
+
</tbody>
|
|
31
|
+
</table>
|
|
32
|
+
<% else %>
|
|
33
|
+
<p>No submissions yet.</p>
|
|
34
|
+
<% end %>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<div class="np-media-card">
|
|
2
|
+
<div class="np-media-card-thumb">
|
|
3
|
+
<% if media.image? && media.file.attached? %>
|
|
4
|
+
<%= image_tag main_app.rails_blob_path(media.file, disposition: "inline", only_path: true), alt: media.alt_text || media.title %>
|
|
5
|
+
<% else %>
|
|
6
|
+
<div class="np-media-card-icon">DOC</div>
|
|
7
|
+
<% end %>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="np-media-card-info">
|
|
10
|
+
<div class="np-media-card-title"><%= media.title || "Untitled" %></div>
|
|
11
|
+
<div class="np-media-card-meta">
|
|
12
|
+
<span class="np-badge"><%= media.content_type %></span>
|
|
13
|
+
<span><%= number_to_human_size(media.file_size || 0) %></span>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="np-media-card-date"><%= time_ago_short(media.created_at) %></div>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="np-media-card-actions">
|
|
18
|
+
<%= link_to "Edit", edit_admin_media_attachment_path(media), class: "np-btn np-btn--small" %>
|
|
19
|
+
<%= button_to "Delete", admin_media_attachment_path(media), method: :delete, class: "np-btn np-btn--small np-btn--danger", data: { confirm: "Delete this media?" } %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<div class="np-media-picker-grid" style="display:grid; grid-template-columns:repeat(auto-fill, minmax(120px, 1fr)); gap:0.75rem; padding:1rem;">
|
|
2
|
+
<% @media.each do |media| %>
|
|
3
|
+
<div class="np-media-picker-item"
|
|
4
|
+
style="cursor:pointer; border:2px solid transparent; border-radius:4px; overflow:hidden; transition:border-color 0.2s;"
|
|
5
|
+
data-media-id="<%= media.id %>"
|
|
6
|
+
data-media-url="<%= main_app.rails_blob_path(media.file, disposition: 'inline', only_path: true) %>"
|
|
7
|
+
data-media-alt="<%= media.alt_text %>"
|
|
8
|
+
data-media-title="<%= media.title %>"
|
|
9
|
+
data-action="click->np-media-picker#select">
|
|
10
|
+
<%= image_tag main_app.rails_blob_path(media.file, disposition: "inline", only_path: true), alt: media.alt_text || media.title, style: "width:100%; height:100px; object-fit:cover; display:block;" %>
|
|
11
|
+
<div style="padding:0.25rem; font-size:0.75rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">
|
|
12
|
+
<%= media.title %>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% if @media.empty? %>
|
|
17
|
+
<p style="grid-column:1/-1; text-align:center; color:#64748b; padding:2rem 0;">No images found in media library.</p>
|
|
18
|
+
<% end %>
|
|
19
|
+
</div>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<% admin_breadcrumb "Media Library", admin_media_attachments_path %>
|
|
2
|
+
<% admin_breadcrumb @media_attachment.title || "Edit" %>
|
|
3
|
+
|
|
4
|
+
<div style="display:flex; gap:2rem; flex-wrap:wrap;">
|
|
5
|
+
<div style="flex:0 0 300px;">
|
|
6
|
+
<div class="np-media-card-thumb" style="height:auto; max-height:300px; border:1px solid var(--np-border); border-radius:0.5rem; overflow:hidden; display:flex; align-items:center; justify-content:center; background-color:#f1f5f9;">
|
|
7
|
+
<% if @media_attachment.image? && @media_attachment.file.attached? %>
|
|
8
|
+
<%= image_tag main_app.rails_blob_path(@media_attachment.file, disposition: "inline", only_path: true), style: "max-width:100%; max-height:300px; object-fit:contain;" %>
|
|
9
|
+
<% else %>
|
|
10
|
+
<div style="padding:2rem; text-align:center; color:#94a3b8;">
|
|
11
|
+
<div style="font-size:2rem; font-weight:700;">DOC</div>
|
|
12
|
+
<div style="margin-top:0.5rem;"><%= @media_attachment.content_type %></div>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div style="margin-top:1rem; font-size:0.875rem; color:#64748b;">
|
|
18
|
+
<p><strong>File size:</strong> <%= number_to_human_size(@media_attachment.file_size || 0) %></p>
|
|
19
|
+
<p><strong>Content type:</strong> <%= @media_attachment.content_type %></p>
|
|
20
|
+
<p><strong>Uploaded:</strong> <%= @media_attachment.created_at.strftime("%B %d, %Y at %I:%M %p") %></p>
|
|
21
|
+
<% if @media_attachment.file.attached? %>
|
|
22
|
+
<p><strong>URL:</strong> <%= link_to "View file", main_app.rails_blob_path(@media_attachment.file, disposition: "inline", only_path: true), target: "_blank", class: "np-btn np-btn--small" %></p>
|
|
23
|
+
<% end %>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div style="flex:1; min-width:250px;">
|
|
28
|
+
<%= form_with model: @media_attachment, url: admin_media_attachment_path(@media_attachment), method: :patch, class: "np-form" do |f| %>
|
|
29
|
+
<% if @media_attachment.errors.any? %>
|
|
30
|
+
<div class="np-form-errors">
|
|
31
|
+
<h3><%= pluralize(@media_attachment.errors.count, "error") %> prevented this media from being saved:</h3>
|
|
32
|
+
<ul>
|
|
33
|
+
<% @media_attachment.errors.full_messages.each do |msg| %>
|
|
34
|
+
<li><%= msg %></li>
|
|
35
|
+
<% end %>
|
|
36
|
+
</ul>
|
|
37
|
+
</div>
|
|
38
|
+
<% end %>
|
|
39
|
+
|
|
40
|
+
<div class="np-form-group">
|
|
41
|
+
<%= f.label :title, class: "np-label" %>
|
|
42
|
+
<%= f.text_field :title, class: "np-input" %>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="np-form-group">
|
|
46
|
+
<%= f.label :alt_text, "Alt text", class: "np-label" %>
|
|
47
|
+
<%= f.text_area :alt_text, class: "np-input", rows: 3, placeholder: "Describe this media for accessibility" %>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="np-form-actions">
|
|
51
|
+
<%= f.submit "Save Changes", class: "np-btn np-btn--primary" %>
|
|
52
|
+
<%= link_to "Back to Media", admin_media_attachments_path, class: "np-btn" %>
|
|
53
|
+
<%= button_to "Delete", admin_media_attachment_path(@media_attachment), method: :delete, class: "np-btn np-btn--danger", data: { confirm: "Delete this media?" } %>
|
|
54
|
+
</div>
|
|
55
|
+
<% end %>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<% admin_breadcrumb "Media Library" %>
|
|
2
|
+
|
|
3
|
+
<div class="np-actions" style="margin-bottom: 1rem;">
|
|
4
|
+
<div data-controller="np-media-upload">
|
|
5
|
+
<%= form_tag admin_media_attachments_path, multipart: true, id: "media-upload-form", style: "display:inline" do %>
|
|
6
|
+
<input type="file" name="files[]" multiple id="media-file-input" style="display:none" data-np-media-upload-target="input" data-action="change->np-media-upload#submit">
|
|
7
|
+
<button type="button" class="np-btn np-btn--primary" data-action="np-media-upload#choose">Upload Files</button>
|
|
8
|
+
<% end %>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="np-media-filters" style="display:flex; gap:1rem; align-items:center; margin-bottom:1rem; flex-wrap:wrap;">
|
|
13
|
+
<div class="np-media-tabs">
|
|
14
|
+
<%= link_to "All", admin_media_attachments_path(q: params[:q]), class: "np-btn np-btn--small #{params[:type].blank? ? 'np-btn--primary' : ''}" %>
|
|
15
|
+
<%= link_to "Images", admin_media_attachments_path(type: "images", q: params[:q]), class: "np-btn np-btn--small #{params[:type] == 'images' ? 'np-btn--primary' : ''}" %>
|
|
16
|
+
<%= link_to "Documents", admin_media_attachments_path(type: "documents", q: params[:q]), class: "np-btn np-btn--small #{params[:type] == 'documents' ? 'np-btn--primary' : ''}" %>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<%= form_tag admin_media_attachments_path, method: :get, style: "display:flex; gap:0.5rem;" do %>
|
|
20
|
+
<% if params[:type].present? %>
|
|
21
|
+
<input type="hidden" name="type" value="<%= params[:type] %>">
|
|
22
|
+
<% end %>
|
|
23
|
+
<input type="text" name="q" value="<%= params[:q] %>" placeholder="Search media..." class="np-input" style="width:14rem;">
|
|
24
|
+
<button type="submit" class="np-btn">Search</button>
|
|
25
|
+
<% end %>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<% if @media.any? %>
|
|
29
|
+
<div class="np-media-grid">
|
|
30
|
+
<% @media.each do |media| %>
|
|
31
|
+
<%= render "media_card", media: media %>
|
|
32
|
+
<% end %>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<% if @total_pages > 1 %>
|
|
36
|
+
<div class="np-pagination" style="display:flex; gap:0.5rem; margin-top:1rem; align-items:center;">
|
|
37
|
+
<% if @current_page > 1 %>
|
|
38
|
+
<%= link_to "Previous", admin_media_attachments_path(page: @current_page - 1, type: params[:type], q: params[:q]), class: "np-btn np-btn--small" %>
|
|
39
|
+
<% end %>
|
|
40
|
+
<span style="font-size:0.875rem; color:#64748b;">Page <%= @current_page %> of <%= @total_pages %></span>
|
|
41
|
+
<% if @current_page < @total_pages %>
|
|
42
|
+
<%= link_to "Next", admin_media_attachments_path(page: @current_page + 1, type: params[:type], q: params[:q]), class: "np-btn np-btn--small" %>
|
|
43
|
+
<% end %>
|
|
44
|
+
</div>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% else %>
|
|
47
|
+
<p style="color:#64748b; text-align:center; padding:2rem 0;">No media found.</p>
|
|
48
|
+
<% end %>
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<%= form_with model: @page, url: @page.new_record? ? admin_pages_path : admin_page_path(@page), class: "np-form" do |f| %>
|
|
2
|
+
<% if @page.errors.any? %>
|
|
3
|
+
<div class="np-form-errors">
|
|
4
|
+
<h3><%= pluralize(@page.errors.count, "error") %> prevented this page from being saved:</h3>
|
|
5
|
+
<ul>
|
|
6
|
+
<% @page.errors.full_messages.each do |message| %>
|
|
7
|
+
<li><%= message %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
</ul>
|
|
10
|
+
</div>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<fieldset class="np-fieldset">
|
|
14
|
+
<legend class="np-legend">General</legend>
|
|
15
|
+
|
|
16
|
+
<div class="np-form-group">
|
|
17
|
+
<%= f.label :title, class: "np-label" %>
|
|
18
|
+
<%= f.text_field :title, class: "np-input" %>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="np-form-group">
|
|
22
|
+
<%= f.label :slug, class: "np-label" %>
|
|
23
|
+
<%= f.text_field :slug, class: "np-input", placeholder: "auto-generated from title if blank" %>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="np-form-group">
|
|
27
|
+
<%= f.label :parent_id, "Parent Page", class: "np-label" %>
|
|
28
|
+
<%= f.select :parent_id, NotPressed::Page.where.not(id: @page.id).pluck(:title, :id), { include_blank: "None (top-level)" }, class: "np-input" %>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="np-form-group">
|
|
32
|
+
<%= f.label :content_type, class: "np-label" %>
|
|
33
|
+
<%= f.select :content_type, NotPressed::ContentTypeRegistry.names, {}, class: "np-input" %>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="np-form-group">
|
|
37
|
+
<%= f.label :status, class: "np-label" %>
|
|
38
|
+
<%= f.select :status, NotPressed::Page.statuses.keys.map { |s| [s.humanize, s] }, {}, class: "np-input", id: "page-status-select" %>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="np-form-group" id="scheduled-at-group" style="<%= @page.scheduled? ? '' : 'display:none;' %>">
|
|
42
|
+
<%= f.label :scheduled_at, "Scheduled Publish Date", class: "np-label" %>
|
|
43
|
+
<%= f.datetime_local_field :scheduled_at, class: "np-input" %>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div id="blog-fields" style="<%= @page.content_type == 'blog_post' ? '' : 'display:none;' %>">
|
|
47
|
+
<div class="np-form-group">
|
|
48
|
+
<%= f.label :category_id, "Category", class: "np-label" %>
|
|
49
|
+
<%= f.select :category_id, NotPressed::Category.ordered.pluck(:name, :id), { include_blank: "None" }, class: "np-input" %>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="np-form-group">
|
|
53
|
+
<span class="np-label">Tags</span>
|
|
54
|
+
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
|
|
55
|
+
<% NotPressed::Tag.order(:name).each do |tag| %>
|
|
56
|
+
<label style="display: inline-flex; align-items: center; gap: 0.25rem;">
|
|
57
|
+
<%= check_box_tag "page[tag_ids][]", tag.id, @page.tag_ids.include?(tag.id) %>
|
|
58
|
+
<%= tag.name %>
|
|
59
|
+
</label>
|
|
60
|
+
<% end %>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</fieldset>
|
|
65
|
+
|
|
66
|
+
<details class="np-fieldset-details">
|
|
67
|
+
<summary class="np-legend">SEO</summary>
|
|
68
|
+
<fieldset class="np-fieldset np-fieldset--no-border">
|
|
69
|
+
<div class="np-form-group">
|
|
70
|
+
<%= f.label :meta_title, class: "np-label" %>
|
|
71
|
+
<%= f.text_field :meta_title, class: "np-input", placeholder: "Defaults to page title" %>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="np-form-group">
|
|
75
|
+
<%= f.label :meta_description, class: "np-label" %>
|
|
76
|
+
<%= f.text_area :meta_description, class: "np-input", rows: 2 %>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="np-form-group">
|
|
80
|
+
<%= f.label :og_image_url, "OG Image URL", class: "np-label" %>
|
|
81
|
+
<%= f.text_field :og_image_url, class: "np-input", placeholder: "https://example.com/image.jpg" %>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div class="np-form-group">
|
|
85
|
+
<%= f.label :canonical_url, "Canonical URL", class: "np-label" %>
|
|
86
|
+
<%= f.text_field :canonical_url, class: "np-input", placeholder: "https://example.com/preferred-url" %>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="np-form-group">
|
|
90
|
+
<%= f.label :meta_robots, "Meta Robots", class: "np-label" %>
|
|
91
|
+
<%= f.text_field :meta_robots, class: "np-input", placeholder: "e.g. noindex, nofollow" %>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div class="np-form-group">
|
|
95
|
+
<%= f.label :og_type, "OG Type", class: "np-label" %>
|
|
96
|
+
<%= f.select :og_type, ["website", "article", "profile"], {}, class: "np-input" %>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<div class="np-form-group">
|
|
100
|
+
<%= f.label :twitter_card, "Twitter Card", class: "np-label" %>
|
|
101
|
+
<%= f.select :twitter_card, ["summary", "summary_large_image"], {}, class: "np-input" %>
|
|
102
|
+
</div>
|
|
103
|
+
</fieldset>
|
|
104
|
+
</details>
|
|
105
|
+
|
|
106
|
+
<details class="np-fieldset-details">
|
|
107
|
+
<summary class="np-legend">Code Injection</summary>
|
|
108
|
+
<fieldset class="np-fieldset np-fieldset--no-border">
|
|
109
|
+
<p class="np-hint">Add custom scripts, styles, or meta tags for this page.</p>
|
|
110
|
+
|
|
111
|
+
<div class="np-form-group">
|
|
112
|
+
<%= f.label :head_code, "Header Code", class: "np-label" %>
|
|
113
|
+
<p class="np-hint">Injected into <head></p>
|
|
114
|
+
<%= f.text_area :head_code, class: "np-input", rows: 4, style: "font-family: monospace;" %>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="np-form-group">
|
|
118
|
+
<%= f.label :body_code, "Footer Code", class: "np-label" %>
|
|
119
|
+
<p class="np-hint">Injected before </body></p>
|
|
120
|
+
<%= f.text_area :body_code, class: "np-input", rows: 4, style: "font-family: monospace;" %>
|
|
121
|
+
</div>
|
|
122
|
+
</fieldset>
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
<details class="np-fieldset-details">
|
|
126
|
+
<summary class="np-legend">Advanced</summary>
|
|
127
|
+
<fieldset class="np-fieldset np-fieldset--no-border">
|
|
128
|
+
<div class="np-form-group">
|
|
129
|
+
<%= f.label :layout, class: "np-label" %>
|
|
130
|
+
<%= f.select :layout, NotPressed.configuration.effective_layouts, { include_blank: "Default" }, class: "np-input" %>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div class="np-form-group">
|
|
134
|
+
<%= f.label :visibility, class: "np-label" %>
|
|
135
|
+
<%= f.select :visibility, NotPressed::Page.visibilities.keys.map { |v| [v.humanize, v] }, {}, class: "np-input", id: "page-visibility-select" %>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="np-form-group" id="password-group" style="<%= @page.visibility_password_protected? ? '' : 'display:none;' %>">
|
|
139
|
+
<%= f.label :page_password, "Page Password", class: "np-label" %>
|
|
140
|
+
<%= f.text_field :page_password, class: "np-input", placeholder: "Enter password for protected page" %>
|
|
141
|
+
</div>
|
|
142
|
+
</fieldset>
|
|
143
|
+
</details>
|
|
144
|
+
|
|
145
|
+
<script>
|
|
146
|
+
document.addEventListener("DOMContentLoaded", function() {
|
|
147
|
+
var statusField = document.getElementById("page-status-select");
|
|
148
|
+
var scheduledGroup = document.getElementById("scheduled-at-group");
|
|
149
|
+
if (statusField && scheduledGroup) {
|
|
150
|
+
statusField.addEventListener("change", function() {
|
|
151
|
+
scheduledGroup.style.display = statusField.value === "scheduled" ? "" : "none";
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
var contentTypeField = document.querySelector("select[name='page[content_type]']");
|
|
156
|
+
var blogFields = document.getElementById("blog-fields");
|
|
157
|
+
if (contentTypeField && blogFields) {
|
|
158
|
+
contentTypeField.addEventListener("change", function() {
|
|
159
|
+
blogFields.style.display = contentTypeField.value === "blog_post" ? "" : "none";
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
var visibilityField = document.getElementById("page-visibility-select");
|
|
164
|
+
var passwordGroup = document.getElementById("password-group");
|
|
165
|
+
if (visibilityField && passwordGroup) {
|
|
166
|
+
visibilityField.addEventListener("change", function() {
|
|
167
|
+
passwordGroup.style.display = visibilityField.value === "password_protected" ? "" : "none";
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<div class="np-form-actions">
|
|
174
|
+
<%= f.submit @page.persisted? ? "Update Page" : "Create Page", class: "np-btn np-btn--primary" %>
|
|
175
|
+
<%= link_to "Cancel", admin_pages_path, class: "np-btn" %>
|
|
176
|
+
</div>
|
|
177
|
+
<% end %>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<div class="np-tree-node" data-tree-id="<%= page.id %>" data-tree-level="<%= level %>" data-page-id="<%= page.id %>" draggable="true" data-action="dragstart->np-page-sortable#dragstart dragover->np-page-sortable#dragover drop->np-page-sortable#drop dragend->np-page-sortable#dragend">
|
|
2
|
+
<div class="np-tree-indent" style="padding-left: <%= level * 1.5 %>rem;">
|
|
3
|
+
<span class="np-drag-handle" data-action="mousedown->np-page-sortable#grabHandle">⣿</span>
|
|
4
|
+
<% if page.children.any? %>
|
|
5
|
+
<button type="button" class="np-tree-toggle" data-action="click->np-tree#toggle" data-np-tree-target="toggle" data-page-id="<%= page.id %>" aria-label="Toggle children">▼</button>
|
|
6
|
+
<% else %>
|
|
7
|
+
<span class="np-tree-toggle np-tree-toggle--leaf">•</span>
|
|
8
|
+
<% end %>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="np-tree-title">
|
|
11
|
+
<%= link_to page.title, edit_admin_page_path(page) %>
|
|
12
|
+
<% if page.children.any? %>
|
|
13
|
+
<span class="np-badge"><%= page.children.size %></span>
|
|
14
|
+
<% end %>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="np-tree-meta"><%= status_badge(page.status) %></div>
|
|
17
|
+
<div class="np-tree-meta"><%= page.content_type %></div>
|
|
18
|
+
<div class="np-tree-meta"><%= page.content_blocks.size %></div>
|
|
19
|
+
<div class="np-tree-meta"><%= time_ago_short(page.updated_at) %></div>
|
|
20
|
+
<div class="np-tree-actions">
|
|
21
|
+
<%= link_to "Edit", edit_admin_page_path(page), class: "np-btn np-btn--small" %>
|
|
22
|
+
<%= button_to "Duplicate", duplicate_admin_page_path(page), method: :post, class: "np-btn np-btn--small" %>
|
|
23
|
+
<%= button_to "Delete", admin_page_path(page), method: :delete, class: "np-btn np-btn--danger np-btn--small", data: { turbo_confirm: "Are you sure?" } %>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<% if page.children.any? %>
|
|
27
|
+
<div class="np-tree-children" data-np-tree-target="children" data-parent-id="<%= page.id %>">
|
|
28
|
+
<% page.children.ordered.each do |child| %>
|
|
29
|
+
<%= render partial: "not_pressed/admin/pages/page_tree_node", locals: { page: child, level: level + 1 } %>
|
|
30
|
+
<% end %>
|
|
31
|
+
</div>
|
|
32
|
+
<% end %>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<div class="np-preview-toggle" data-controller="np-preview" data-np-preview-preview-url-value="<%= preview_admin_page_path(@page) %>">
|
|
2
|
+
<div class="np-preview-toggle-buttons">
|
|
3
|
+
<button type="button" class="np-btn np-btn--small np-preview-btn--active" data-action="click->np-preview#editorMode" data-np-preview-target="editorBtn">Editor</button>
|
|
4
|
+
<button type="button" class="np-btn np-btn--small" data-action="click->np-preview#splitMode" data-np-preview-target="splitBtn">Split</button>
|
|
5
|
+
<button type="button" class="np-btn np-btn--small" data-action="click->np-preview#previewMode" data-np-preview-target="previewBtn">Preview</button>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div class="np-editor-split" data-np-preview-target="container">
|
|
9
|
+
<div class="np-editor-pane" data-np-preview-target="editorPane">
|
|
10
|
+
<div class="np-page-settings">
|
|
11
|
+
<details>
|
|
12
|
+
<summary class="np-btn" style="margin-bottom: 1rem;">Page Settings</summary>
|
|
13
|
+
<div class="np-page-settings-body">
|
|
14
|
+
<%= render "form" %>
|
|
15
|
+
</div>
|
|
16
|
+
</details>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<hr style="margin: 1.5rem 0; border: none; border-top: 1px solid var(--np-border);">
|
|
20
|
+
|
|
21
|
+
<div class="np-block-editor" data-controller="np-block-editor np-sortable" data-np-block-editor-page-id-value="<%= @page.id %>" data-np-sortable-url-value="<%= reorder_admin_page_content_blocks_path(@page) %>">
|
|
22
|
+
<h3 style="margin-bottom: 1rem;">Content Blocks</h3>
|
|
23
|
+
|
|
24
|
+
<div id="blocks-list" data-np-sortable-target="list">
|
|
25
|
+
<% @blocks.each do |block| %>
|
|
26
|
+
<%= render "not_pressed/admin/content_blocks/block", block: block %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="np-block-type-picker" style="margin-top: 1rem;">
|
|
31
|
+
<button type="button" class="np-btn np-btn--primary" data-action="click->np-block-editor#openPicker">+ Add Block</button>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<%= render "not_pressed/admin/content_blocks/block_picker", page: @page %>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<% if @versions.present? %>
|
|
39
|
+
<hr style="margin: 1.5rem 0; border: none; border-top: 1px solid var(--np-border);">
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary class="np-btn" style="margin-bottom: 1rem;">Version History (<%= @versions.size %>)</summary>
|
|
43
|
+
<table class="np-table" style="margin-top: 0.5rem;">
|
|
44
|
+
<thead>
|
|
45
|
+
<tr>
|
|
46
|
+
<th>Version</th>
|
|
47
|
+
<th>Event</th>
|
|
48
|
+
<th>Date</th>
|
|
49
|
+
</tr>
|
|
50
|
+
</thead>
|
|
51
|
+
<tbody>
|
|
52
|
+
<% @versions.each do |version| %>
|
|
53
|
+
<tr>
|
|
54
|
+
<td>#<%= version.version_number %></td>
|
|
55
|
+
<td><span class="np-badge"><%= version.event.humanize %></span></td>
|
|
56
|
+
<td><%= time_ago_short(version.created_at) %></td>
|
|
57
|
+
</tr>
|
|
58
|
+
<% end %>
|
|
59
|
+
</tbody>
|
|
60
|
+
</table>
|
|
61
|
+
</details>
|
|
62
|
+
<% end %>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="np-preview-pane" data-np-preview-target="previewPane" style="display: none;">
|
|
66
|
+
<iframe data-np-preview-target="frame" class="np-preview-frame" src="<%= preview_admin_page_path(@page) %>"></iframe>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<div class="np-actions" style="margin-bottom: 1.5rem;">
|
|
2
|
+
<%= link_to "New Page", new_admin_page_path, class: "np-btn np-btn--primary" %>
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<% if @pages.any? %>
|
|
6
|
+
<div class="np-tree" data-controller="np-tree np-page-sortable" data-np-page-sortable-url-value="<%= reorder_admin_pages_path %>">
|
|
7
|
+
<div class="np-tree-header">
|
|
8
|
+
<div class="np-tree-header-title">Title</div>
|
|
9
|
+
<div class="np-tree-meta">Status</div>
|
|
10
|
+
<div class="np-tree-meta">Type</div>
|
|
11
|
+
<div class="np-tree-meta">Blocks</div>
|
|
12
|
+
<div class="np-tree-meta">Updated</div>
|
|
13
|
+
<div class="np-tree-header-actions">Actions</div>
|
|
14
|
+
</div>
|
|
15
|
+
<% @pages.each do |page| %>
|
|
16
|
+
<%= render partial: "not_pressed/admin/pages/page_tree_node", locals: { page: page, level: 0 } %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</div>
|
|
19
|
+
<% else %>
|
|
20
|
+
<p>No pages yet. <%= link_to "Create your first page", new_admin_page_path %>.</p>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render "form" %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Preview: <%= @page.title %></title>
|
|
7
|
+
<%= stylesheet_link_tag "not_pressed/content", media: "all" %>
|
|
8
|
+
<%= stylesheet_link_tag "not_pressed/gallery", media: "all" %>
|
|
9
|
+
</head>
|
|
10
|
+
<body class="np-preview-body">
|
|
11
|
+
<article class="np-preview-article">
|
|
12
|
+
<h1><%= @page.title %></h1>
|
|
13
|
+
<%= render_page_content(@page) %>
|
|
14
|
+
</article>
|
|
15
|
+
<%= javascript_include_tag "not_pressed/lightbox" %>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|