Skip to content

Commit

Permalink
Merge 49a96be into 96fe140
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Dec 12, 2018
2 parents 96fe140 + 49a96be commit 8b8995a
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 73 deletions.
53 changes: 38 additions & 15 deletions src/lib/y2configuration_management/salt/form_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require "y2configuration_management/salt/form_builder"
require "y2configuration_management/salt/form_data"
require "y2configuration_management/widgets/form_popup"
require "yaml"

Yast.import "CWM"
Yast.import "Wizard"
Expand Down Expand Up @@ -58,18 +59,29 @@ def show_main_dialog
# Convenience method for returning the value of a given element
#
# @param path [String] Path to the element
def get(path)
@data.get(path)
# @param index [Integer] Element's index when path refers to a collection
def get(path, index = nil)
@data.get(path, index)
end

# Opens a new dialog in order to add a new element to a collection
#
# @param path [String] Collection's path
def add(path)
element = form.find_element_by(path: path).prototype
result = show_popup(element.name, form_builder.build(element))
result = edit_item(path, {})
return if result.nil?
@data.add(path, result.values.first)
@data.add_item(path, result.values.first)
refresh_main_form
end

# Opens a new dialog in order to edit an element within a collection
#
# @param path [String] Collection's path
# @param index [Integer] Element's index
def edit(path, index)
result = edit_item(path, get(path, index))
return if result.nil?
@data.update_item(path, index, result.values.first)
refresh_main_form
end

Expand All @@ -78,7 +90,7 @@ def add(path)
# @param path [String] Collection's path
# @param index [Integer] Element's index
def remove(path, index)
@data.remove(path, index)
@data.remove_item(path, index)
refresh_main_form
end

Expand All @@ -98,14 +110,15 @@ def form_builder

# Renders the main form's dialog
def main_form
widget_form = form_builder.build(form.root.elements)
widget_form.value = get(form.root.path)
widget_form
return @main_form if @main_form
@main_form = form_builder.build(form.root.elements)
@main_form.value = get(form.root.path)
@main_form
end

# Refreshes the main form content
def refresh_main_form
replace_point.replace(main_form)
main_form.refresh(get(form.root.path))
end

# Replace point to place the main dialog
Expand All @@ -115,6 +128,18 @@ def replace_point
@replace_point ||= ::CWM::ReplacePoint.new(widget: main_form)
end

# Displays a form to edit a given item
#
# @param path [String] Collection path
# @param item [Object] Item to edit
# @return [Hash,nil] edited data; `nil` when the user cancels the dialog
def edit_item(path, item)
element = form.find_element_by(path: path)
widget_form = form_builder.build(element.prototype)
widget_form.value = item
show_popup(element.name, widget_form)
end

# Displays a popup
#
# @param title [String] Popup title
Expand All @@ -129,11 +154,9 @@ def show_popup(title, widget)
# version.
def next_handler
return false unless Yast::Popup.YesNo("Do you want to exit?")
# This does not work. should main_form be memoized?
# main_form.store
# data.update(form.root.path, main_form.result)
data.update(form.root.path, main_form.store)
puts data.to_h.inspect
main_form.store
data.update(form.root.path, main_form.result)
puts YAML.dump(data.to_h)
true
end
end
Expand Down
33 changes: 21 additions & 12 deletions src/lib/y2configuration_management/salt/form_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,9 @@ def initialize(form)
# Returns the value of a given element
#
# @param path [String] Path to the element
def get(path)
@data.dig(*path_to_parts(path)) || default_for(path)
end

# Adds an element to a collection
#
# @param path [String] Path to the collection
# @param value [Hash] Value to add
def add(path, value)
collection = get(path)
collection.push(value)
def get(path, index = nil)
value = @data.dig(*path_to_parts(path)) || default_for(path)
index ? value.at(index) : value
end

# Updates an element's value
Expand All @@ -64,11 +56,28 @@ def update(path, value)
parent[parts.last] = value
end

# Adds an element to a collection
#
# @param path [String] Path to the collection
# @param value [Hash] Value to add
def add_item(path, value)
collection = get(path)
collection.push(value)
end

# @param path [String] Path to the collection
# @param index [Integer] Position of the element to remove
# @param value [Object] New value
def update_item(path, index, value)
collection = get(path)
collection[index] = value
end

# Removes an element from a collection
#
# @param path [String] Path to the collection
# @param index [Integer] Position of the element to remove
def remove(path, index)
def remove_item(path, index)
collection = get(path)
collection.delete_at(index)
end
Expand Down
50 changes: 31 additions & 19 deletions src/lib/y2configuration_management/widgets/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ module Widgets
# This widget uses a table to display a collection of elements and offers
# buttons to add, remove and edit them.
class Collection < ::CWM::CustomWidget
attr_reader :label, :min_items, :max_items, :controller, :path, :id
attr_reader :label, :min_items, :max_items, :controller, :path, :id, :headers

# @return [Array<String>] Headers for the collection table
attr_reader :headers

# @return [Array<Object>] List of objects which are included in the collection
attr_accessor :value

Expand All @@ -43,6 +47,7 @@ def initialize(spec, controller)
@controller = controller
@path = spec.path # form element path
@id = spec.id
@headers, @headers_ids = headers_from_prototype(spec.prototype)
self.widget_id = "collection:#{spec.id}"
self.value = []
end
Expand All @@ -56,7 +61,7 @@ def contents
Id("table:#{path}"),
Opt(:notify, :immediate),
Header(*headers),
items_list
[]
),
HBox(
HStretch(),
Expand All @@ -67,6 +72,14 @@ def contents
)
end

# Sets the value
#
# @param items_list [Array<Hash>] Collection items
def value=(items_list)
Yast::UI.ChangeWidget(Id("table:#{path}"), :Items, format_items(items_list))
@value = items_list
end

# Forces the widget to inspect all events
#
# @return [TrueClass]
Expand All @@ -84,11 +97,8 @@ def handle(event)
when "#{widget_id}_add".to_sym
controller.add(path)
when "#{widget_id}_edit".to_sym
# TODO
# controller.edit(path, selected_row) if selected_row
controller.edit(path, selected_row) if selected_row
when "#{widget_id}_remove".to_sym
# TODO
# controller.remove(path, selected_row) if selected_row
controller.remove(path, selected_row) if selected_row
end

Expand All @@ -97,6 +107,9 @@ def handle(event)

private

# @return [Array<String>] Header identifiers
attr_reader :headers_ids

# Returns the index of the selected row
#
# @return [Integer,nil] Index of the selected row or nil if no row is selected
Expand All @@ -105,25 +118,24 @@ def selected_row
row_id ? row_id.to_i : nil
end

# Returns the headers for the collection table
#
# @todo Get this information from the formula spec
#
# @return [Array<String>]
def headers
return unless value.first
value.first.keys
end

# Format the items list for the colletion table
#
# @return [Array<Array<String|Yast::Term>>]
def items_list
value.each_with_index.map do |item, index|
values = headers.map { |h| item[h] }
def format_items(items_list)
items_list.each_with_index.map do |item, index|
values = headers_ids.map { |h| item[h] }
Item(Id(index.to_s), *values)
end
end

# Returns the list of headers names and IDs from the prototype spec
#
# @param prototype [FormElement] Prototype definition
def headers_from_prototype(prototype)
names = prototype.elements.map { |h| (h.name || h.id) }
ids = prototype.elements.map(&:id)
[names, ids]
end
end
end
end
39 changes: 27 additions & 12 deletions src/lib/y2configuration_management/widgets/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,26 @@ class Form < ::CWM::CustomWidget
# @return [Hash] Form values from included widgets when this one is removed from the UI
attr_reader :result

# @example Setting values for included widgets
# form.value = { "name" => "John", "surname" => "Doe" }
# @example Setting values for nested widgets
# form.value = { "ranges" => [ { "start" => "10.0.0.10", "end" => "10.0.0.20" } ] }
attr_accessor :value

# Constructor
#
# @param children [Array<CWM::AbstractWidget>] Widgets included in the form
def initialize(children)
@children = children
@value = {}
end

# Sets the value for the form
#
# This method propagates the values to the underlying widgets.
# The values are defined using the `#value=` method.
#
# @example Setting values for included widgets
# form.value = { "name" => "John", "surname" => "Doe" }
# @example Setting values for nested widgets
# form.value = { "ranges" => [ { "start" => "10.0.0.10", "end" => "10.0.0.20" } ] }
#
# @param value [Hash] New value
def value=(value)
children.each do |widget|
widget.value = value[widget.id]
end
# @see CWM::AbstractWidget#init
def init
set_children_contents
end

# Widget's content
Expand All @@ -75,6 +74,22 @@ def contents
def store
@result = children.reduce({}) { |a, e| a.merge(e.id => e.value) }
end

# Refreshes the widget's content
#
# @param values [Hash] New values
def refresh(values)
self.value = values
set_children_contents
end

private

def set_children_contents
children.each do |widget|
widget.value = value[widget.id] if value[widget.id]
end
end
end
end
end
2 changes: 1 addition & 1 deletion src/lib/y2configuration_management/widgets/select.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def initialize(spec, controller)

# @see CWM::AbstractWidget
def init
return if default.nil?
return if default.nil? || !value.nil?
item = items.find { |_i, v| v == default }
self.value = item.first if item
end
Expand Down
7 changes: 6 additions & 1 deletion src/lib/y2configuration_management/widgets/text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ def initialize(spec, controller)

# @see CWM::AbstractWidget
def init
self.value = default
self.value = default if value.nil? || value.empty?
end

# @see CWM::ValueBasedWidget
def value=(val)
super(val.to_s)
end
end
end
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/form.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ person:
"$prototype":
$type: group
brand:
"$name": Brand
"$default": Dell
"$type": select
"$values":
Expand Down

0 comments on commit 8b8995a

Please sign in to comment.