trusty-cms 7.0.26 → 7.0.28
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/Gemfile.lock +1 -1
- data/README.md +17 -5
- data/app/assets/javascripts/admin/preview.js +40 -0
- data/app/assets/javascripts/admin.js +1 -0
- data/app/controllers/admin/pages_controller.rb +29 -1
- data/app/controllers/admin/resource_controller.rb +0 -2
- data/app/helpers/admin/node_helper.rb +2 -11
- data/app/helpers/admin/url_helper.rb +12 -0
- data/app/helpers/application_helper.rb +0 -10
- data/app/models/page.rb +1 -1
- data/app/services/admin/preview_page_builder.rb +54 -0
- data/app/views/admin/pages/_fields.html.haml +17 -21
- data/config/locales/en.yml +0 -2
- data/config/routes.rb +1 -0
- data/lib/trusty_cms/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16753e005b09f59c333c5e9fd2af4bca3bd0e20f8d2da054500b3d262d1eecfa
|
4
|
+
data.tar.gz: c4159171a6a9f932b685cd3855bd0f931392053d4d797025e73aae1a5aa443fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f91892e8c3e8b0aa0e3899b7796833a4e2a0e5074eacf92f5e47b7e216559b5c4d32f487f03fb725775d960d20f0cd15cea678a0a14ef42aa65c9d07cb531c2
|
7
|
+
data.tar.gz: f5735dc96aa6cf0c3c80686f36d48cd7d49f5b8865ffd4c2d02ab708170764b5bff91a7fb525acbff932e67c76b9adcd104f35e145ee71ce61c4c897e42c597f
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -77,6 +77,23 @@ Steps:
|
|
77
77
|
|
78
78
|
rspec
|
79
79
|
|
80
|
+
### Preview Custom Page Types
|
81
|
+
|
82
|
+
TrustyCMS supports a preview feature for standard page types. However, this functionality may not work out of the box for custom page types. To enable the preview feature for your custom page types, follow these steps:
|
83
|
+
|
84
|
+
1. In your application, create the following initializer file: `config/initializers/preview_page_types.rb`
|
85
|
+
2. Inside this file, define a `PREVIEW_PAGE_TYPES` array constant with the names of the page types you’d like to enable the Preview button for, for example:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
PREVIEW_PAGE_TYPES = %w[
|
89
|
+
BlogPage
|
90
|
+
FacilityPage
|
91
|
+
FileNotFoundPage
|
92
|
+
].freeze
|
93
|
+
```
|
94
|
+
|
95
|
+
3. Test the Preview button with each custom page type. If a page type does not preview correctly, remove it from the list.
|
96
|
+
|
80
97
|
### Custom Page Type Routes Setup
|
81
98
|
Additional configuration is required to ensure correct URL generation in the admin interface — specifically for the "Edit Page" dropdown and the "Save and View Draft" functionality.
|
82
99
|
|
@@ -106,11 +123,6 @@ DEFAULT_PAGE_TYPE_ROUTES = %w[
|
|
106
123
|
].freeze
|
107
124
|
```
|
108
125
|
|
109
|
-
### Save and View Draft Caching
|
110
|
-
To ensure that pages and drafts under development are not cached by the browser or content delivery networks (such as CloudFront), the CMS appends a `trusty-no-cache` URL parameter containing the current date and time when a user selects **Save and View Draft** or **Save and View Page**.
|
111
|
-
|
112
|
-
Because the `trusty-no-cache` parameter is always unique, it effectively bypasses caching mechanisms at both the CDN and browser levels, ensuring the user receives the most up-to-date version of the content with every request. Note that additional CDN configuration may be required to ensure query parameters are respected.
|
113
|
-
|
114
126
|
### Page Status Refresh Setup
|
115
127
|
|
116
128
|
To ensure **Scheduled Pages** automatically update their status to **Published** after their designated **Publish Date & Time**, follow these steps to set up an automated refresh using **AWS Lambda** and **EventBridge**.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
(function(Preview, $) {
|
2
|
+
Preview.showPreview = function(form){
|
3
|
+
var oldTarget = form.target;
|
4
|
+
var oldAction = form.action;
|
5
|
+
|
6
|
+
var $previewer = $('#preview_panel');
|
7
|
+
var $preview_tools = $previewer.find('.preview_tools');
|
8
|
+
var $frame = $('#page-preview');
|
9
|
+
|
10
|
+
$(window).scrollTop(0);
|
11
|
+
$previewer.show();
|
12
|
+
$preview_tools.css('opacity', 1);
|
13
|
+
$('body').addClass('clipped');
|
14
|
+
form.target = $frame.attr('id');
|
15
|
+
form.action = relative_url_root + '/admin/preview';
|
16
|
+
form.submit();
|
17
|
+
|
18
|
+
form.target = oldTarget;
|
19
|
+
form.action = oldAction;
|
20
|
+
}
|
21
|
+
|
22
|
+
}(window.Preview = window.Preview || {}, jQuery));
|
23
|
+
|
24
|
+
$(function () {
|
25
|
+
$('#show-preview').on('click', function(event){
|
26
|
+
event.preventDefault();
|
27
|
+
Preview.showPreview(this.form);
|
28
|
+
});
|
29
|
+
|
30
|
+
$('.preview_tools a.cancel').on('click', function(event){
|
31
|
+
event.preventDefault();
|
32
|
+
$('#preview_panel').hide();
|
33
|
+
$('body').removeClass('clipped');
|
34
|
+
$('#page-preview').attr('src', '');
|
35
|
+
});
|
36
|
+
|
37
|
+
$('iframe').on('load', function(event){
|
38
|
+
$('#preview_panel .preview_tools').css('opacity', null);
|
39
|
+
});
|
40
|
+
});
|
@@ -3,7 +3,6 @@ class Admin::PagesController < Admin::ResourceController
|
|
3
3
|
before_action :count_deleted_pages, only: [:destroy]
|
4
4
|
before_action :set_page, only: %i[edit restore]
|
5
5
|
rescue_from ActiveRecord::RecordInvalid, with: :validation_error
|
6
|
-
include Admin::NodeHelper
|
7
6
|
include Admin::PagesHelper
|
8
7
|
include Admin::UrlHelper
|
9
8
|
|
@@ -43,6 +42,7 @@ class Admin::PagesController < Admin::ResourceController
|
|
43
42
|
assets = Asset.order('created_at DESC')
|
44
43
|
@term = assets.ransack(params[:search] || '')
|
45
44
|
@page = self.model = model_class.new_with_defaults(trusty_config)
|
45
|
+
@render_preview_button = render_preview_button?
|
46
46
|
assign_page_attributes
|
47
47
|
response_for :new
|
48
48
|
end
|
@@ -53,6 +53,7 @@ class Admin::PagesController < Admin::ResourceController
|
|
53
53
|
@page_url = generate_page_url(request.url, @page)
|
54
54
|
@page_path = format_path(@page.path)
|
55
55
|
@versions = format_versions(@page.versions)
|
56
|
+
@render_preview_button = render_preview_button?
|
56
57
|
response_for :edit
|
57
58
|
end
|
58
59
|
|
@@ -62,6 +63,12 @@ class Admin::PagesController < Admin::ResourceController
|
|
62
63
|
redirect_to edit_admin_page_path(@page)
|
63
64
|
end
|
64
65
|
|
66
|
+
def preview
|
67
|
+
render_preview
|
68
|
+
rescue PreviewStop => e
|
69
|
+
render text: e.message unless @performed_render
|
70
|
+
end
|
71
|
+
|
65
72
|
def save_table_position
|
66
73
|
new_position = params[:new_position]
|
67
74
|
Page.save_order(new_position)
|
@@ -152,6 +159,20 @@ class Admin::PagesController < Admin::ResourceController
|
|
152
159
|
end
|
153
160
|
end
|
154
161
|
|
162
|
+
def render_preview
|
163
|
+
params.permit!
|
164
|
+
Page.transaction do
|
165
|
+
page = Admin::PreviewPageBuilder.new(
|
166
|
+
model_class:,
|
167
|
+
page_params: params[:page],
|
168
|
+
referer: request.referer,
|
169
|
+
).build
|
170
|
+
|
171
|
+
page.pagination_parameters = pagination_parameters
|
172
|
+
process_with_exception(page)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
155
176
|
def process_with_exception(page)
|
156
177
|
page.process(request, response)
|
157
178
|
@performed_render = true
|
@@ -177,4 +198,11 @@ class Admin::PagesController < Admin::ResourceController
|
|
177
198
|
raise "I'm not allowed to constantize #{page_class}!"
|
178
199
|
end
|
179
200
|
end
|
201
|
+
|
202
|
+
def render_preview_button?
|
203
|
+
page_class = @page.class.name
|
204
|
+
previewable_classes = ['Page']
|
205
|
+
previewable_classes += PREVIEW_PAGE_TYPES if defined?(PREVIEW_PAGE_TYPES)
|
206
|
+
previewable_classes.include?(page_class)
|
207
|
+
end
|
180
208
|
end
|
@@ -202,8 +202,6 @@ class Admin::ResourceController < ApplicationController
|
|
202
202
|
end
|
203
203
|
|
204
204
|
def redirect_url
|
205
|
-
return "#{edit_admin_page_url(model)}?view_page=true" if params[:save_and_view]
|
206
|
-
|
207
205
|
params[:continue] ? { action: 'edit', id: model.id } : { action: 'index' }
|
208
206
|
end
|
209
207
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module Admin::NodeHelper
|
2
|
+
include Admin::UrlHelper
|
3
|
+
|
2
4
|
def render_nodes(page, starting_index, parent_index = nil, simple = false)
|
3
5
|
@rendered_html = ''
|
4
6
|
render_node page, starting_index, parent_index, simple
|
@@ -25,17 +27,6 @@ module Admin::NodeHelper
|
|
25
27
|
page
|
26
28
|
end
|
27
29
|
|
28
|
-
def format_path(path)
|
29
|
-
return '' if path.nil? || path.empty?
|
30
|
-
|
31
|
-
parts = path.split('/').reject(&:empty?)
|
32
|
-
return 'Root' if parts.size == 1
|
33
|
-
return '/' if parts.size == 2
|
34
|
-
|
35
|
-
formatted_path = parts[1..-2].join('/')
|
36
|
-
formatted_path.empty? ? '/' : "/#{formatted_path}"
|
37
|
-
end
|
38
|
-
|
39
30
|
def homepage
|
40
31
|
@homepage ||= Page.find_by_parent_id(nil)
|
41
32
|
end
|
@@ -1,6 +1,18 @@
|
|
1
1
|
module Admin::UrlHelper
|
2
2
|
require 'uri'
|
3
3
|
|
4
|
+
def format_path(path)
|
5
|
+
return '' if path.to_s.empty?
|
6
|
+
|
7
|
+
parts = path.split('/').reject(&:empty?)
|
8
|
+
parts_size = parts.size
|
9
|
+
return 'Root' if parts_size == 1
|
10
|
+
return '/' if parts_size == 2
|
11
|
+
|
12
|
+
formatted_path = parts[1..-2].join('/')
|
13
|
+
formatted_path.empty? ? '/' : "/#{formatted_path}"
|
14
|
+
end
|
15
|
+
|
4
16
|
def generate_page_url(url, page)
|
5
17
|
base_url = extract_base_url(url)
|
6
18
|
build_url(base_url, page)
|
@@ -42,16 +42,6 @@ module ApplicationHelper
|
|
42
42
|
submit_tag t('buttons.save_and_continue'), name: 'continue', class: 'button', accesskey: 's', id: 'save-and-continue-button'
|
43
43
|
end
|
44
44
|
|
45
|
-
def save_model_and_view_page_button(model, options = {})
|
46
|
-
return nil unless generate_page_url(request.url, model)
|
47
|
-
|
48
|
-
options[:label] ||= model.published? ? t('buttons.save_and_view_page') : t('buttons.save_and_view_draft')
|
49
|
-
options[:class] ||= 'button'
|
50
|
-
options[:name] ||= 'save_and_view'
|
51
|
-
options[:id] ||= 'save-and-view-button'
|
52
|
-
submit_tag options.delete(:label), options
|
53
|
-
end
|
54
|
-
|
55
45
|
def current_item?(item)
|
56
46
|
if item.tab&.many? { |i| current_url?(i.relative_url) }
|
57
47
|
# Accept only stricter URL matches if more than one matches
|
data/app/models/page.rb
CHANGED
@@ -121,7 +121,7 @@ class Page < ActiveRecord::Base
|
|
121
121
|
def path
|
122
122
|
return '' if slug.blank?
|
123
123
|
|
124
|
-
parent? ? parent.
|
124
|
+
parent.present? ? clean_path("#{parent.path}/#{slug}") : clean_path(slug)
|
125
125
|
end
|
126
126
|
|
127
127
|
alias_method :url, :path
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Admin
|
2
|
+
class PreviewPageBuilder
|
3
|
+
def initialize(model_class:, page_params:, referer:)
|
4
|
+
@model_class = model_class
|
5
|
+
@page_params = page_params
|
6
|
+
@referer = referer
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
editing_existing_page? ? build_existing_page : build_new_page
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def build_existing_page
|
16
|
+
page = find_page_from_referer.becomes(valid_model_class)
|
17
|
+
page.update(@page_params)
|
18
|
+
page
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_new_page
|
22
|
+
page = valid_model_class.new(@page_params)
|
23
|
+
|
24
|
+
if creating_child_page?
|
25
|
+
parent = find_page_from_referer
|
26
|
+
page.parent = parent
|
27
|
+
page.layout_id ||= parent.layout_id
|
28
|
+
end
|
29
|
+
|
30
|
+
page.save!
|
31
|
+
page
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_model_class
|
35
|
+
Page.descendants.include?(@model_class) ? @model_class : Page
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_page_from_referer
|
39
|
+
Page.find(extract_page_id_from_referer)
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract_page_id_from_referer
|
43
|
+
@referer[%r{/admin/pages/(\d+)}, 1]
|
44
|
+
end
|
45
|
+
|
46
|
+
def editing_existing_page?
|
47
|
+
@referer =~ %r{/admin/pages/\d+/edit}
|
48
|
+
end
|
49
|
+
|
50
|
+
def creating_child_page?
|
51
|
+
@referer =~ %r{/admin/pages/\d+/children/new}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -20,7 +20,8 @@
|
|
20
20
|
= render :partial => 'admin/page_fields/page_field', :collection => @page.fields
|
21
21
|
= render_region :extended_metadata, :locals => {:f => fields}
|
22
22
|
.drawer_handle
|
23
|
-
|
23
|
+
- toggle_class = meta_errors? ? 'less' : 'more'
|
24
|
+
%a.toggle{ href: '#attributes', rel: 'toggle[attributes]', class: toggle_class }
|
24
25
|
= meta_label
|
25
26
|
%i.fas.fa-angle-down
|
26
27
|
- form.edit_page_parts do
|
@@ -66,32 +67,27 @@
|
|
66
67
|
.error.hidden
|
67
68
|
%span#published-at-error
|
68
69
|
|
69
|
-
- render_region :form_bottom, :
|
70
|
+
- render_region :form_bottom, locals: { f: fields } do |form_bottom|
|
70
71
|
- form_bottom.edit_buttons do
|
71
72
|
- @buttons_partials.each do |partial|
|
72
|
-
= render :
|
73
|
+
= render partial: partial, locals: { f: fields }
|
74
|
+
|
73
75
|
.page-actions
|
74
76
|
= save_model_button(@page)
|
75
77
|
= save_model_and_continue_editing_button(@page)
|
76
|
-
=
|
78
|
+
= submit_tag(t('preview'), class: 'button', id: 'show-preview') if @render_preview_button
|
77
79
|
= t('or')
|
78
80
|
= link_to t('cancel'), admin_pages_url(site_id: @site_id), class: 'alt'
|
79
|
-
#view-page-url-data{ data: { url: @page_url } }
|
80
|
-
- form_bottom.edit_timestamp do
|
81
|
-
= updated_stamp @page
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
const separator = baseUrl.includes("?") ? "&" : "?";
|
93
|
-
const newTabUrl = `${baseUrl}${separator}trusty-no-cache=${encodeURIComponent(now)}`;
|
94
|
-
window.open(newTabUrl, '_blank');
|
95
|
-
}
|
96
|
-
});
|
82
|
+
.fullcover.grey_out#preview_panel{ style: 'display: none;' }
|
83
|
+
%iframe.fullcover#page-preview{
|
84
|
+
name: 'page-preview',
|
85
|
+
src: "#{ActionController::Base.relative_url_root}/loading-iframe.html",
|
86
|
+
frameborder: 0,
|
87
|
+
scrolling: 'auto'
|
88
|
+
}
|
89
|
+
.preview_tools
|
90
|
+
= link_to t('edit_page'), {}, class: 'button cancel'
|
97
91
|
|
92
|
+
- form_bottom.edit_timestamp do
|
93
|
+
= updated_stamp(@page)
|
data/config/locales/en.yml
CHANGED
data/config/routes.rb
CHANGED
data/lib/trusty_cms/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trusty-cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TrustyCms CMS dev team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activestorage-validator
|
@@ -702,6 +702,7 @@ files:
|
|
702
702
|
- app/assets/javascripts/admin/pagefield.js
|
703
703
|
- app/assets/javascripts/admin/persist.min.js
|
704
704
|
- app/assets/javascripts/admin/popup.js
|
705
|
+
- app/assets/javascripts/admin/preview.js
|
705
706
|
- app/assets/javascripts/admin/sortable.js
|
706
707
|
- app/assets/javascripts/admin/tabcontrol.js.erb
|
707
708
|
- app/assets/javascripts/admin/tags.js
|
@@ -814,6 +815,7 @@ files:
|
|
814
815
|
- app/models/trusty_cms/page_response_cache_director.rb
|
815
816
|
- app/models/user.rb
|
816
817
|
- app/models/user_action_observer.rb
|
818
|
+
- app/services/admin/preview_page_builder.rb
|
817
819
|
- app/views/admin/assets/_asset.html.haml
|
818
820
|
- app/views/admin/assets/_asset_table.html.haml
|
819
821
|
- app/views/admin/assets/_errors.html.haml
|