iron-cms 0.6.0 → 0.7.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/app/assets/builds/iron.css +668 -388
- data/app/assets/tailwind/iron/application.css +1 -0
- data/app/assets/tailwind/iron/components/button.css +0 -7
- data/app/assets/tailwind/iron/components/checkbox.css +21 -0
- data/app/assets/tailwind/iron/components/form.css +1 -1
- data/app/assets/tailwind/iron/lexxy.css +165 -51
- data/app/controllers/iron/account/exports_controller.rb +26 -0
- data/app/controllers/iron/account/imports_controller.rb +27 -0
- data/app/helpers/iron/form_builder.rb +7 -0
- data/app/jobs/iron/export_job.rb +9 -0
- data/app/jobs/iron/import_job.rb +9 -0
- data/app/models/concerns/iron/broadcastable.rb +9 -0
- data/app/models/concerns/iron/processable.rb +34 -0
- data/app/models/iron/account/export.rb +86 -0
- data/app/models/iron/account/import.rb +208 -0
- data/app/models/iron/block_definition/exportable.rb +14 -0
- data/app/models/iron/block_definition/importable.rb +27 -0
- data/app/models/iron/block_definition.rb +1 -1
- data/app/models/iron/content_type/exportable.rb +20 -0
- data/app/models/iron/content_type/importable.rb +32 -0
- data/app/models/iron/content_type.rb +1 -1
- data/app/models/iron/current.rb +6 -3
- data/app/models/iron/entry/exportable.rb +49 -0
- data/app/models/iron/entry/importable.rb +181 -0
- data/app/models/iron/entry.rb +1 -1
- data/app/models/iron/field.rb +9 -1
- data/app/models/iron/field_definition/exportable.rb +23 -0
- data/app/models/iron/field_definition/importable.rb +39 -0
- data/app/models/iron/field_definition.rb +1 -1
- data/app/models/iron/fields/block.rb +18 -0
- data/app/models/iron/fields/block_list.rb +8 -0
- data/app/models/iron/fields/boolean.rb +4 -0
- data/app/models/iron/fields/date.rb +4 -0
- data/app/models/iron/fields/file.rb +16 -0
- data/app/models/iron/fields/number.rb +4 -0
- data/app/models/iron/fields/reference.rb +4 -0
- data/app/models/iron/fields/reference_list.rb +4 -0
- data/app/models/iron/fields/rich_text_area.rb +32 -0
- data/app/models/iron/fields/text_area.rb +4 -0
- data/app/models/iron/fields/text_field.rb +4 -0
- data/app/models/iron/user.rb +2 -0
- data/app/views/iron/account/exports/index.html.erb +43 -0
- data/app/views/iron/account/exports/new.html.erb +39 -0
- data/app/views/iron/account/exports/show.html.erb +40 -0
- data/app/views/iron/account/imports/index.html.erb +43 -0
- data/app/views/iron/account/imports/new.html.erb +52 -0
- data/app/views/iron/account/imports/show.html.erb +37 -0
- data/app/views/iron/content_types/index.html.erb +1 -8
- data/app/views/iron/entries/fields/_file.html.erb +3 -3
- data/app/views/iron/settings/show.html.erb +4 -11
- data/config/routes.rb +3 -9
- data/db/migrate/20251209103109_create_iron_account_exports.rb +13 -0
- data/db/migrate/20251209103110_create_iron_account_imports.rb +13 -0
- data/lib/iron/version.rb +1 -1
- data/lib/iron.rb +1 -1
- metadata +40 -28
- data/app/controllers/iron/contents_controller.rb +0 -33
- data/app/controllers/iron/schemas_controller.rb +0 -32
- data/app/models/concerns/iron/csv_serializable.rb +0 -28
- data/app/models/iron/archive.rb +0 -69
- data/app/models/iron/block_definition/portable.rb +0 -20
- data/app/models/iron/content_export.rb +0 -73
- data/app/models/iron/content_import/entry_builder.rb +0 -80
- data/app/models/iron/content_import/entry_snapshot.rb +0 -23
- data/app/models/iron/content_import/field_reconstructor.rb +0 -276
- data/app/models/iron/content_import/field_snapshot.rb +0 -33
- data/app/models/iron/content_import/registry.rb +0 -32
- data/app/models/iron/content_import/session.rb +0 -89
- data/app/models/iron/content_import.rb +0 -15
- data/app/models/iron/content_type/portable.rb +0 -30
- data/app/models/iron/entry/portable.rb +0 -35
- data/app/models/iron/field/portable.rb +0 -33
- data/app/models/iron/field_definition/portable.rb +0 -42
- data/app/models/iron/schema_archive.rb +0 -71
- data/app/models/iron/schema_exporter.rb +0 -15
- data/app/models/iron/schema_importer/import_strategy.rb +0 -59
- data/app/models/iron/schema_importer/merge_strategy.rb +0 -52
- data/app/models/iron/schema_importer/replace_strategy.rb +0 -51
- data/app/models/iron/schema_importer/safe_strategy.rb +0 -55
- data/app/models/iron/schema_importer.rb +0 -108
- data/app/views/iron/contents/new.html.erb +0 -34
- data/app/views/iron/schemas/new.html.erb +0 -57
- data/lib/iron/test_fixtures.rb +0 -50
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
module Iron
|
|
2
|
-
class SchemaImporter::ImportStrategy
|
|
3
|
-
def import_block_definition(row)
|
|
4
|
-
raise NotImplementedError
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def import_content_type(row)
|
|
8
|
-
raise NotImplementedError
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def import_field_definition(row)
|
|
12
|
-
raise NotImplementedError
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
protected
|
|
16
|
-
|
|
17
|
-
def find_parent(parent_type, parent_handle)
|
|
18
|
-
case parent_type
|
|
19
|
-
when "content_type"
|
|
20
|
-
ContentType.find_by(handle: parent_handle)
|
|
21
|
-
when "block"
|
|
22
|
-
BlockDefinition.find_by(handle: parent_handle)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def content_type_class(type)
|
|
27
|
-
case type
|
|
28
|
-
when "single" then ContentTypes::Single
|
|
29
|
-
when "collection" then ContentTypes::Collection
|
|
30
|
-
else
|
|
31
|
-
raise "Invalid content type: #{type}. Must be 'single' or 'collection'"
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def field_definition_class(type)
|
|
36
|
-
"Iron::FieldDefinitions::#{type.camelize}".constantize
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def parse_metadata(metadata_string)
|
|
40
|
-
return {} if metadata_string.blank?
|
|
41
|
-
|
|
42
|
-
JSON.parse(metadata_string)
|
|
43
|
-
rescue JSON::ParserError
|
|
44
|
-
{}
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def parse_supported_block_definitions(supported_handles_string)
|
|
48
|
-
return BlockDefinition.none unless supported_handles_string.present?
|
|
49
|
-
|
|
50
|
-
BlockDefinition.where(handle: supported_handles_string.split("|"))
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def parse_supported_content_types(supported_handles_string)
|
|
54
|
-
return ContentType.none unless supported_handles_string.present?
|
|
55
|
-
|
|
56
|
-
ContentType.where(handle: supported_handles_string.split("|"))
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
module Iron
|
|
2
|
-
class SchemaImporter::MergeStrategy < SchemaImporter::ImportStrategy
|
|
3
|
-
def import_block_definition(row)
|
|
4
|
-
definition = BlockDefinition.find_or_initialize_by(handle: row["handle"])
|
|
5
|
-
definition.update!(
|
|
6
|
-
name: row["name"],
|
|
7
|
-
description: row["description"]
|
|
8
|
-
)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def import_content_type(row)
|
|
12
|
-
content_type = ContentType.find_or_initialize_by(handle: row["handle"])
|
|
13
|
-
|
|
14
|
-
content_type = content_type.becomes!(content_type_class(row["type"]))
|
|
15
|
-
content_type.update!(
|
|
16
|
-
name: row["name"],
|
|
17
|
-
description: row["description"],
|
|
18
|
-
icon: row["icon"],
|
|
19
|
-
web_publishing_enabled: row["web_publishing_enabled"] == "true",
|
|
20
|
-
base_path: row["base_path"]
|
|
21
|
-
)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def import_field_definition(row)
|
|
25
|
-
raise "Field type is required" unless row["type"].present?
|
|
26
|
-
return unless row["parent_type"].present? && row["parent_handle"].present? && row["handle"].present?
|
|
27
|
-
|
|
28
|
-
parent = find_parent(row["parent_type"], row["parent_handle"])
|
|
29
|
-
return unless parent
|
|
30
|
-
|
|
31
|
-
field_def = parent.field_definitions.find_or_initialize_by(handle: row["handle"])
|
|
32
|
-
field_def = field_def.becomes!(field_definition_class(row["type"]))
|
|
33
|
-
|
|
34
|
-
attributes = {
|
|
35
|
-
name: row["name"],
|
|
36
|
-
rank: row["rank"],
|
|
37
|
-
metadata: parse_metadata(row["metadata"])
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if field_def.is_a?(FieldDefinitions::Block) || field_def.is_a?(FieldDefinitions::BlockList)
|
|
41
|
-
attributes[:supported_block_definition_ids] = parse_supported_block_definitions(row["supported_block_definitions"]).pluck(:id)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
if field_def.is_a?(FieldDefinitions::Reference) || field_def.is_a?(FieldDefinitions::ReferenceList)
|
|
45
|
-
attributes[:supported_content_type_ids] = parse_supported_content_types(row["supported_content_types"]).pluck(:id)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
field_def.assign_attributes(attributes)
|
|
49
|
-
field_def.save!
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
module Iron
|
|
2
|
-
class SchemaImporter::ReplaceStrategy < SchemaImporter::ImportStrategy
|
|
3
|
-
def import_block_definition(row)
|
|
4
|
-
BlockDefinition.create!(
|
|
5
|
-
handle: row["handle"],
|
|
6
|
-
name: row["name"],
|
|
7
|
-
description: row["description"]
|
|
8
|
-
)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def import_content_type(row)
|
|
12
|
-
content_type_class(row["type"]).create!(
|
|
13
|
-
handle: row["handle"],
|
|
14
|
-
name: row["name"],
|
|
15
|
-
description: row["description"],
|
|
16
|
-
icon: row["icon"],
|
|
17
|
-
web_publishing_enabled: row["web_publishing_enabled"] == "true",
|
|
18
|
-
base_path: row["base_path"]
|
|
19
|
-
)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def import_field_definition(row)
|
|
23
|
-
raise "Field type is required" unless row["type"].present?
|
|
24
|
-
return unless row["parent_type"].present? && row["parent_handle"].present? && row["handle"].present?
|
|
25
|
-
|
|
26
|
-
parent = find_parent(row["parent_type"], row["parent_handle"])
|
|
27
|
-
return unless parent
|
|
28
|
-
|
|
29
|
-
parent.field_definitions.find_by(handle: row["handle"])&.destroy!
|
|
30
|
-
|
|
31
|
-
klass = field_definition_class(row["type"])
|
|
32
|
-
attributes = {
|
|
33
|
-
schemable: parent,
|
|
34
|
-
handle: row["handle"],
|
|
35
|
-
name: row["name"],
|
|
36
|
-
rank: row["rank"],
|
|
37
|
-
metadata: parse_metadata(row["metadata"])
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if klass <= FieldDefinitions::Block || klass <= FieldDefinitions::BlockList
|
|
41
|
-
attributes[:supported_block_definition_ids] = parse_supported_block_definitions(row["supported_block_definitions"]).pluck(:id)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
if klass <= FieldDefinitions::Reference || klass <= FieldDefinitions::ReferenceList
|
|
45
|
-
attributes[:supported_content_type_ids] = parse_supported_content_types(row["supported_content_types"]).pluck(:id)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
klass.create!(attributes)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
module Iron
|
|
2
|
-
class SchemaImporter::SafeStrategy < SchemaImporter::ImportStrategy
|
|
3
|
-
def import_block_definition(row)
|
|
4
|
-
return if BlockDefinition.exists?(handle: row["handle"])
|
|
5
|
-
|
|
6
|
-
BlockDefinition.create!(
|
|
7
|
-
handle: row["handle"],
|
|
8
|
-
name: row["name"],
|
|
9
|
-
description: row["description"]
|
|
10
|
-
)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def import_content_type(row)
|
|
14
|
-
return if ContentType.exists?(handle: row["handle"])
|
|
15
|
-
|
|
16
|
-
content_type_class(row["type"]).create!(
|
|
17
|
-
handle: row["handle"],
|
|
18
|
-
name: row["name"],
|
|
19
|
-
description: row["description"],
|
|
20
|
-
icon: row["icon"],
|
|
21
|
-
web_publishing_enabled: row["web_publishing_enabled"] == "true",
|
|
22
|
-
base_path: row["base_path"]
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def import_field_definition(row)
|
|
27
|
-
raise "Field type is required" unless row["type"].present?
|
|
28
|
-
return unless row["parent_type"].present? && row["parent_handle"].present? && row["handle"].present?
|
|
29
|
-
|
|
30
|
-
parent = find_parent(row["parent_type"], row["parent_handle"])
|
|
31
|
-
return unless parent
|
|
32
|
-
|
|
33
|
-
return if parent.field_definitions.exists?(handle: row["handle"])
|
|
34
|
-
|
|
35
|
-
klass = field_definition_class(row["type"])
|
|
36
|
-
attributes = {
|
|
37
|
-
schemable: parent,
|
|
38
|
-
handle: row["handle"],
|
|
39
|
-
name: row["name"],
|
|
40
|
-
rank: row["rank"],
|
|
41
|
-
metadata: parse_metadata(row["metadata"])
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if klass <= FieldDefinitions::Block || klass <= FieldDefinitions::BlockList
|
|
45
|
-
attributes[:supported_block_definition_ids] = parse_supported_block_definitions(row["supported_block_definitions"]).pluck(:id)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
if klass <= FieldDefinitions::Reference || klass <= FieldDefinitions::ReferenceList
|
|
49
|
-
attributes[:supported_content_type_ids] = parse_supported_content_types(row["supported_content_types"]).pluck(:id)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
klass.create!(attributes)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
require "csv"
|
|
2
|
-
|
|
3
|
-
module Iron
|
|
4
|
-
class SchemaImporter
|
|
5
|
-
IMPORT_MODES = %w[merge replace safe].freeze
|
|
6
|
-
|
|
7
|
-
attr_reader :file, :mode, :errors
|
|
8
|
-
|
|
9
|
-
def self.import(file, mode: "merge")
|
|
10
|
-
new(file, mode:).import
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def initialize(file, mode: "merge")
|
|
14
|
-
raise ArgumentError, "Missing import file" unless file.present?
|
|
15
|
-
raise ArgumentError, "Invalid import mode: #{mode}. Must be one of: #{IMPORT_MODES.join(', ')}" unless IMPORT_MODES.include?(mode)
|
|
16
|
-
|
|
17
|
-
@file = file
|
|
18
|
-
@mode = mode.to_s
|
|
19
|
-
@errors = []
|
|
20
|
-
@strategy = build_strategy(mode)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def import
|
|
24
|
-
ActiveRecord::Base.transaction do
|
|
25
|
-
Account.clear_schema! if mode == "replace"
|
|
26
|
-
|
|
27
|
-
archive = SchemaArchive.from_file(file)
|
|
28
|
-
|
|
29
|
-
unless archive.valid?
|
|
30
|
-
errors.concat(archive.errors)
|
|
31
|
-
return ImportResult.new(false, errors)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
if archive["block_definitions.csv"]
|
|
35
|
-
CSV.parse(archive["block_definitions.csv"], headers: true) do |row|
|
|
36
|
-
next unless row["handle"].present?
|
|
37
|
-
@strategy.import_block_definition(row)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
if archive["content_types.csv"]
|
|
42
|
-
CSV.parse(archive["content_types.csv"], headers: true) do |row|
|
|
43
|
-
next unless row["handle"].present?
|
|
44
|
-
@strategy.import_content_type(row)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
if archive["field_definitions.csv"]
|
|
49
|
-
CSV.parse(archive["field_definitions.csv"], headers: true) do |row|
|
|
50
|
-
@strategy.import_field_definition(row)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
update_content_type_references(archive["content_types.csv"])
|
|
55
|
-
|
|
56
|
-
ImportResult.new(true, [])
|
|
57
|
-
end
|
|
58
|
-
rescue StandardError => e
|
|
59
|
-
errors << "Import failed: #{e.message}"
|
|
60
|
-
ImportResult.new(false, errors)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def build_strategy(mode)
|
|
66
|
-
case mode.to_s
|
|
67
|
-
when "merge" then SchemaImporter::MergeStrategy.new
|
|
68
|
-
when "replace" then SchemaImporter::ReplaceStrategy.new
|
|
69
|
-
when "safe" then SchemaImporter::SafeStrategy.new
|
|
70
|
-
else
|
|
71
|
-
raise ArgumentError, "Invalid import mode: #{mode}"
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def update_content_type_references(content_types_csv)
|
|
76
|
-
return unless content_types_csv
|
|
77
|
-
|
|
78
|
-
CSV.parse(content_types_csv, headers: true) do |row|
|
|
79
|
-
handle = row["handle"]
|
|
80
|
-
content_type = ContentType.find_by(handle: handle)
|
|
81
|
-
next unless content_type
|
|
82
|
-
|
|
83
|
-
if row["title_field_handle"].present?
|
|
84
|
-
title_field = content_type.field_definitions.find_by(handle: row["title_field_handle"])
|
|
85
|
-
content_type.update!(title_field_definition: title_field) if title_field
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
if row["web_page_title_field_handle"].present?
|
|
89
|
-
page_title_field = content_type.field_definitions.find_by(handle: row["web_page_title_field_handle"])
|
|
90
|
-
content_type.update!(web_page_title_field_definition: page_title_field) if page_title_field
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
class ImportResult
|
|
96
|
-
attr_reader :errors
|
|
97
|
-
|
|
98
|
-
def initialize(success, errors)
|
|
99
|
-
@success = success
|
|
100
|
-
@errors = errors
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def success?
|
|
104
|
-
@success
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<% content_for :title, "Import Content" %>
|
|
2
|
-
|
|
3
|
-
<div class="">
|
|
4
|
-
<%= back_button_to "Settings", settings_path %>
|
|
5
|
-
<h1 class="page-title">Import Content</h1>
|
|
6
|
-
<p class="mt-2 text-sm text-stone-500">Upload a content archive exported from another Iron instance.</p>
|
|
7
|
-
|
|
8
|
-
<%= form_with url: import_content_path, multipart: true, class: "mt-8 max-w-2xl", data: { turbo: false } do |form| %>
|
|
9
|
-
<div class="field-group">
|
|
10
|
-
<div class="field">
|
|
11
|
-
<%= form.label :content_file, "Content Archive" %>
|
|
12
|
-
<div>
|
|
13
|
-
<%= form.file_field :content_file,
|
|
14
|
-
accept: ".tar",
|
|
15
|
-
required: true,
|
|
16
|
-
class: "input" %>
|
|
17
|
-
<p class="mt-2 text-sm text-stone-500">Select a .tar file exported using Iron's content export.</p>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<div class="field">
|
|
22
|
-
<label class="text-sm font-medium text-stone-700">Import behaviour</label>
|
|
23
|
-
<p class="text-sm text-stone-500 mt-1">
|
|
24
|
-
Entries with matching IDs and instance tokens are updated. Other records are created.
|
|
25
|
-
</p>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div class="mt-6 flex items-center gap-x-3">
|
|
30
|
-
<%= form.submit "Import Content", class: "button-primary" %>
|
|
31
|
-
<%= link_to "Cancel", settings_path, class: "button-secondary" %>
|
|
32
|
-
</div>
|
|
33
|
-
<% end %>
|
|
34
|
-
</div>
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
<% content_for :title, "Import Schema" %>
|
|
2
|
-
|
|
3
|
-
<div class="">
|
|
4
|
-
<%= back_button_to "Content Types", content_types_path %>
|
|
5
|
-
<h1 class="page-title">Import Schema</h1>
|
|
6
|
-
<p class="mt-2 text-sm text-stone-500">Upload a schema tar file to import content types, fields, and blocks.</p>
|
|
7
|
-
|
|
8
|
-
<%= form_with url: import_schema_path, multipart: true, class: "mt-8 max-w-2xl", data: { turbo: false } do |form| %>
|
|
9
|
-
<div class="field-group">
|
|
10
|
-
<div class="field">
|
|
11
|
-
<%= form.label :schema_file, "Schema File" %>
|
|
12
|
-
<div>
|
|
13
|
-
<%= form.file_field :schema_file,
|
|
14
|
-
accept: ".tar",
|
|
15
|
-
required: true,
|
|
16
|
-
class: "input" %>
|
|
17
|
-
<p class="mt-2 text-sm text-stone-500">Select a .tar file exported from Iron CMS</p>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<div class="field">
|
|
22
|
-
<%= form.label :import_mode, "Import Mode" %>
|
|
23
|
-
<div class="space-y-4">
|
|
24
|
-
<% @import_modes.each do |mode| %>
|
|
25
|
-
<div class="flex items-start">
|
|
26
|
-
<div class="flex h-6 items-center">
|
|
27
|
-
<%= form.radio_button :import_mode, mode,
|
|
28
|
-
checked: mode == "merge",
|
|
29
|
-
class: "h-4 w-4 border-stone-300 text-blue-600 focus:ring-blue-600" %>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="ml-3">
|
|
32
|
-
<%= form.label "import_mode_#{mode}", class: "text-sm font-medium text-stone-700" do %>
|
|
33
|
-
<%= mode.capitalize %>
|
|
34
|
-
<% end %>
|
|
35
|
-
<p class="text-sm text-stone-500">
|
|
36
|
-
<% case mode %>
|
|
37
|
-
<% when "merge" %>
|
|
38
|
-
Add new items and update existing ones by handle
|
|
39
|
-
<% when "replace" %>
|
|
40
|
-
Clear existing schema and import fresh (destructive)
|
|
41
|
-
<% when "safe" %>
|
|
42
|
-
Only add new items, skip existing handles
|
|
43
|
-
<% end %>
|
|
44
|
-
</p>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
<% end %>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
<div class="mt-6 flex items-center gap-x-3">
|
|
53
|
-
<%= form.submit "Import Schema", class: "button-primary" %>
|
|
54
|
-
<%= link_to "Cancel", content_types_path, class: "button-secondary" %>
|
|
55
|
-
</div>
|
|
56
|
-
<% end %>
|
|
57
|
-
</div>
|
data/lib/iron/test_fixtures.rb
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
require "stringio"
|
|
2
|
-
|
|
3
|
-
module Iron
|
|
4
|
-
module TestFixtures
|
|
5
|
-
class << self
|
|
6
|
-
def load
|
|
7
|
-
return if @loaded
|
|
8
|
-
|
|
9
|
-
fixture_path = Rails.root.join("test/fixtures/iron")
|
|
10
|
-
schema_file = fixture_path.join("schema.tar.gz")
|
|
11
|
-
content_file = fixture_path.join("content.tar.gz")
|
|
12
|
-
|
|
13
|
-
if schema_file.exist?
|
|
14
|
-
load_schema(schema_file)
|
|
15
|
-
else
|
|
16
|
-
Rails.logger.warn "Iron test fixture not found: #{schema_file}"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
if content_file.exist?
|
|
20
|
-
load_content(content_file)
|
|
21
|
-
else
|
|
22
|
-
Rails.logger.warn "Iron test fixture not found: #{content_file}"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
@loaded = true
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def load_schema(file_path)
|
|
31
|
-
File.open(file_path, "rb") do |file|
|
|
32
|
-
result = SchemaImporter.import(file, mode: "merge")
|
|
33
|
-
unless result.success?
|
|
34
|
-
raise "Failed to load Iron schema fixtures: #{result.errors.join(', ')}"
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def load_content(file_path)
|
|
40
|
-
File.open(file_path, "rb") do |file|
|
|
41
|
-
archive = Archive.from_file(file)
|
|
42
|
-
result = ContentImport.import(archive)
|
|
43
|
-
unless result.success?
|
|
44
|
-
raise "Failed to load Iron content fixtures: #{result.errors.join(', ')}"
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|