Phase 5: ship the catalog ActiveAdmin resources from the engine
- the 7 catalog admin files (softwares, releases, external_links, platform_links, images, files page, downloads) move to the engine's app/admin; the host ActiveAdmin instance loads them via ActiveAdmin.application.load_paths (single admin, URLs unchanged) - engine initializers: Zeitwerk ignore for app/admin (production eager load) and load_paths + watchable_dirs registration, guarded by defined?(ActiveAdmin) so the admin-less dummy app boots - images admin reads image owners from WarpEngine.config.image_owners; the host registers the Member owner in config/initializers/warp_engine.rb; the interim ImageUsage registry is gone - fix: SoftwareImage.distinct.pluck clashed with its order(:position) default scope on MySQL (unscope(:order)) — introduced in phase 0, caught by the first authenticated /admin/images smoke test - files page: download links use the public /file/ URL instead of the raw container path; the picker's stored path comes from config Verified: both suites green, zeitwerk:check (production) clean, JSON baselines intact, authenticated admin smoke test on every page incl. the 3-level nested software form and Files picker mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
# A katalóguson kívüli modellek regisztrálják ide, hogy mely Image rekordokat
|
||||
# használják. A leendő WarpEngine.config.image_owners hook elődje: az admin
|
||||
# Images oldal In use/Orphan logikája ezen keresztül marad domain-független.
|
||||
#
|
||||
# Owner kontraktus:
|
||||
# image_ids: -> { Array<Integer> } — az owner által használt image id-k
|
||||
# usage_label: ->(image) { String vagy nil } — megjelenítendő címke, ha használja
|
||||
module ImageUsage
|
||||
Owner = Struct.new(:label, :image_ids, :usage_label, keyword_init: true)
|
||||
|
||||
def self.owners
|
||||
@owners ||= []
|
||||
end
|
||||
|
||||
def self.reset!
|
||||
@owners = []
|
||||
end
|
||||
|
||||
def self.register(label:, image_ids:, usage_label:)
|
||||
owners << Owner.new(label:, image_ids:, usage_label:)
|
||||
end
|
||||
|
||||
def self.used_image_ids
|
||||
owners.flat_map { |o| o.image_ids.call }
|
||||
end
|
||||
|
||||
def self.usage_labels_for(image)
|
||||
owners.filter_map { |o| o.usage_label.call(image) }
|
||||
end
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
# TTG-specifikus image-használók regisztrációja. to_prepare: reload után is újrafut.
|
||||
Rails.application.config.to_prepare do
|
||||
ImageUsage.reset!
|
||||
ImageUsage.register(
|
||||
label: "member",
|
||||
image_ids: -> { Member.where.not(image_id: nil).distinct.pluck(:image_id) },
|
||||
usage_label: ->(image) { "member" if Member.where(image_id: image.id).exists? }
|
||||
)
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
# WarpEngine host-konfiguráció. to_prepare: reload után is újrafut, ezért
|
||||
# értékadás (nem <<), hogy idempotens legyen.
|
||||
Rails.application.config.to_prepare do
|
||||
WarpEngine.configure do |c|
|
||||
c.image_owners = [
|
||||
{
|
||||
label: "member",
|
||||
image_ids: -> { Member.where.not(image_id: nil).distinct.pluck(:image_id) },
|
||||
usage_label: ->(image) { "member" if Member.where(image_id: image.id).exists? }
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
@@ -147,7 +147,7 @@ ActiveAdmin.register_page "Files" do
|
||||
|
||||
# Download (files only)
|
||||
if entry[:type] != :directory
|
||||
a "⬇️", href: "/softwares/#{entry[:path]}", class: "fm-icon-btn", title: "Download", download: entry[:name]
|
||||
a "⬇️", href: "/file/#{entry[:path]}", class: "fm-icon-btn", title: "Download", download: entry[:name]
|
||||
end
|
||||
|
||||
# Rename
|
||||
@@ -165,7 +165,7 @@ ActiveAdmin.register_page "Files" do
|
||||
|
||||
# Picker mode: Select button
|
||||
if picker_mode
|
||||
abs_path = "/softwares/#{entry[:path]}"
|
||||
abs_path = File.join(WarpEngine.config.file_container_path, entry[:path])
|
||||
a "Select", href: "#", class: "fm-btn fm-btn-select",
|
||||
onclick: "var inp=window.parent.document.getElementById('#{j picker_field}');if(inp){inp.value='#{j abs_path}';}var ov=window.parent.document.querySelector('.fm-modal-overlay');if(ov){ov.remove();window.parent.document.body.style.overflow='';}return false;"
|
||||
end
|
||||
@@ -3,7 +3,12 @@ ActiveAdmin.register WarpEngine::Image, as: "Image" do
|
||||
|
||||
menu priority: 5, label: "🖼️ Images"
|
||||
|
||||
used_ids = -> { WarpEngine::SoftwareImage.distinct.pluck(:image_id) + ImageUsage.used_image_ids }
|
||||
# SoftwareImage a natív használó; a hoston regisztrált image_owners
|
||||
# (WarpEngine.config) további használókat adhat hozzá (pl. TTG Member).
|
||||
used_ids = -> {
|
||||
WarpEngine::SoftwareImage.unscope(:order).distinct.pluck(:image_id) +
|
||||
WarpEngine.config.image_owners.flat_map { |o| o[:image_ids].call }
|
||||
}
|
||||
|
||||
scope :all, default: true
|
||||
scope("In use") { |scope| scope.where(id: used_ids.call) }
|
||||
@@ -31,7 +36,7 @@ ActiveAdmin.register WarpEngine::Image, as: "Image" do
|
||||
column(:usage) do |img|
|
||||
uses = []
|
||||
uses << "#{img.software_images.size} software(s)" if img.software_images.any?
|
||||
uses.concat(ImageUsage.usage_labels_for(img))
|
||||
uses.concat(WarpEngine.config.image_owners.filter_map { |o| o[:usage_label].call(img) })
|
||||
uses.any? ? uses.join(", ") : status_tag("orphan", class: "warning")
|
||||
end
|
||||
column :created_at
|
||||
@@ -1,5 +1,22 @@
|
||||
module WarpEngine
|
||||
class Engine < ::Rails::Engine
|
||||
isolate_namespace WarpEngine
|
||||
|
||||
# Az app/admin fájlok ActiveAdmin DSL-t tartalmaznak, nem definiálnak a
|
||||
# fájlnévnek megfelelő konstansokat — a Zeitwerk (eager load) nem nyúlhat hozzájuk.
|
||||
initializer "warp_engine.ignore_admin_dir", before: :setup_main_autoloader do
|
||||
Rails.autoloaders.main.ignore(Engine.root.join("app/admin"))
|
||||
end
|
||||
|
||||
# Az admin erőforrásokat a HOST ActiveAdmin példánya tölti be; az engine csak
|
||||
# regisztrálja a saját app/admin könyvtárát. Auth/téma/route-ok a host dolga.
|
||||
initializer "warp_engine.active_admin" do |app|
|
||||
if defined?(ActiveAdmin)
|
||||
admin_dir = Engine.root.join("app/admin").to_s
|
||||
ActiveAdmin.application.load_paths << admin_dir
|
||||
# dev módban az engine admin-fájljainak szerkesztése is triggerel reloadot
|
||||
app.config.watchable_dirs[admin_dir] = [ :rb ]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user