summaryrefslogtreecommitdiff
path: root/app/models/node.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-11 23:43:02 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-11 23:43:02 +0200
commit92c394b43a0603743b914c6298aab986805ca990 (patch)
tree39308770fbae5558d98a7def3d25802ed8083d81 /app/models/node.rb
parent47beb3fe6ed6fdb75c2dd3a55362ad1aba3bbc3b (diff)
Add drafts/recent/mine/chapters admin node views
Four NodesController actions -- drafts, recent, mine, chapters -- each building its own base scope, sharing one private method (index_matching) for search narrowing and pagination. Wizard rewrite to link into these instead of rendering its own tables is a separate, later step. Node.editor_search backs the shared "q" narrowing: an ILIKE substring match against title/abstract on whichever of head or draft is present, splitting the term on whitespace and requiring every word to match somewhere independently, not as one phrase, since real words can end up separated by markup in the underlying HTML. Deliberately separate from Node.search, the public content search, which stays tsvector-based and head-only. chapters generalizes into /admin/nodes/tags/:tags for an arbitrary tag list (OR'd, not AND'd), sharing the controller action but rendering its own template rather than branching inside one view.
Diffstat (limited to 'app/models/node.rb')
-rw-r--r--app/models/node.rb22
1 files changed, 22 insertions, 0 deletions
diff --git a/app/models/node.rb b/app/models/node.rb
index 9cb4840..24f3cd0 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -345,6 +345,28 @@ class Node < ApplicationRecord
345 .distinct 345 .distinct
346 end 346 end
347 347
348 # This one is for admin-only views, where finding a draft is the point.
349 # Substring match on whichever of head/draft is present.
350 def self.editor_search(term)
351 words = term.to_s.split(/\s+/).reject(&:blank?)
352 return none if words.empty?
353
354 conditions = []
355 binds = {}
356
357 words.each_with_index do |word, i|
358 key = "term#{i}"
359 binds[key.to_sym] = "%#{sanitize_sql_like(word)}%"
360 conditions << "(head_translations.title ILIKE :#{key} OR head_translations.abstract ILIKE :#{key} " \
361 "OR draft_translations.title ILIKE :#{key} OR draft_translations.abstract ILIKE :#{key})"
362 end
363
364 joins("LEFT JOIN page_translations head_translations ON head_translations.page_id = nodes.head_id")
365 .joins("LEFT JOIN page_translations draft_translations ON draft_translations.page_id = nodes.draft_id")
366 .where(conditions.join(" AND "), binds)
367 .distinct
368 end
369
348 protected 370 protected
349 def lock_for! current_user 371 def lock_for! current_user
350 self.lock_owner = current_user 372 self.lock_owner = current_user