-
Notifications
You must be signed in to change notification settings - Fork 900
/
Copy pathdialog.rb
210 lines (167 loc) · 6.19 KB
/
dialog.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
class Dialog < ApplicationRecord
DIALOG_DIR_PLUGIN = 'content/service_dialogs'.freeze
# The following gets around a glob symbolic link issue
YAML_FILES_PATTERN = "{,*/**/}*.{yaml,yml}".freeze
default_value_for :system, false
has_many :dialog_tabs, -> { order(:position) }, :dependent => :destroy
validate :validate_children
include DialogMixin
has_many :resource_actions
virtual_has_one :content, :class_name => "Hash"
before_destroy :reject_if_has_resource_actions
validates :name, :unique_within_region => true
alias_attribute :name, :label
attr_accessor :target_resource
def self.seed
dialog_import_service = DialogImportService.new
Vmdb::Plugins.each do |plugin|
Dir.glob(plugin.root.join(DIALOG_DIR_PLUGIN, YAML_FILES_PATTERN)).each do |file|
dialog_import_service.import_all_service_dialogs_from_yaml_file(file)
end
end
end
def each_dialog_field(&block)
dialog_fields.each(&block)
end
def dialog_fields
dialog_tabs.flat_map(&:dialog_fields)
end
def field_name_exist?(name)
dialog_fields.any? { |df| df.name == name }
end
def dialog_resources
dialog_tabs
end
def automate_values_hash
dialog_fields.each_with_object({}) do |df, result|
if df.options.include?("multiple")
result[MiqAeEngine.create_automation_attribute_array_key(df.automate_key_name)] = df.automate_output_value
else
result[df.automate_key_name] = df.automate_output_value
end
end
end
def validate_children
# To remove the meaningless error message like "Dialog tabs is invalid" when child's validation fails
errors.delete(:dialog_tabs)
if dialog_tabs.blank?
errors.add(:base, _("Dialog %{dialog_label} must have at least one Tab") % {:dialog_label => label})
end
duplicate_field_names = dialog_fields.collect(&:name).duplicates
if duplicate_field_names.present?
errors.add(:base, _("Dialog field name cannot be duplicated on a dialog: %{duplicates}") % {:duplicates => duplicate_field_names.join(', ')})
end
dialog_tabs.each do |dt|
next if dt.valid?
dt.errors.full_messages.each do |err_msg|
errors.add(:base, _("Dialog %{dialog_label} / %{error_message}") %
{:dialog_label => label, :error_message => err_msg})
end
end
end
def validate_field_data
dialog_tabs.each_with_object([]) do |dt, result|
dt.dialog_groups.each do |dg|
dg.dialog_fields.each do |df|
err_msg = df.validate_field_data(dt, dg)
result << err_msg if err_msg.present?
end
end
end
end
def load_values_into_fields(values, ignore_nils = true)
values = values.with_indifferent_access
dialog_field_hash.each_value do |field|
field.dialog = self
new_value = values[field.automate_key_name] || values[field.name] || values.dig("parameters", field.name)
new_value ||= field.value unless ignore_nils
field.value = new_value
end
end
def initialize_with_given_values(values)
dialog_field_hash.each_value do |field|
field.dialog = self
field.value = values[field.automate_key_name] || values[field.name]
end
dialog_field_hash.each_value do |field|
given_value = values[field.automate_key_name] || values[field.name]
field.initialize_with_given_value(given_value)
end
end
def initialize_value_context(_values)
dialog_field_hash.each_value do |field|
field.dialog = self
end
dialog_field_hash.each_value(&:initialize_value_context)
end
def initialize_static_values
dialog_field_hash.each_value do |field|
field.dialog = self
end
dialog_field_hash.each_value(&:initialize_static_values)
end
def init_fields_with_values_for_request(values)
values = values.with_indifferent_access
dialog_field_hash.each do |_key, field|
field.value = values[field.automate_key_name] || values[field.name]
end
end
def field(name)
dialog_field_hash[name.to_s]
end
def content(target = nil, resource_action = nil, all_attributes = false)
return DialogSerializer.new.serialize(Array[self], all_attributes) if target.nil? && resource_action.nil?
workflow = ResourceActionWorkflow.new({}, User.current_user, resource_action, :target => target)
DialogSerializer.new.serialize(Array[workflow.dialog], all_attributes)
end
# Allows you to pass dialog tabs as a hash
# Will update any item passed with an ID,
# Creates a new item without an ID,
# Removes any items not passed in the content.
def update_tabs(tabs)
association_list = dialog_import_service.build_association_list("dialog_tabs" => tabs)
transaction do
updated_tabs = []
tabs.each do |dialog_tab|
if dialog_tab.key?('id')
DialogTab.find(dialog_tab['id']).tap do |tab|
tab.update(dialog_tab.except('id', 'href', 'dialog_id', 'dialog_groups'))
tab.update_dialog_groups(dialog_tab['dialog_groups'])
updated_tabs << tab
end
else
updated_tabs << dialog_import_service.build_dialog_tabs('dialog_tabs' => [dialog_tab]).first
end
end
self.dialog_tabs = updated_tabs
end
transaction do
dialog_import_service.build_associations(self, association_list)
end
end
def deep_copy(new_attributes = {})
new_dialog = dup
new_dialog.dialog_tabs = dialog_tabs.collect(&:deep_copy)
new_attributes.each do |attr, value|
new_dialog.send(:"#{attr}=", value)
end
new_dialog
end
private
def dialog_field_hash
@dialog_field_hash ||= dialog_fields.index_by { |df| df.name }
end
def reject_if_has_resource_actions
connected_components = resource_actions.collect do |ra|
# not find - we need nil when not found
ra.resource_type.constantize.find_by(:id => ra.resource_id)
end.compact
if connected_components.length > 0
errors.add(:base, _("Dialog cannot be deleted because it is connected to other components: %{components}") % {:components => connected_components.map { |cc| cc.class.name + ":" + cc.id.to_s + " - " + cc.try(:name) }})
throw :abort
end
end
def dialog_import_service
@dialog_import_service ||= DialogImportService.new
end
end