Skip to content

Commit

Permalink
add dialog info when import/export custom buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
borisko123 committed May 7, 2020
1 parent 927b99f commit 6e636c2
Show file tree
Hide file tree
Showing 6 changed files with 490 additions and 170 deletions.
24 changes: 19 additions & 5 deletions lib/task_helpers/exports/custom_buttons.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ class Exports
class CustomButtons
class ExportArInstances
EXCLUDE_ATTRS = %w(id created_on updated_on created_at updated_at dialog_id resource_id).freeze
def self.export_object(obj, hash)

# extract dialog data (name), for this resource action
def self.handle_dialog(obj, a)
extra_attributes = {} # will contain dialog data
if a.to_sym == :resource_action
dialog_label = obj.try(:resource_action).try(:dialog).try(:name)
extra_attributes.merge!({"dialog_label" => dialog_label}) if dialog_label
end
extra_attributes
end

def self.export_object(obj, hash, extra_attributes = {})
class_name = obj.class.name.underscore

$log.info("Exporting #{obj.class.name}: #{obj.try('name')} (ID: #{obj&.id})")
(hash[class_name] ||= []) << item = { 'attributes' => build_attr_list(obj.try(:attributes)) }
(hash[class_name] ||= []) << item = {'attributes' => build_attr_list(obj.try(:attributes)).merge(extra_attributes)}
create_association_list(obj, item)
descendant_list(obj, item)
end
Expand All @@ -18,12 +29,15 @@ def self.build_attr_list(attrs)

def self.create_association_list(obj, item)
associations = obj.class.try(:reflections)

if associations
associations = associations.collect { |model, assoc| { model => assoc.class.to_s.demodulize } }.select { |as| as.values.first != "BelongsToReflection" && as.keys.first != "all_relationships" }
associations = associations.collect { |model, assoc| {model => assoc.class.to_s.demodulize} }.select { |as| as.values.first != "BelongsToReflection" && as.keys.first != "all_relationships" }
associations.each do |assoc|
assoc.each do |a|
next if obj.try(a.first.to_sym).blank?
export_object(obj.try(a.first.to_sym), (item['associations'] ||= {}))
assoc_name = obj.try(a.first.to_sym)
extra_attributes = handle_dialog(obj, a.first) # stores dialog data
export_object(obj.try(a.first.to_sym), (item['associations'] ||= {}), extra_attributes)
end
end
end
Expand Down Expand Up @@ -53,4 +67,4 @@ def export(options = {})
end
end
end
end
end
75 changes: 58 additions & 17 deletions lib/task_helpers/imports/custom_buttons.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# frozen_string_literal: true

module TaskHelpers
class Imports
class CustomButtons

def import(options)
return unless options[:source]
glob = File.file?(options[:source]) ? options[:source] : "#{options[:source]}/*.yaml"

glob = File.file?(options[:source]) ? options[:source] : "#{options[:source]}/*.yaml*"
Dir.glob(glob) do |filename|
$log.info("Importing Custom Buttons from: #{filename}")

begin
import_custom_buttons(filename)
rescue StandardError
Expand All @@ -26,36 +29,50 @@ def import(obj_hash)
ActiveRecord::Base.transaction { obj_hash.each { |obj_def| create_object(*obj_def) } }
end

def find_or_create_object(class_name, obj)
klass = class_name.camelize.constantize
attributes = obj['attributes']
name = attributes.fetch('name', nil)
instance = klass.find_by(name: name) if name
# create new object
unless instance
item = klass.create!(attributes&.except('guid'))
populate_item(item, obj, class_name)
else # update existed object
instance.update_attributes!(attributes&.except('guid'))
populate_item(instance, obj, class_name)
end
end

def create_object(class_name, obj_array)
klass = class_name.camelize.constantize

obj_array.collect do |obj|
if klass.name == "CustomButtonSet"
if klass.name == 'CustomButtonSet'
order = obj.fetch_path('attributes', 'set_data', :button_order)
obj['attributes']['set_data'][:button_order] = nil if order.present?
end

klass.create!(obj['attributes']&.except('guid')).tap do |new_obj|
add_children(obj, new_obj)
add_associations(obj, new_obj)
try("#{class_name}_post", new_obj)
end
find_or_create_object(class_name, obj)
end
end

def add_children(obj, new_obj)
if obj['children'].present?
obj['children'].each do |child|
new_obj.add_members(create_object(*child))
childes = create_object(*child)
new_obj.add_members(childes)
end
end
end

def add_associations(obj, new_obj)
if obj['associations'].present?
obj['associations'].each do |assoc|
new_obj.send("#{assoc.first}=", create_object(*assoc).first)
end
return unless obj['associations'].present?

# try to find existing resource_actions
resource_action = ResourceAction.find_by(resource_id: new_obj.id, resource_type: 'CustomButton')
obj['associations'].each do |assoc|
populate_action(new_obj, assoc) { create_object(*assoc).first } unless resource_action
populate_action(new_obj, assoc) { |args| resource_action.tap { |ra| ra.update_attributes!(args) } } if resource_action
end
end

Expand All @@ -69,8 +86,32 @@ def custom_button_post(new_obj)
end

def check_user(new_obj)
existing_user = User.find_by(:name => new_obj[:userid])
new_obj.update(:userid => existing_user.nil? ? "admin" : existing_user)
existing_user = User.find_by(name: new_obj[:userid])
new_obj.update(userid: existing_user.nil? ? 'admin' : existing_user)
end

private

def populate_item(item, obj, class_name)
item.tap do |i|
add_children(obj, i)
add_associations(obj, i)
try("#{class_name}_post", i)
end
end

def populate_action(item, assoc)
# check if imported data has dialog data
args = assoc.second.first['attributes']
dialog_label = args.delete('dialog_label')

unless dialog_label.nil?
dialog = Dialog.find_by_label(dialog_label)
$log.info("Unable to locate dialog: [#{dialog_label}]") unless dialog
end
resource_action = yield (args)
resource_action['dialog_id'] = dialog.id if dialog
item.send("#{assoc.first}=", resource_action)
end
end

Expand All @@ -80,4 +121,4 @@ def import_custom_buttons(filename)
end
end
end
end
end
105 changes: 86 additions & 19 deletions spec/lib/task_helpers/imports/custom_buttons_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
RSpec.describe TaskHelpers::Imports::CustomButtons do
let(:data_dir) { File.join(File.expand_path(__dir__), 'data', 'custom_buttons') }
let(:custom_button_file) { 'CustomButtons.yaml' }
let(:bad_custom_button_file) { 'CustomButtonsBad.yaml' }
let(:custom_button_set_name) { 'group1|Vm|' }
let(:custom_button_file) { 'CustomButtons.yaml' }
let(:bad_custom_button_file) { 'CustomButtonsBad.yaml' }
let(:custom_button_set_name) { 'group1|Vm|' }
let(:custom_button_set_description) { 'group1' }
let(:resource_action_ae_namespace) { 'SYSTEM' }
let(:options) { {:source => source} }
let(:resource_action_ae_namespace) { 'SYSTEM' }
let(:options) { {:source => source} }
let(:custom_button_1_name) { 'button 1' }
let!(:test_dialog) { FactoryBot.create(:dialog, :label => 'dialog') }
let!(:test_dialog_2) { FactoryBot.create(:dialog, :label => 'dialog 2') }
let(:for_update_custom_button_file) { 'CustomButtonsForUpdate.yml' }

describe "#import" do
describe "when the source is a directory" do
Expand All @@ -19,19 +23,23 @@
end

context "with existing identical buttons" do
it 'should raise' do
it 'should NOT raise' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
assert_imports_only_custom_button_set_one
end
end

context "yaml import failure" do
it 'should raise' do
file = Tempfile.new('foo.yaml', data_dir)
file.write("bad yaml here")
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
assert_imports_only_custom_button_set_one
begin
file.write("bad yaml here")
assert_raises_import_error
assert_imports_only_custom_button_set_one
ensure
file.close
file.unlink # deletes the temp file
end
end
end
end
Expand All @@ -45,28 +53,66 @@
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_test_custom_button_set_present
assert_imports_only_custom_button_set_one
assert_dialog_is_set
end
end
end

context "doesn't import bad yaml" do
let(:source) { "#{data_dir}/#{bad_custom_button_file}" }
it 'does not imports a specified file' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_no_custom_buttons
end
context "doesn't import bad yaml" do
let(:source) { "#{data_dir}/#{bad_custom_button_file}" }
it 'does not imports a specified file' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_no_custom_buttons
end
end

context "with existing identical buttons" do
it 'should not import anything' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
assert_imports_only_custom_button_set_one
assert_imports_only_custom_button_set_one
end
end


context "updating" do
let(:source) { "#{data_dir}/#{custom_button_file}" }
context "updated with the same data" do
it "should remain the same" do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_custom_buttons(3)
assert_button_data('#ff0000')
# call second time, in order to test update logic
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_custom_buttons(3)
assert_button_data('#ff0000')
end
end
context "updated with the group and button's color" do
let(:source) { "#{data_dir}/#{custom_button_file}" }
it "color should be changed" do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_custom_buttons(3)
options[:source] = "#{data_dir}/#{for_update_custom_button_file}"
# call second time, in order to test update logic
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_custom_buttons(3)
assert_button_data('#aabbcc')
assert_button_set_data('#112233')
assert_resource_action_data('#112233')
end
end
end
end
end


def assert_dialog_is_set
btn1 = CustomButton.find_by(name: custom_button_1_name)
expect(btn1).to be
expect(btn1.resource_action.dialog.id).to eq(test_dialog_2.id)
end

def assert_test_custom_button_set_present
cbs = CustomButtonSet.find_by(:name => custom_button_set_name)
expect(cbs.custom_buttons.count).to eq(3)
Expand All @@ -86,4 +132,25 @@ def assert_imports_no_custom_buttons
def assert_raises_import_error
expect { TaskHelpers::Imports::CustomButtons.new.import(options) }.to raise_error(StandardError, /Error importing/)
end
end

def assert_imports_custom_buttons(count = 0)
expect(CustomButton.count).to eq(count)
end

def assert_button_data(color)
b1 = CustomButton.find_by(name: 'button 1')
expect(b1).to be
expect(b1.options[:button_color]).to eq(color)
end

def assert_button_set_data(color)
cbs1 = CustomButtonSet.find_by(name: 'group1|Vm|')
expect(cbs1).to be
expect(cbs1.set_data[:button_color]).to eq(color)
end

def assert_resource_action_data(action)
b1 = CustomButton.find_by(name: 'button 1')
expect(b1.resource_action.action).to eq('my_action')
end
end
Loading

0 comments on commit 6e636c2

Please sign in to comment.