comfy_middle_seat 4.0.2 → 4.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 +4 -4
- data/CHANGELOG.md +19 -1
- data/README.md +21 -2
- data/app/assets/javascripts/comfy/admin/cms/application.js +1 -0
- data/app/assets/stylesheets/comfy/admin/cms/application.sass +2 -0
- data/app/assets/stylesheets/comfy/admin/cms/harbor.sass +68 -0
- data/app/assets/stylesheets/comfy/admin/cms/harbor_variables.sass +36 -0
- data/app/controllers/comfy/admin/cms/pages_controller.rb +42 -6
- data/app/controllers/comfy/cms/content_controller.rb +2 -0
- data/app/models/comfy/cms/page.rb +13 -0
- data/app/views/comfy/admin/cms/pages/_index_branch.html.haml +8 -2
- data/app/views/comfy/admin/cms/pages/edit.html.haml +21 -3
- data/config/locales/en.yml +2 -2
- data/lib/comfy_middle_seat/content/tags/breadcrumbs.rb +8 -3
- data/lib/comfy_middle_seat/content/tags/children.rb +10 -5
- data/lib/comfy_middle_seat/content/tags/siblings.rb +14 -10
- data/lib/comfy_middle_seat/routing.rb +1 -0
- data/lib/comfy_middle_seat/version.rb +1 -1
- data/package-lock.json +1 -3
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d22803345977cfaec60811a1301ce6ad6ada6ab242d41c5c390b4c5aa6da645
|
|
4
|
+
data.tar.gz: 537cd86f6e7685b7a771dcd80e5c0c1bc01544f92e88fc3939bc956bc2a08db2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d0785ac0b03f9f9ce49112a9b8ce41332d077e3535afd1fd46f6baab5ced8316cd95a6daef480c2e67c254d4bedcf1707f2b11ee1df980907a546443ce4a2958
|
|
7
|
+
data.tar.gz: e36f136f038d6bbdd043c306306c4d2c9fa8fc4cac7a5b0ad7021c717858eaa354c529516d0642a4d09c501fc892b7c871d0749e4388bad4d22b474a5a581302
|
data/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,23 @@ This changelog follows the project's lineage: **Comfortable Mexican Sofa → Com
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Hide pages beneath unpublished ancestors without changing their publication settings.
|
|
18
|
+
- Show inherited page visibility and clarify descendant publishing actions.
|
|
19
|
+
- Gray out descendant publishing actions when no changes are needed.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Refresh page and translation navigation when branch visibility changes.
|
|
24
|
+
|
|
25
|
+
## [v4.0.2] - 2026-09-21
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Refresh the README with clearer features, setup, compatibility, and upgrade guidance.
|
|
30
|
+
- Add RubyGems links for source code, issues, documentation, and the changelog.
|
|
31
|
+
|
|
15
32
|
## [v4.0.1] - 2026-09-18
|
|
16
33
|
|
|
17
34
|
### Changed
|
|
@@ -203,7 +220,8 @@ First release of `comfortable_media_surfer`. This new gem is a revival of [Comfo
|
|
|
203
220
|
|
|
204
221
|
- Rebranded **ComfortableMexicanSofa** as **ComfortableMediaSurfer** in order to publish new gem (database table names and schema have not changed).
|
|
205
222
|
|
|
206
|
-
[Unreleased]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.0.
|
|
223
|
+
[Unreleased]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.0.2...master
|
|
224
|
+
[v4.0.2]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.0.1...v4.0.2
|
|
207
225
|
[v4.0.1]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.0.0...v4.0.1
|
|
208
226
|
[v4.0.0]: https://github.com/avonderluft/comfy-middle-seat/compare/v3.2.1...v4.0.0
|
|
209
227
|
[v3.2.1]: https://github.com/avonderluft/comfy-middle-seat/compare/v3.2.0...v3.2.1
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Add editor-managed pages, reusable layouts, rich text, Markdown, files, translations, search, and revision history to an existing Rails application—without moving your content into a separate service.
|
|
8
8
|
|
|
9
|
-
Comfy Middle Seat is actively maintained and continues the lineage of Comfortable Mexican Sofa and Comfortable Media Surfer. It keeps the memorable C.M.S. initials, with a new place to sit. It all
|
|
9
|
+
Comfy Middle Seat is actively maintained and continues the lineage of Comfortable Mexican Sofa and Comfortable Media Surfer. It keeps the memorable C.M.S. initials, with a new place to sit. It all depends on who is sitting to your right and left.
|
|
10
10
|
|
|
11
11
|
[Quick Start](#quick-start) · [Features](#features) · [Documentation](#documentation) · [Upgrading](#upgrading) · [Contributing](#contributing)
|
|
12
12
|
|
|
@@ -34,7 +34,7 @@ Comfy Middle Seat is best suited to Rails applications that render their own web
|
|
|
34
34
|
- Revision history with comparison, preview, and restore workflows.
|
|
35
35
|
- Page translations and multilingual publishing.
|
|
36
36
|
- Multi-site publishing from one installation.
|
|
37
|
-
-
|
|
37
|
+
- Publish individual pages or whole branches, with ancestor-aware visibility.
|
|
38
38
|
|
|
39
39
|
### For Rails developers
|
|
40
40
|
|
|
@@ -114,6 +114,14 @@ A Site defines a hostname, path, and language. Layouts define page structure and
|
|
|
114
114
|
|
|
115
115
|
When an editor creates a Page using this Layout, the admin automatically presents fields for `title` and `content`. Content tags can also provide Markdown, files, images, dates, numbers, checkboxes, snippets, partials, helpers, navigation, and other reusable content.
|
|
116
116
|
|
|
117
|
+
### Publishing pages
|
|
118
|
+
|
|
119
|
+
A page is publicly visible only when it and all its ancestors are published. Unpublishing a parent hides its branch without changing descendants’ individual publication settings. Republishing the parent restores only descendants whose full ancestor chain is published; drafts stay unpublished. Translations must also satisfy their own publication settings.
|
|
120
|
+
|
|
121
|
+
The Page index toggle changes only that page. The **Child pages** menu’s **Publish descendants** and **Unpublish descendants** actions change all descendants, not the current page or its ancestors. The admin marks published pages hidden by an unpublished ancestor.
|
|
122
|
+
|
|
123
|
+
Development mode continues to show unpublished pages for preview. Check public visibility in test, staging, or production mode.
|
|
124
|
+
|
|
117
125
|
## Compatibility and requirements
|
|
118
126
|
|
|
119
127
|
| Component | Support |
|
|
@@ -143,6 +151,17 @@ When adapting upstream examples, use the `comfy_middle_seat` gem, `config/initia
|
|
|
143
151
|
|
|
144
152
|
## Upgrading
|
|
145
153
|
|
|
154
|
+
### Ancestor-aware publishing (unreleased)
|
|
155
|
+
|
|
156
|
+
Review branches with unpublished ancestors: their descendants will no longer be publicly accessible. No database migration is required. After deploying, clear existing rendered content once from the Rails console so cached navigation follows the new rule:
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
Comfy::Cms::Page.update_all(content_cache: nil)
|
|
160
|
+
Comfy::Cms::Translation.update_all(content_cache: nil)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Content is regenerated on demand. Subsequent publication and parent changes refresh the affected site’s caches automatically.
|
|
164
|
+
|
|
146
165
|
### From Comfortable Media Surfer
|
|
147
166
|
|
|
148
167
|
1. Replace `comfortable_media_surfer` with `comfy_middle_seat` in the `Gemfile`. Do not include both gems.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@import "comfy/admin/cms/harbor_variables"
|
|
1
2
|
@import "comfy/vendor/bootstrap/bootstrap"
|
|
2
3
|
|
|
3
4
|
@import "codemirror/lib/codemirror"
|
|
@@ -8,4 +9,5 @@
|
|
|
8
9
|
@import "comfy/admin/cms/codemirror_overrides"
|
|
9
10
|
@import "comfy/admin/cms/redactor_overrides"
|
|
10
11
|
@import "comfy/admin/cms/base"
|
|
12
|
+
@import "comfy/admin/cms/harbor"
|
|
11
13
|
@import "comfy/admin/cms/custom"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
body#comfy
|
|
2
|
+
.btn-primary, .btn-secondary
|
|
3
|
+
@include button-variant($harbor-teal, $harbor-teal, $harbor-hover, $harbor-hover, $harbor-pressed, $harbor-pressed)
|
|
4
|
+
|
|
5
|
+
.btn-outline-primary, .btn-outline-secondary
|
|
6
|
+
@include button-outline-variant($harbor-teal, $harbor-hover, $harbor-tint, $harbor-hover)
|
|
7
|
+
background-color: $white
|
|
8
|
+
border-color: $gray-400
|
|
9
|
+
&:not(:disabled):not(.disabled):active, &:not(:disabled):not(.disabled).active
|
|
10
|
+
color: $harbor-pressed
|
|
11
|
+
&:disabled, &.disabled
|
|
12
|
+
background-color: $white
|
|
13
|
+
border-color: $gray-300
|
|
14
|
+
|
|
15
|
+
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible
|
|
16
|
+
outline: 2px solid $harbor-teal
|
|
17
|
+
outline-offset: 2px
|
|
18
|
+
|
|
19
|
+
#cms-left
|
|
20
|
+
nav.navbar ul.nav li
|
|
21
|
+
a
|
|
22
|
+
color: $harbor-nav-text
|
|
23
|
+
@include transition(color .15s ease-in-out, background-color .15s ease-in-out)
|
|
24
|
+
a:hover
|
|
25
|
+
color: $white
|
|
26
|
+
background-color: $gray-700
|
|
27
|
+
a.active
|
|
28
|
+
color: $white
|
|
29
|
+
background-color: $harbor-teal
|
|
30
|
+
box-shadow: inset 3px 0 0 $harbor-gold
|
|
31
|
+
a.active:hover
|
|
32
|
+
background-color: $harbor-hover
|
|
33
|
+
a:focus-visible, button:focus-visible
|
|
34
|
+
outline-color: $harbor-gold
|
|
35
|
+
.left-footer
|
|
36
|
+
color: $harbor-nav-text
|
|
37
|
+
a
|
|
38
|
+
color: $harbor-nav-text
|
|
39
|
+
&:hover
|
|
40
|
+
color: $white
|
|
41
|
+
|
|
42
|
+
#cms-main
|
|
43
|
+
.page-header
|
|
44
|
+
color: $harbor-navy
|
|
45
|
+
ul.list
|
|
46
|
+
li .row
|
|
47
|
+
@include transition(background-color .15s ease-in-out)
|
|
48
|
+
.item .item-title a
|
|
49
|
+
color: $gray-800
|
|
50
|
+
&:hover
|
|
51
|
+
color: $harbor-hover
|
|
52
|
+
&.draft
|
|
53
|
+
color: $gray-600
|
|
54
|
+
.item .item-controls .dragger, .item .item-controls .toggle
|
|
55
|
+
color: $gray-600
|
|
56
|
+
li.sortable-ghost > .row, li.sortable-chosen > .row, &:not(.sortable-active) > li > .row:hover
|
|
57
|
+
background-color: $harbor-tint
|
|
58
|
+
|
|
59
|
+
#cms-right
|
|
60
|
+
.box
|
|
61
|
+
border-color: $gray-300
|
|
62
|
+
.box.translations a.translation
|
|
63
|
+
color: $gray-800
|
|
64
|
+
&.draft
|
|
65
|
+
color: $gray-600
|
|
66
|
+
|
|
67
|
+
#cms-uploader ul.list .file-path
|
|
68
|
+
color: $gray-600
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Loaded before Bootstrap so forms, alerts, badges, and pagination share the palette.
|
|
2
|
+
$harbor-navy: #172b3a
|
|
3
|
+
$harbor-teal: #0f766e
|
|
4
|
+
$harbor-hover: #0b5e57
|
|
5
|
+
$harbor-pressed: #094c47
|
|
6
|
+
$harbor-tint: #e0f2ef
|
|
7
|
+
$harbor-gold: #d5a34a
|
|
8
|
+
$harbor-nav-text: #bfd0dc
|
|
9
|
+
|
|
10
|
+
$gray-100: #f3f7fa
|
|
11
|
+
$gray-200: #e4ecf1
|
|
12
|
+
$gray-300: #cbd7e0
|
|
13
|
+
$gray-400: #91aab9
|
|
14
|
+
$gray-500: #718999
|
|
15
|
+
$gray-600: #526777
|
|
16
|
+
$gray-700: #385364
|
|
17
|
+
$gray-800: #243746
|
|
18
|
+
$gray-900: $harbor-navy
|
|
19
|
+
|
|
20
|
+
$primary: $harbor-teal
|
|
21
|
+
$secondary: $harbor-teal
|
|
22
|
+
$success: #26734d
|
|
23
|
+
$info: #246b8c
|
|
24
|
+
$warning: $harbor-gold
|
|
25
|
+
$danger: #b23a48
|
|
26
|
+
$dark: $harbor-navy
|
|
27
|
+
$light: $gray-100
|
|
28
|
+
$body-color: $gray-800
|
|
29
|
+
$body-bg: #ffffff
|
|
30
|
+
$link-color: $harbor-teal
|
|
31
|
+
$link-hover-color: $harbor-hover
|
|
32
|
+
$input-border-color: $gray-400
|
|
33
|
+
$input-focus-border-color: $harbor-teal
|
|
34
|
+
$input-focus-box-shadow: 0 0 0 .2rem rgba($harbor-teal, .2)
|
|
35
|
+
$custom-select-focus-border-color: $harbor-teal
|
|
36
|
+
$custom-select-focus-box-shadow: $input-focus-box-shadow
|
|
@@ -8,13 +8,13 @@ class Comfy::Admin::Cms::PagesController < Comfy::Admin::Cms::BaseController
|
|
|
8
8
|
|
|
9
9
|
include ::Comfy::ReorderAction
|
|
10
10
|
|
|
11
|
-
helper_method :page_branch_open
|
|
11
|
+
helper_method :page_branch_open?, :page_publicly_visible?, :descendant_publication_states
|
|
12
12
|
|
|
13
13
|
self.reorder_action_resource = ::Comfy::Cms::Page
|
|
14
14
|
|
|
15
15
|
before_action :check_for_layouts, only: %i[new edit]
|
|
16
16
|
before_action :build_page, only: %i[new create]
|
|
17
|
-
before_action :load_page, only: %i[edit update destroy publish_children unpublish_children]
|
|
17
|
+
before_action :load_page, only: %i[edit update destroy toggle_publication publish_children unpublish_children]
|
|
18
18
|
|
|
19
19
|
before_action :authorize
|
|
20
20
|
before_action :assign_page_params, only: :update
|
|
@@ -118,6 +118,13 @@ class Comfy::Admin::Cms::PagesController < Comfy::Admin::Cms::BaseController
|
|
|
118
118
|
head :not_found
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
+
def toggle_publication
|
|
122
|
+
@page.update!(is_published: !@page.is_published?)
|
|
123
|
+
status = @page.is_published? ? 'published' : 'unpublished'
|
|
124
|
+
flash[:success] = I18n.t("comfy.admin.cms.pages.#{status}", default: "Page #{status}")
|
|
125
|
+
redirect_to comfy_admin_cms_site_pages_path(@site, params.permit(:q, :categories))
|
|
126
|
+
end
|
|
127
|
+
|
|
121
128
|
def publish_children
|
|
122
129
|
update_children_publication(true, :children_published)
|
|
123
130
|
end
|
|
@@ -128,12 +135,27 @@ class Comfy::Admin::Cms::PagesController < Comfy::Admin::Cms::BaseController
|
|
|
128
135
|
|
|
129
136
|
protected
|
|
130
137
|
|
|
138
|
+
# Query one tree level at a time; mixed flags already enable both actions.
|
|
139
|
+
def descendant_publication_states(page)
|
|
140
|
+
states = []
|
|
141
|
+
parent_ids = [page.id]
|
|
142
|
+
while parent_ids.present? && states.size < 2
|
|
143
|
+
descendants = @site.pages.where(parent_id: parent_ids).pluck(:id, :is_published)
|
|
144
|
+
states |= descendants.map(&:last)
|
|
145
|
+
parent_ids = descendants.map(&:first)
|
|
146
|
+
end
|
|
147
|
+
states
|
|
148
|
+
end
|
|
149
|
+
|
|
131
150
|
def update_children_publication(is_published, message)
|
|
132
151
|
descendant_ids = @page.descendants.map(&:id)
|
|
133
|
-
@
|
|
134
|
-
.
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
@page.class.transaction do
|
|
153
|
+
@site.pages
|
|
154
|
+
.where(id: descendant_ids)
|
|
155
|
+
.update_all(is_published: is_published, updated_at: Time.current)
|
|
156
|
+
@page.clear_site_content_cache!
|
|
157
|
+
end
|
|
158
|
+
default = is_published ? 'Descendant pages published' : 'Descendant pages unpublished'
|
|
137
159
|
flash[:success] = I18n.t("comfy.admin.cms.pages.#{message}", default: default)
|
|
138
160
|
redirect_to action: :edit, id: @page
|
|
139
161
|
end
|
|
@@ -182,6 +204,20 @@ protected
|
|
|
182
204
|
pages_by_parent
|
|
183
205
|
end
|
|
184
206
|
|
|
207
|
+
# Reuse loaded tree nodes and memoize shared ancestors for filtered results.
|
|
208
|
+
def page_publicly_visible?(page)
|
|
209
|
+
@page_visibility ||= {}
|
|
210
|
+
return @page_visibility[page.id] if @page_visibility.key?(page.id)
|
|
211
|
+
|
|
212
|
+
@visibility_pages ||= (Array(@pages) + [@page] + (@pages_by_parent || {}).values.flatten)
|
|
213
|
+
.compact.index_by(&:id)
|
|
214
|
+
@page_visibility[page.id] = page.is_published? && (
|
|
215
|
+
page.parent_id.nil? || page_publicly_visible?(
|
|
216
|
+
@visibility_pages[page.parent_id] ||= @site.pages.find(page.parent_id)
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
end
|
|
220
|
+
|
|
185
221
|
def page_branch_open?(page)
|
|
186
222
|
page.root? || page_tree_session.member?(page.id.to_s)
|
|
187
223
|
end
|
|
@@ -27,6 +27,9 @@ class Comfy::Cms::Page < ActiveRecord::Base
|
|
|
27
27
|
:assign_full_path
|
|
28
28
|
before_create :assign_position
|
|
29
29
|
after_save :sync_child_full_paths!
|
|
30
|
+
after_save :clear_site_content_cache!,
|
|
31
|
+
if: -> { is_published_previously_changed? || parent_id_previously_changed? }
|
|
32
|
+
after_destroy :clear_site_content_cache!
|
|
30
33
|
after_find :unescape_slug_and_path
|
|
31
34
|
|
|
32
35
|
# -- Validations -------------------------------------------------------------
|
|
@@ -89,6 +92,16 @@ class Comfy::Cms::Page < ActiveRecord::Base
|
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
# -- Instance Methods --------------------------------------------------------
|
|
95
|
+
def published_with_ancestors?
|
|
96
|
+
is_published? && ancestors.all?(&:is_published?)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def clear_site_content_cache!
|
|
100
|
+
pages = Comfy::Cms::Page.where(site_id: site_id)
|
|
101
|
+
pages.update_all(content_cache: nil)
|
|
102
|
+
Comfy::Cms::Translation.where(page_id: pages.select(:id)).update_all(content_cache: nil)
|
|
103
|
+
end
|
|
104
|
+
|
|
92
105
|
# For previewing purposes sometimes we need to have full_path set. This
|
|
93
106
|
# full path take care of the pages and its childs but not of the site path
|
|
94
107
|
def full_path
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
- has_children = children.present? || page.children_count.to_i.positive?
|
|
6
6
|
- has_siblings = siblings.size > 1
|
|
7
7
|
- branch_open = page_branch_open?(page)
|
|
8
|
+
- publicly_visible = page_publicly_visible?(page)
|
|
8
9
|
|
|
9
10
|
%li{id: dom_id(page), data: {id: page.id}}
|
|
10
11
|
.row
|
|
@@ -25,17 +26,22 @@
|
|
|
25
26
|
|
|
26
27
|
.item-content
|
|
27
28
|
.item-title
|
|
28
|
-
- published_css_class =
|
|
29
|
+
- published_css_class = publicly_visible ? "published" : "draft"
|
|
29
30
|
= link_to page.label, edit_comfy_admin_cms_site_page_path(@site, page), class: published_css_class
|
|
30
31
|
.item-meta
|
|
31
32
|
= link_to page.url, page.url, target: "_blank"
|
|
33
|
+
- if page.is_published? && !publicly_visible
|
|
34
|
+
.publication-status= t('.hidden_by_ancestor', default: 'Hidden by unpublished ancestor')
|
|
32
35
|
|
|
33
36
|
.col-md-2.item-categories.d-flex.align-items-center
|
|
34
37
|
= render "comfy/admin/cms/categories/categories", object: page
|
|
35
38
|
|
|
36
39
|
.col-md-4.d-flex.align-items-center.justify-content-md-end
|
|
37
40
|
.btn-group.btn-group-sm
|
|
38
|
-
=
|
|
41
|
+
- publication_label = page.is_published? ? t(".unpublish", default: "Unpublish") : t(".publish", default: "Publish")
|
|
42
|
+
- publication_path = toggle_publication_comfy_admin_cms_site_page_path(@site, page, q: params[:q], categories: params[:categories])
|
|
43
|
+
= link_to publication_label, publication_path, method: :patch, class: "btn btn-outline-secondary"
|
|
44
|
+
= link_to t(".add_child_page"), new_comfy_admin_cms_site_page_path(@site, parent_id: page.id), class: "btn btn-outline-secondary text-nowrap"
|
|
39
45
|
= link_to t(".edit"), edit_comfy_admin_cms_site_page_path(@site, page), class: "btn btn-outline-secondary"
|
|
40
46
|
- unless page.root?
|
|
41
47
|
= link_to t(".delete"), comfy_admin_cms_site_page_path(@site, page), method: :delete, data: {confirm: t('.are_you_sure')}, class: "btn btn-danger"
|
|
@@ -6,9 +6,27 @@
|
|
|
6
6
|
.page-header.d-flex.justify-content-between.align-items-center
|
|
7
7
|
%h2= t('.title')
|
|
8
8
|
- if @page.children.exists?
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
- publication_states = descendant_publication_states(@page)
|
|
10
|
+
.dropdown
|
|
11
|
+
%button#child-pages-menu.btn.btn-sm.btn-outline-secondary.dropdown-toggle.text-nowrap{type: 'button', data: {toggle: 'dropdown'}, aria: {haspopup: 'true', expanded: 'false', controls: 'child-pages-actions'}}
|
|
12
|
+
= t('.child_pages', default: 'Child pages')
|
|
13
|
+
#child-pages-actions.dropdown-menu.dropdown-menu-right{aria: {labelledby: 'child-pages-menu'}}
|
|
14
|
+
- if publication_states.include?(false)
|
|
15
|
+
= link_to t('.publish_descendants', default: 'Publish descendants'), publish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.publish_descendants_confirmation', default: 'Publish all descendant pages?')}, class: 'dropdown-item'
|
|
16
|
+
- else
|
|
17
|
+
%button.dropdown-item.disabled{type: 'button', disabled: true, aria: {disabled: 'true'}}= t('.publish_descendants', default: 'Publish descendants')
|
|
18
|
+
- if publication_states.include?(true)
|
|
19
|
+
= link_to t('.unpublish_descendants', default: 'Unpublish descendants'), unpublish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.unpublish_descendants_confirmation', default: 'Unpublish all descendant pages?')}, class: 'dropdown-item'
|
|
20
|
+
- else
|
|
21
|
+
%button.dropdown-item.disabled{type: 'button', disabled: true, aria: {disabled: 'true'}}= t('.unpublish_descendants', default: 'Unpublish descendants')
|
|
22
|
+
|
|
23
|
+
- unless @page.published_with_ancestors?
|
|
24
|
+
.alert.alert-info.publication-status{role: 'status'}
|
|
25
|
+
- if @page.is_published?
|
|
26
|
+
= t('.hidden_by_ancestor', default: 'Hidden by unpublished ancestor. Publish its ancestors to make this page visible.')
|
|
27
|
+
- else
|
|
28
|
+
= t('.unpublished_notice', default: 'This page is unpublished.')
|
|
29
|
+
= t('.branch_visibility_notice', default: 'Descendants are visible only when they and all their ancestors are published. Their publication settings are preserved when an ancestor is unpublished.')
|
|
12
30
|
|
|
13
31
|
- draft_data = cms_draft_form_data('site', @site.id, 'page', @page.id, record: @page)
|
|
14
32
|
= comfy_form_with model: @page, scope: :page, url: {action: :update}, html: {multipart: true, data: draft_data} do |form|
|
data/config/locales/en.yml
CHANGED
|
@@ -125,8 +125,8 @@ en:
|
|
|
125
125
|
creation_failure: Failed to create page
|
|
126
126
|
updated: Page, siblings, and parent updated
|
|
127
127
|
update_failure: Failed to update page
|
|
128
|
-
children_published:
|
|
129
|
-
children_unpublished:
|
|
128
|
+
children_published: Descendant pages published
|
|
129
|
+
children_unpublished: Descendant pages unpublished
|
|
130
130
|
deleted: Page deleted, siblings, and parent updated
|
|
131
131
|
not_found: Page not found
|
|
132
132
|
layout_not_found: No Layouts found. Please create one.
|
|
@@ -24,16 +24,21 @@ class ComfyMiddleSeat::Content::Tags::Breadcrumbs < ComfyMiddleSeat::Content::Ta
|
|
|
24
24
|
@style = ''
|
|
25
25
|
@style = "<style>#breadcrumbs {#{@locals['style']}}</style>" if @locals['style']
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
page = context.is_a?(Comfy::Cms::Translation) ? context.page : context
|
|
28
|
+
@visible = Rails.env.development? || page.published_with_ancestors?
|
|
29
|
+
@links = ''
|
|
30
|
+
return unless @visible
|
|
30
31
|
|
|
32
|
+
@links = '<div id="breadcrumbs">'
|
|
33
|
+
page.ancestors.reverse.each do |a|
|
|
31
34
|
@links += "<a href=#{a.url(relative: true)}>#{a.label}</a> » "
|
|
32
35
|
end
|
|
33
36
|
@links += "#{context.label}</div>"
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
def content
|
|
40
|
+
return '' unless @visible
|
|
41
|
+
|
|
37
42
|
"#{@style}#{@links}"
|
|
38
43
|
end
|
|
39
44
|
end
|
|
@@ -27,15 +27,20 @@ class ComfyMiddleSeat::Content::Tags::Children < ComfyMiddleSeat::Content::Tag
|
|
|
27
27
|
@exclude = []
|
|
28
28
|
@exclude = @locals['exclude'].split(',').map(&:strip) if @locals['exclude']
|
|
29
29
|
@list = ''
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
page = context.is_a?(Comfy::Cms::Translation) ? context.page : context
|
|
31
|
+
preview = Rails.env.development?
|
|
32
|
+
@visible = preview || page.published_with_ancestors?
|
|
33
|
+
@page_children = []
|
|
34
|
+
return unless @visible
|
|
35
|
+
|
|
36
|
+
@page_children = page.children.order(:position).to_ary
|
|
37
|
+
@page_children.select!(&:is_published?) unless preview
|
|
35
38
|
@page_children.delete_if { |child| @exclude.include? child.slug }
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
def content
|
|
42
|
+
return '' unless @visible
|
|
43
|
+
|
|
39
44
|
if @page_children.any?
|
|
40
45
|
@list = "<ul id=\"children\">\n"
|
|
41
46
|
@page_children.each do |c|
|
|
@@ -29,28 +29,32 @@ class ComfyMiddleSeat::Content::Tags::Siblings < ComfyMiddleSeat::Content::Tag
|
|
|
29
29
|
@exclude = []
|
|
30
30
|
@exclude = @locals['exclude'].split(',') if @locals['exclude']
|
|
31
31
|
@links = ''
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
@page = context.is_a?(Comfy::Cms::Translation) ? context.page : context
|
|
33
|
+
preview = Rails.env.development?
|
|
34
|
+
@visible = preview || @page.published_with_ancestors?
|
|
35
|
+
@sibs = []
|
|
36
|
+
return unless @visible
|
|
37
|
+
|
|
38
|
+
@sibs = @page.self_and_siblings.order(:position).to_ary
|
|
39
|
+
@sibs.select!(&:is_published?) unless preview
|
|
37
40
|
@sibs.delete_if { |sib| @exclude.include? sib.slug }
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
def content
|
|
44
|
+
return '' unless @visible
|
|
45
|
+
|
|
41
46
|
if @sibs.count > 1
|
|
42
47
|
@links = '<div id="siblings">'
|
|
43
48
|
prevp = false
|
|
44
49
|
@sibs.each do |sib|
|
|
45
50
|
sib_idx = @sibs.index(sib)
|
|
46
|
-
next if sib.slug ==
|
|
47
|
-
next
|
|
48
|
-
next unless @sibs.index(context) # current page is excluded
|
|
51
|
+
next if sib.slug == @page.slug
|
|
52
|
+
next unless @sibs.index(@page) # current page is excluded
|
|
49
53
|
|
|
50
|
-
if sib_idx == @sibs.index(
|
|
54
|
+
if sib_idx == @sibs.index(@page) - 1
|
|
51
55
|
@links += "<a href=#{sib.url(relative: true)}>#{sib.label}</a> « <em>Previous</em> • "
|
|
52
56
|
prevp = true
|
|
53
|
-
elsif sib_idx == @sibs.index(
|
|
57
|
+
elsif sib_idx == @sibs.index(@page) + 1
|
|
54
58
|
@links += '•' unless prevp
|
|
55
59
|
@links += "<em>Next</em> » <a href=#{sib.url(relative: true)}>#{sib.label}</a>"
|
|
56
60
|
end
|
data/package-lock.json
CHANGED
|
@@ -868,8 +868,7 @@
|
|
|
868
868
|
"version": "3.7.1",
|
|
869
869
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
|
870
870
|
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
|
871
|
-
"license": "MIT"
|
|
872
|
-
"peer": true
|
|
871
|
+
"license": "MIT"
|
|
873
872
|
},
|
|
874
873
|
"node_modules/micromatch": {
|
|
875
874
|
"version": "4.0.8",
|
|
@@ -918,7 +917,6 @@
|
|
|
918
917
|
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
|
919
918
|
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
|
920
919
|
"license": "MIT",
|
|
921
|
-
"peer": true,
|
|
922
920
|
"funding": {
|
|
923
921
|
"type": "opencollective",
|
|
924
922
|
"url": "https://opencollective.com/popperjs"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: comfy_middle_seat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0
|
|
4
|
+
version: 4.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oleg Khabarov
|
|
@@ -306,6 +306,8 @@ files:
|
|
|
306
306
|
- app/assets/stylesheets/comfy/admin/cms/base.sass
|
|
307
307
|
- app/assets/stylesheets/comfy/admin/cms/codemirror_overrides.sass
|
|
308
308
|
- app/assets/stylesheets/comfy/admin/cms/custom.sass
|
|
309
|
+
- app/assets/stylesheets/comfy/admin/cms/harbor.sass
|
|
310
|
+
- app/assets/stylesheets/comfy/admin/cms/harbor_variables.sass
|
|
309
311
|
- app/assets/stylesheets/comfy/admin/cms/redactor_overrides.sass
|
|
310
312
|
- app/assets/stylesheets/comfy/vendor/bootstrap/_alert.scss
|
|
311
313
|
- app/assets/stylesheets/comfy/vendor/bootstrap/_badge.scss
|