morpheus-cli 6.3.0 → 6.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,625 @@
1
+ require 'morpheus/cli/cli_command'
2
+ require 'securerandom'
3
+
4
+ class Morpheus::Cli::LibraryFormsCommand
5
+ include Morpheus::Cli::CliCommand
6
+ include Morpheus::Cli::LibraryHelper
7
+
8
+ set_command_name :'library-forms'
9
+ register_subcommands :list, :get, :add, :update, :remove
10
+
11
+ def connect(opts)
12
+ @api_client = establish_remote_appliance_connection(opts)
13
+ @library_instance_types_interface = @api_client.library_instance_types
14
+ @provision_types_interface = @api_client.provision_types
15
+ @option_types_interface = @api_client.option_types
16
+ @option_type_forms_interface = @api_client.option_type_forms
17
+ end
18
+
19
+ def handle(args)
20
+ handle_subcommand(args)
21
+ end
22
+
23
+ def list(args)
24
+ options = {}
25
+ params = {}
26
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
27
+ opts.banner = subcommand_usage()
28
+ opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
29
+ add_query_parameter(params, 'labels', parse_labels(val))
30
+ end
31
+ opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
32
+ add_query_parameter(params, 'allLabels', parse_labels(val))
33
+ end
34
+ build_standard_list_options(opts, options)
35
+ opts.footer = "List option forms."
36
+ end
37
+ optparse.parse!(args)
38
+ # verify_args!(args:args, optparse:optparse, count:0)
39
+ if args.count > 0
40
+ options[:phrase] = args.join(" ")
41
+ end
42
+ connect(options)
43
+ params.merge!(parse_list_options(options))
44
+ @option_type_forms_interface.setopts(options)
45
+ if options[:dry_run]
46
+ print_dry_run @option_type_forms_interface.dry.list(params)
47
+ return
48
+ end
49
+ json_response = @option_type_forms_interface.list(params)
50
+ render_response(json_response, options, rest_list_key) do
51
+ option_type_forms = json_response[rest_list_key]
52
+ subtitles = []
53
+ subtitles += parse_list_subtitles(options)
54
+ print_h1 "Morpheus Forms", subtitles, options
55
+ if option_type_forms.empty?
56
+ print cyan,"No forms found.",reset,"\n"
57
+ else
58
+ rows = option_type_forms.collect do |option_type_form|
59
+ {
60
+ id: option_type_form['id'],
61
+ name: option_type_form['name'],
62
+ code: option_type_form['code'],
63
+ labels: option_type_form['labels'],
64
+ description: option_type_form['description'],
65
+ }
66
+ end
67
+ columns = [
68
+ :id,
69
+ :name,
70
+ :code,
71
+ {:labels => {:display_method => lambda {|it| format_list(it[:labels], '', 3) rescue '' }}},
72
+ :description,
73
+ ]
74
+ print cyan
75
+ print as_pretty_table(rows, columns, options)
76
+ print reset
77
+ print_results_pagination(json_response)
78
+ end
79
+ print reset,"\n"
80
+ end
81
+ end
82
+
83
+ def get(args)
84
+ options = {}
85
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
86
+ opts.banner = subcommand_usage("[form]")
87
+ build_standard_get_options(opts, options)
88
+ opts.footer = <<-EOT
89
+ Get details about a form.
90
+ [form] is required. This is the name or id of a form.
91
+ EOT
92
+ end
93
+ optparse.parse!(args)
94
+ verify_args!(args:args, optparse:optparse, min:1)
95
+ connect(options)
96
+ id_list = parse_id_list(args)
97
+ return run_command_for_each_arg(id_list) do |arg|
98
+ _get(arg, options)
99
+ end
100
+ end
101
+
102
+ def _get(id, options)
103
+ params = {}
104
+ params.merge!(parse_query_options(options))
105
+ if id.to_s !~ /\A\d{1,}\Z/
106
+ # option_type_form = find_by_name(:option_type_form, id)
107
+ option_type_form = find_option_type_form_by_name_or_id(id)
108
+ return 1, "Form not found" if option_type_form.nil?
109
+ id = option_type_form['id']
110
+ end
111
+ @option_type_forms_interface.setopts(options)
112
+ if options[:dry_run]
113
+ print_dry_run @option_type_forms_interface.dry.get(id.to_i, params)
114
+ return
115
+ end
116
+ json_response = @option_type_forms_interface.get(id.to_i, params)
117
+ render_response(json_response, options, rest_object_key) do
118
+ option_type_form = json_response[rest_object_key]
119
+ print_h1 "Form Details", options
120
+ print cyan
121
+ print_description_list({
122
+ "ID" => 'id',
123
+ "Name" => 'name',
124
+ "Code" => 'code',
125
+ "Description" => 'description',
126
+ "Labels" => lambda {|it| format_list(it['labels']) },
127
+ }, option_type_form, options)
128
+
129
+ # show option types
130
+ print_h2 "Form Inputs"
131
+ #print format_option_types_table(option_type_form['options'], options, nil, true)
132
+ print format_option_types_table(option_type_form['options'], options, 'config.customOptions')
133
+ print reset,"\n"
134
+
135
+ # show Field Groups
136
+ field_groups = option_type_form['fieldGroups']
137
+ if field_groups && field_groups.size > 0
138
+ field_groups.each do |field_group|
139
+ print_h2 "#{field_group['name']}"
140
+ #print format_option_types_table(field_group['options'], options, nil, true)
141
+ if field_group['options'] && !field_group['options'].empty?
142
+ print format_option_types_table(field_group['options'], options, 'config.customOptions')
143
+ print reset,"\n"
144
+ else
145
+ print cyan, "This field group is empty", reset, "\n\n"
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ def add(args)
153
+ options = {}
154
+ my_option_types = nil
155
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
156
+ opts.banner = subcommand_usage("[name] [options]")
157
+ build_option_type_options(opts, options, new_option_type_form_option_types())
158
+ # maybe use --inputs for less confusion
159
+ opts.on('--options OPTIONS', String, "List of option type inputs to add to the form, this list can include full JSON objects or just the id to use an existing option eg. --options '[5,6,7,{\"fieldName\":\"input\",\"fieldLabel\":\"Input\"}]'") do |val|
160
+ val = "[#{val.strip}]" unless val.strip.to_s[0] == '[' && val.strip.to_s[-1] == ']'
161
+ begin
162
+ options[:selected_options] = JSON.parse(val)
163
+ rescue
164
+ raise_command_error "Failed to parse --options value '#{val}' as JSON"
165
+ end
166
+ end
167
+ build_standard_add_options(opts, options)
168
+ opts.footer = "Create a new form."
169
+ end
170
+ optparse.parse!(args)
171
+ verify_args!(args:args, optparse:optparse, max:1)
172
+ if args.count == 1
173
+ options[:options]['name'] = args[0]
174
+ end
175
+ connect(options)
176
+ parse_payload(options, rest_object_key) do |payload|
177
+ form_payload = prompt_new_form(options)
178
+ #form_payload.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
179
+ payload.deep_merge!({rest_object_key => form_payload})
180
+ # cleanup payload
181
+ # remove transient option params used for prompting for list of inputs
182
+ payload[rest_object_key].keys.each do |k|
183
+ if k == "option" || k.to_s =~ /^option\d+$/ || k == "fieldGroup" || k.to_s =~ /^fieldGroup\d+$/
184
+ payload[rest_object_key].delete(k)
185
+ end
186
+ end
187
+ end
188
+ execute_api(@option_type_forms_interface, :create, [], options, rest_object_key) do |json_response|
189
+ form = json_response[rest_object_key]
190
+ print_green_success "Added form #{form['name']}"
191
+ _get(form['id'], options)
192
+ end
193
+ end
194
+
195
+ def update(args)
196
+ options = {}
197
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
198
+ opts.banner = subcommand_usage("[form] [options]")
199
+ build_option_type_options(opts, options, update_option_type_form_option_types())
200
+ build_standard_update_options(opts, options)
201
+ opts.footer = <<-EOT
202
+ Update a form.
203
+ [form] is required. This is the name or id of a form.
204
+ EOT
205
+ end
206
+ optparse.parse!(args)
207
+ verify_args!(args:args, optparse:optparse, count:1)
208
+ connect(options)
209
+ form = find_option_type_form_by_name_or_id(args[0])
210
+ return 1, "Form not found" if form.nil?
211
+ parse_payload(options, rest_object_key) do |payload|
212
+ option_types = update_option_type_form_option_types()
213
+ v_prompt = no_prompt(option_types, options)
214
+ #v_prompt.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
215
+ payload.deep_merge!({rest_object_key => v_prompt})
216
+ if payload[rest_object_key].empty? # || options[:no_prompt]
217
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
218
+ end
219
+ end
220
+ execute_api(@option_type_forms_interface, :update, [form['id']], options, 'backup') do |json_response|
221
+ form = json_response[rest_object_key]
222
+ print_green_success "Updated form #{form['name']}"
223
+ _get(form['id'], options.merge(params:{}))
224
+ end
225
+ end
226
+
227
+ def remove(args)
228
+ options = {}
229
+ params = {}
230
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
231
+ opts.banner = subcommand_usage("[form]")
232
+ build_standard_remove_options(opts, options)
233
+ opts.footer = <<-EOT
234
+ Delete a form.
235
+ [form] is required. This is the name or id of a form.
236
+ EOT
237
+ end
238
+ optparse.parse!(args)
239
+ verify_args!(args:args, optparse:optparse, count:1)
240
+ connect(options)
241
+ form = find_option_type_form_by_name_or_id(args[0])
242
+ return 1, "Form not found" if form.nil?
243
+ parse_options(options, params)
244
+ confirm!("Are you sure you want to delete the form #{form['name']}?", options)
245
+ execute_api(@option_type_forms_interface, :destroy, [form['id']], options) do |json_response|
246
+ print_green_success "Removed form #{form['name']}"
247
+ end
248
+ end
249
+
250
+ private
251
+
252
+ def rest_list_key
253
+ option_type_form_list_key
254
+ end
255
+
256
+ def rest_object_key
257
+ option_type_form_object_key
258
+ end
259
+
260
+ def option_type_form_list_key
261
+ "optionTypeForms"
262
+ end
263
+
264
+ def option_type_form_object_key
265
+ "optionTypeForm"
266
+ end
267
+
268
+ def find_option_type_form_by_name_or_id(val)
269
+ if val.to_s =~ /\A\d{1,}\Z/
270
+ return find_option_type_form_by_id(val)
271
+ else
272
+ return find_option_type_form_by_name(val)
273
+ end
274
+ end
275
+
276
+ def find_option_type_form_by_id(id)
277
+ begin
278
+ json_response = @option_type_forms_interface.get(id.to_i)
279
+ return json_response[option_type_form_object_key]
280
+ rescue RestClient::Exception => e
281
+ if e.response && e.response.code == 404
282
+ print_red_alert "Form not found by id #{id}"
283
+ return nil
284
+ else
285
+ raise e
286
+ end
287
+ end
288
+ end
289
+
290
+ def find_option_type_form_by_name(name)
291
+ json_results = @option_type_forms_interface.list({name: name.to_s})
292
+ records = json_results[option_type_form_list_key]
293
+ if json_results['optionTypeForms'].empty?
294
+ print_red_alert "Form not found by name '#{name}'"
295
+ return nil
296
+ elsif records.size > 1
297
+ print_red_alert "More than one #{label.downcase} found by name '#{val}'"
298
+ print_error "\n"
299
+ puts_error as_pretty_table(records, [:id, :name], {color:red})
300
+ print_red_alert "Try using ID instead"
301
+ print_error reset,"\n"
302
+ return nil
303
+ end
304
+ option_type_form = json_results['optionTypeForms'][0]
305
+ return option_type_form
306
+ end
307
+
308
+ # def get_available_option_list_types
309
+ # [
310
+ # {'name' => 'REST', 'value' => 'rest'},
311
+ # {'name' => 'Morpheus Api', 'value' => 'api'},
312
+ # {'name' => 'LDAP', 'value' => 'ldap'},
313
+ # {'name' => 'Manual', 'value' => 'manual'}
314
+ # ]
315
+ # end
316
+
317
+ # def find_option_list_type(code)
318
+ # get_available_option_list_types.find {|it| code == it['value'] || code == it['name'] }
319
+ # end
320
+
321
+ def new_option_type_form_option_types()
322
+ [
323
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Form name'},
324
+ {'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => true, 'description' => 'Unique form code'},
325
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
326
+ {'shorthand' => '-l', 'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false, 'noPrompt' => true, 'processValue' => lambda {|val| parse_labels(val) }},
327
+ ]
328
+ end
329
+
330
+ def update_option_type_form_option_types()
331
+ list = new_option_type_form_option_types()
332
+ list.each {|it|
333
+ it.delete('required')
334
+ it.delete('defaultValue')
335
+ it.delete('skipSingleOption')
336
+ }
337
+ list
338
+ end
339
+
340
+ # CLI Form builder
341
+
342
+ def prompt_new_form(options)
343
+ form_payload = {}
344
+ form_payload = prompt(new_option_type_form_option_types(), options)
345
+ # prompt for options
346
+ form_payload['options'] = prompt_new_form_options(options)
347
+ form_payload['fieldGroups'] = prompt_new_field_groups(options)
348
+
349
+ return form_payload
350
+ end
351
+
352
+ # prompts user to define a list of new option types
353
+ # returns array of option type objects {'fieldName' => "input1", 'fieldLabel' => "Input 1"}
354
+ def prompt_new_form_options(options={}, field_group_context=nil)
355
+ #puts "Source Headers:"
356
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
357
+ option_types = []
358
+ i = 0
359
+ field_context = "option#{i+1}"
360
+ context_value_map = options[:options] # should just be options or options.deep_merge(options[:options] || {})
361
+ if field_group_context
362
+ context_value_map = context_value_map ? (context_value_map[field_group_context] || {}) : {}
363
+ end
364
+ selected_options = options[:selected_options] || [] # user passing in --options '[42,{"fieldName":"foo","fieldLabel":"Foo"}]'
365
+ # puts "selected_options: #{selected_options.inspect}"
366
+ has_another_option_type = context_value_map[field_context] || selected_options[0]
367
+ add_another_option_type = has_another_option_type || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add an Input?", {default: true}))
368
+ while add_another_option_type do
369
+ print_h2 "Input #{i+1}"
370
+ full_context = [field_group_context, field_context].select {|it| it.to_s != "" }.join('.')
371
+ option_type = prompt_new_option_type(options, selected_options[i], full_context)
372
+ print "\n"
373
+ option_types << option_type
374
+ i += 1
375
+ field_context = "option#{i+1}"
376
+ has_another_option_type = context_value_map && context_value_map[field_context]
377
+ add_another_option_type = has_another_option_type || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another Input?", {default: false}))
378
+ end
379
+
380
+ return option_types
381
+ end
382
+
383
+ def prompt_new_option_type(options, selected_value=nil, field_context=nil)
384
+ option_type = {}
385
+ if selected_value
386
+ if selected_value.is_a?(Hash)
387
+ option_type = selected_value
388
+ else
389
+ existing_option_type = find_option_type_by_name_or_id(selected_value)
390
+ raise_command_error "Option Type not found for '#{selected_value}'" if existing_option_type.nil?
391
+ option_type['id'] = existing_option_type['id']
392
+ end
393
+ return option_type
394
+ end
395
+ # Use Existing Input? then skip all other inputs
396
+ # context_value_map = field_context ? (options[:options][field_context] || {}) : {}
397
+ context_value_map = field_context ? get_object_value(options[:options], field_context) : options[:options]
398
+ if context_value_map && context_value_map['id']
399
+ context_value_map['existing'] = "on"
400
+ end
401
+ use_existing = prompt_value({'fieldContext' => field_context, 'fieldName' => 'existing', 'fieldLabel' => 'Use Existing', 'type' => 'checkbox', 'required' => true, 'defaultValue' => false, 'description' => "Use an existing input instead of customizing a new one for this form"}, options)
402
+ if use_existing.to_s == "on" || use_existing.to_s == "yes" || use_existing.to_s == "true"
403
+ existing_id = prompt_value({'fieldContext' => field_context, 'fieldName' => 'id', 'fieldLabel' => 'Existing Input', 'type' => 'select', 'optionSource' => 'optionTypes', 'required' => true, 'description' => "Choose an existing input"}, options)
404
+ option_type['id'] = existing_id.to_i
405
+ else
406
+ # prompt for a new option type
407
+ option_types = new_form_input_option_types
408
+ option_types.each {|it| it['fieldContext'] = field_context }
409
+ results = prompt(option_types, options)
410
+ results.booleanize! #.deep_compact!
411
+ # option_type = field_context ? results[field_context] : results
412
+ option_type = field_context ? get_object_value(results, field_context) : results
413
+ end
414
+ return option_type
415
+ end
416
+
417
+ # prompts user to define a list of field groups and their options
418
+ # returns array of option type objects {'fieldName' => "input1", 'fieldLabel' => "Input 1"}
419
+ def prompt_new_field_groups(options={})
420
+ #puts "Source Headers:"
421
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
422
+ field_groups = []
423
+ selected_field_groups = options[:selected_field_groups] || [] # user passing in --options '[42,{"fieldName":"foo","fieldLabel":"Foo"}]'
424
+ # puts "selected_field_groups: #{selected_field_groups.inspect}"
425
+ i = 0
426
+ field_context = "fieldGroup#{i+1}"
427
+ has_another_field_group = options[:options][field_context] || selected_field_groups[0]
428
+ add_another_field_group = has_another_field_group || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add a Field Group?", {default: false}))
429
+ while add_another_field_group do
430
+ print_h2 "Field Group #{i+1}"
431
+ field_group = prompt_new_field_group(options, selected_field_groups[i], field_context)
432
+ print "\n"
433
+ field_groups << field_group
434
+ i += 1
435
+ field_context = "fieldGroup#{i+1}"
436
+ has_another_field_group = options[:options] && options[:options][field_context]
437
+ add_another_field_group = has_another_field_group || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another Field Group?", {default: false}))
438
+ end
439
+
440
+ return field_groups
441
+ end
442
+
443
+ def prompt_new_field_group(options, selected_value=nil, field_context=nil)
444
+ field_group = {}
445
+ # if selected_value
446
+ # if selected_value.is_a?(Hash)
447
+ # field_group = selected_value
448
+ # end
449
+ # return field_group
450
+ # end
451
+
452
+ # prompt for a field group
453
+ field_group_option_types = [
454
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'This field sets the name attribute for the field group.', 'defaultValue' => 'new fieldgroup'},
455
+ # {'fieldName' => 'code', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'This field sets the code attribute for the field group.', 'defaultValue' => SecureRandom.uuid},
456
+ # {'fieldName' => 'localizedName', 'fieldLabel' => 'Localized Name', 'type' => 'typeahead', 'optionSource' => 'messageCodes', 'description' => 'i18n code for the name'},
457
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'description' => 'This field sets the name attribute for the input.'},
458
+ {'fieldName' => 'collapsible', 'fieldLabel' => 'Collapsible', 'type' => 'checkbox', 'defaultValue' => true, 'description' => 'Field group is collapsible'},
459
+ {'fieldName' => 'defaultCollapsed', 'fieldLabel' => 'Default Collapsed', 'type' => 'checkbox', 'defaultValue' => true, 'description' => 'Collapse field group by default'},
460
+ {'fieldName' => 'visibleOnCode', 'fieldLabel' => 'Visibility Field', 'type' => 'text', 'description' => 'A fieldName that will trigger visibility of this field group'},
461
+ ]
462
+ field_group_option_types.each {|it| it['fieldContext'] = field_context }
463
+ results = prompt(field_group_option_types, options)
464
+ results.booleanize! #.deep_compact!
465
+ field_group = field_context ? results[field_context] : results
466
+ field_group['code'] = SecureRandom.uuid unless field_group['code']
467
+ # prompt for options
468
+ field_group['options'] = prompt_new_form_options(options, field_context)
469
+
470
+ return field_group
471
+ end
472
+
473
+ # not used yet
474
+ def prompt_edit_form(form, params, options)
475
+ form_payload = {}
476
+ selected_options = options[:selected_options] || [] # user passing in --options [42,{"fieldName":"foo","fieldLabel":"Foo"}]
477
+ # this prompts for an action for each option on the list: keep, edit, remove
478
+ new_options = []
479
+ Array(form['options']).each_with_index do |option_type, i|
480
+
481
+ field_context = i == 0 ? "option" : "option#{i+1}"
482
+ results = prompt_edit_option_type(option_type, options, selected_options[i], field_context)
483
+ if results.nil?
484
+ # deleted
485
+ next
486
+ end
487
+ new_options << results[field_context]
488
+ end
489
+ form_payload['options'] = new_options
490
+
491
+ # todo: fieldGroups
492
+ Array(form['fieldGroups']).each do |option_type|
493
+ end
494
+
495
+
496
+ return form_payload
497
+ end
498
+
499
+ def prompt_edit_option_type(current_option_type, options, selected_value=nil, field_context=nil)
500
+ option_type = {'id' => current_option_type['id']}
501
+ # if selected_value
502
+ # if selected_value.is_a?(Hash)
503
+ # option_type = selected_value
504
+ # else
505
+ # existing_option_type = find_option_type_by_name_or_id(selected_value)
506
+ # raise_command_error "Option Type not found for '#{selected_value}'" if existing_option_type.nil?
507
+ # option_type['id'] = existing_option_type['id']
508
+ # end
509
+ # return option_type
510
+ # end
511
+
512
+ action_options = [{'name' => 'Modify', 'value' => 'modify'}, {'name' => 'Keep', 'value' => 'keep'}, {'name' => 'Delete', 'value' => 'delete'}]
513
+ v_prompt = prompt([{'fieldContext' => field_context, 'fieldName' => 'action', 'type' => 'select', 'fieldLabel' => "Modify/Keep/Delete Input '#{current_option_type['fieldLabel']}' (ID: #{current_option_type['id']})", 'selectOptions' => action_options, 'required' => true, 'defaultValue' => 'keep', 'description' => 'Modify, Keep or Remove form input?'}], options[:options])
514
+ action = v_prompt[field_context]['action']
515
+
516
+ if action == 'delete'
517
+ # deleted input is just excluded from list
518
+ option_type = nil
519
+ elsif action == 'keep'
520
+ # no changes
521
+ elsif action == 'modify'
522
+ # Modify existing input
523
+
524
+ # Use Existing Input?
525
+ # If yes then then skip all other inputs
526
+ if options[:options][field_context] && options[:options][field_context]['id']
527
+ options[:options][field_context]['existing'] = "on"
528
+ end
529
+ use_existing = prompt_value({'fieldContext' => field_context, 'fieldName' => 'existing', 'fieldLabel' => 'Use Existing', 'type' => 'checkbox', 'required' => true, 'defaultValue' => (current_option_type['formField'] ? false : true), 'description' => "Use an existing input instead of customizing a new one for this form"}, options)
530
+ if use_existing.to_s == "on" || use_existing.to_s == "yes" || use_existing.to_s == "true"
531
+ existing_id = prompt_value({'fieldContext' => field_context, 'fieldName' => 'id', 'fieldLabel' => 'Existing Input', 'type' => 'select', 'optionSource' => 'optionTypes', 'required' => true, 'defaultValue' => (current_option_type['formField'] ? nil : current_option_type['name']), 'description' => "Choose an existing input"}, options)
532
+ option_type['id'] = existing_id.to_i
533
+ else
534
+ # prompt to edit the existing option type
535
+ option_types = update_form_input_option_types
536
+ option_types.each {|it| it['fieldContext'] = field_context }
537
+ results = prompt(option_types, options)
538
+ results.booleanize! #.deep_compact!
539
+ if field_context
540
+ results = results[field_context]
541
+ end
542
+ option_type.deep_merge!(results) if results
543
+ end
544
+ end
545
+
546
+ return option_type
547
+ end
548
+
549
+ def new_form_input_option_types()
550
+ [
551
+ {'code' => 'optionType.type', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => get_available_form_input_types(), 'defaultValue' => 'text', 'required' => true},
552
+ {'fieldName' => 'optionList', 'fieldLabel' => 'Option List', 'type' => 'select', 'optionSource' => 'optionTypeLists', 'required' => true, 'dependsOnCode' => 'optionType.type:select', 'description' => "The Option List to be the source of options when type is 'select'."},
553
+ {'fieldName' => 'fieldLabel', 'fieldLabel' => 'Field Label', 'type' => 'text', 'required' => true, 'description' => 'This is the input label that shows typically to the left of a custom option.'},
554
+ {'fieldName' => 'fieldCode', 'fieldLabel' => 'Localized Label', 'type' => 'typeahead', 'optionSource' => 'messageCodes', 'description' => 'i18n code for the label'},
555
+ {'fieldName' => 'fieldName', 'fieldLabel' => 'Field Name', 'type' => 'text', 'required' => true, 'description' => 'This field sets the name attribute for the input.'},
556
+ {'fieldName' => 'defaultValue', 'fieldLabel' => 'Default Value', 'type' => 'text', :preprocesser => lambda do |option_type, api_client, api_params|
557
+ input_type = option_type['fieldContext'] ? api_params[option_type['fieldContext']]['type'] : api_params['type']
558
+ if input_type == 'checkbox'
559
+ # option_type.merge!({'type' => 'select', 'selectOptions' => [{"name" => "On", "value" => "on"},{"name" => "Off", "value" => "off"}]})
560
+ option_type.merge!({'type' => 'checkbox'})
561
+ end
562
+ end
563
+ },
564
+ {'fieldName' => 'placeHolder', 'fieldLabel' => 'Placeholder', 'type' => 'text', 'description' => 'Text that is displayed when the field is empty'},
565
+ {'fieldName' => 'helpBlock', 'fieldLabel' => 'Help Block', 'type' => 'text', 'description' => 'This is the explaination of the input that shows typically underneath the option.'},
566
+ {'fieldName' => 'helpBlockFieldCode', 'fieldLabel' => 'Localized Help Block', 'type' => 'typeahead', 'optionSource' => 'messageCodes', 'description' => 'i18n code for the help block'},
567
+ {'fieldName' => 'required', 'fieldLabel' => 'Required', 'type' => 'checkbox', 'defaultValue' => false},
568
+ {'fieldName' => 'exportMeta', 'fieldLabel' => 'Export As Tag', 'type' => 'checkbox', 'defaultValue' => false, 'description' => 'Export as Tag'},
569
+ {'fieldName' => 'displayValueOnDetails', 'fieldLabel' => 'Display Value On Details', 'type' => 'checkbox', 'defaultValue' => false},
570
+ {'fieldName' => 'isLocked', 'fieldLabel' => 'Locked', 'type' => 'checkbox', 'defaultValue' => false},
571
+ {'fieldName' => 'isHidden', 'fieldLabel' => 'Hidden', 'type' => 'checkbox', 'defaultValue' => false},
572
+ {'fieldName' => 'excludeFromSearch', 'fieldLabel' => 'Exclude From Search', 'type' => 'checkbox', 'defaultValue' => false},
573
+ # Advanced
574
+ {'fieldName' => 'dependsOnCode', 'fieldLabel' => 'Dependent Field', 'type' => 'text', 'description' => 'A fieldName that will trigger reloading this input'},
575
+ {'fieldName' => 'visibleOnCode', 'fieldLabel' => 'Visibility Field', 'type' => 'text', 'description' => 'A fieldName that will trigger visibility of this input'},
576
+ {'fieldName' => 'verifyPattern', 'fieldLabel' => 'Verify Pattern', 'type' => 'text', 'dependsOnCode' => 'optionType.type:text', 'description' => 'A regexp string that validates the input, use (?i) to make the matcher case insensitive'},
577
+ {'fieldName' => 'requireOnCode', 'fieldLabel' => 'Require Field', 'type' => 'text', 'description' => 'A fieldName that will trigger required attribute of this input'},
578
+ ]
579
+ end
580
+
581
+ def update_form_input_option_types()
582
+ list = new_option_type_form_option_types()
583
+ list.each {|it|
584
+ it.delete('required')
585
+ it.delete('defaultValue')
586
+ it.delete('skipSingleOption')
587
+ }
588
+ list
589
+ end
590
+
591
+ def get_available_form_input_types()
592
+ {
593
+ checkbox: "Checkbox",
594
+ hidden: "Hidden",
595
+ number: "Number",
596
+ password: "Password",
597
+ radio: "Radio",
598
+ select: "Select List",
599
+ text: "Text",
600
+ textarea: "Textarea",
601
+ byteSize: "Byte Size",
602
+ 'code-editor': "Code Editor",
603
+ fileContent: "File Content",
604
+ logoSelector: "Icon Picker",
605
+ keyValue: "Key Value",
606
+ textArray: "Text Array",
607
+ typeahead: "Typeahead",
608
+ cloud: "Cloud",
609
+ diskManager: "Disks",
610
+ environment: "Environment",
611
+ ports: "Exposed Ports",
612
+ group: "Group",
613
+ 'instances-input': "Instances",
614
+ layout: "Layout",
615
+ networkManager: "Networks",
616
+ plan: "Plan",
617
+ resourcePool: "Resource Pool",
618
+ secGroup: "Security Groups",
619
+ 'servers-input': "Servers",
620
+ 'virtual-image': "Virtual Image",
621
+ vmwFolders: "Vmw Folders",
622
+ httpHeader: "Headers",
623
+ }.collect {|k,v| {'name' => v.to_s, 'value' => k.to_s } }
624
+ end
625
+ end