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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5a4db65127e75cd26c7579614c4a0b7d9911cdc42c69642c23713a54f646c6e
4
- data.tar.gz: c715bde4f3d50f585f996cb6279a07b317e6cbdcd67fa9cdb2ffcc981492bb62
3
+ metadata.gz: 4d22803345977cfaec60811a1301ce6ad6ada6ab242d41c5c390b4c5aa6da645
4
+ data.tar.gz: 537cd86f6e7685b7a771dcd80e5c0c1bc01544f92e88fc3939bc956bc2a08db2
5
5
  SHA512:
6
- metadata.gz: e4a9cdd0915e2bc45dcb9f58d35711566972838f16569e6b64d9408c9265974d4609f916a0aa5911dc6a872b183003023b3372c6f8247100ede1528c3aec6ac8
7
- data.tar.gz: fb6647ee01f1a0b907e314b379113100c3cc0062aa0baa91bbfa9f1b909539f1e8114719874e032d863b6c5e1f3ce36e98f6277bfd7ec7155fff2f3667089512
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.1...master
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 depend on who is sitting to your right and left.
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
- - Controls to publish or unpublish child pages together.
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.
@@ -6,6 +6,7 @@ ujs.start();
6
6
 
7
7
  import "bootstrap/js/src/tab";
8
8
  import "bootstrap/js/src/collapse";
9
+ import "bootstrap/js/src/dropdown";
9
10
 
10
11
  import "../../vendor/diff/diff_match_patch.min";
11
12
  import "../../vendor/diff/pretty_text_diff";
@@ -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
- @site.pages
134
- .where(id: descendant_ids)
135
- .update_all(is_published: is_published, updated_at: Time.current)
136
- default = is_published ? 'Child pages published' : 'Child pages unpublished'
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
@@ -80,6 +80,8 @@ protected
80
80
  @cms_site.pages.published.find_by!(full_path: full_path)
81
81
  end
82
82
 
83
+ return nil unless Rails.env == 'development' || @cms_page.published_with_ancestors?
84
+
83
85
  @cms_page.translate!
84
86
  @cms_layout = @cms_page.layout
85
87
 
@@ -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 = page.is_published? ? "published" : "draft"
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
- = link_to t(".add_child_page"), new_comfy_admin_cms_site_page_path(@site, parent_id: page.id), class: "btn btn-outline-secondary"
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
- .btn-group.btn-group-sm
10
- = link_to t('.publish_children', default: 'Publish children'), publish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.publish_children_confirmation', default: 'Publish all child pages?')}, class: 'btn btn-success'
11
- = link_to t('.unpublish_children', default: 'Unpublish children'), unpublish_children_comfy_admin_cms_site_page_path(@site, @page), method: :patch, data: {confirm: t('.unpublish_children_confirmation', default: 'Unpublish all child pages?')}, class: 'btn btn-outline-secondary'
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|
@@ -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: Child pages published
129
- children_unpublished: Child pages 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
- @links = '<div id="breadcrumbs">'
28
- context.ancestors.reverse.each do |a|
29
- next if Rails.env == 'production' && !a.is_published
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> &raquo; "
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
- # ActiveRecord_Associations_CollectionProxy
31
- @page_children = context.children.order(:position).to_ary
32
- unless Rails.env == 'development'
33
- @page_children.delete_if { |child| !child.is_published }
34
- end
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
- # ActiveRecord_Associations_CollectionProxy
33
- @sibs = context.self_and_siblings.order(:position).to_ary
34
- unless Rails.env == 'development'
35
- @sibs.delete_if { |sib| !sib.is_published }
36
- end
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 == context.slug
47
- next if Rails.env == 'production' && !sib.is_published
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(context) - 1
54
+ if sib_idx == @sibs.index(@page) - 1
51
55
  @links += "<a href=#{sib.url(relative: true)}>#{sib.label}</a> &laquo;&nbsp;<em>Previous</em> &bull; "
52
56
  prevp = true
53
- elsif sib_idx == @sibs.index(context) + 1
57
+ elsif sib_idx == @sibs.index(@page) + 1
54
58
  @links += '&bull;' unless prevp
55
59
  @links += "<em>Next</em>&nbsp;&raquo; <a href=#{sib.url(relative: true)}>#{sib.label}</a>"
56
60
  end
@@ -36,6 +36,7 @@ module ComfyMiddleSeat::Routing
36
36
  concerns :with_revisions, controller: 'revisions/page'
37
37
 
38
38
  get :toggle_branch, on: :member
39
+ patch :toggle_publication, on: :member
39
40
  patch :publish_children, on: :member
40
41
  patch :unpublish_children, on: :member
41
42
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ComfyMiddleSeat
4
- VERSION = '4.0.2'
4
+ VERSION = '4.1.0'
5
5
  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.2
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