Skip to content

Commit

Permalink
Merge 6e12737 into f72d334
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Feb 22, 2019
2 parents f72d334 + 6e12737 commit 7e6077e
Show file tree
Hide file tree
Showing 27 changed files with 1,213 additions and 118 deletions.
96 changes: 90 additions & 6 deletions src/lib/y2configuration_management/salt/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,12 @@ def initialize(controller, form)
def build(locator)
form_element = form.find_element_by(locator: locator.unbounded)
form_element = form_element.prototype if form_element.is_a?(Collection)
scalar = !form_element.respond_to?(:elements)
root_locator = form_element.is_a?(Container) ? locator : locator.parent
elements = scalar ? [form_element] : form_element.elements
widgets = Array(elements).map { |e| build_element(e, root_locator) }
Y2ConfigurationManagement::Widgets::Form.new(
widgets, controller, scalar: scalar
)
if form_element.respond_to?(:elements)
build_form(form_element, root_locator, controller)
else
build_single_value_form(form_element, root_locator)
end
end

private
Expand Down Expand Up @@ -125,6 +124,91 @@ def build_input(input_spec, locator)
def build_collection(collection_spec, locator)
Y2ConfigurationManagement::Widgets::Collection.new(collection_spec, controller, locator)
end

# @param form_element [FormElement] Form element to include in the form
# @param locator [FormElementLocator] Form element locator
# @return [Y2ConfigurationManagement::Widgets::Form]
def build_single_value_form(form_element, locator)
widget = build_element(form_element, locator)
Y2ConfigurationManagement::Widgets::SingleValueForm.new(widget, title: form_element.name)
end

# @param form_element [FormElement] Root form element for the form
# @param locator [FormElementLocator] Form element locator
# @param controller [FormController] Controller to inject into the form
# @return [Y2ConfigurationManagement::Widgets::Form]
def build_form(form_element, locator, controller)
tree_pager = build_tree_pager(form_element, locator)
Y2ConfigurationManagement::Widgets::Form.new(
tree_pager, controller, title: form_element.name
)
end

# Builds a tree pager for a form
#
# The root element (Form#root) is excluded from the tree. However, when building
# a pager for any other container, that container should be taken into account.
# Additionally, the root element cannot contain simple input elements (usually it
# contains just one container).
#
# See #build_root_tree_items and #build_container_tree_items for the details.
#
# @param form_element [FormElement] Form element
# @param locator [FormElementLocator] Form element locator
def build_tree_pager(form_element, locator)
tree_items =
if form_element.parent.nil?
build_root_tree_items(form_element)
else
build_container_tree_item(form_element, locator)
end

Widgets::TreePager.new(Array(tree_items))
end

# Builds tree pager items for the root element
#
# @param form_element [FormElement] Root form element
# @return [Array<Widgets::PagerTreeItem>]
def build_root_tree_items(form_element)
form_element.elements.map { |e| build_tree_item(e, e.locator) }
end

# Builds tree pager item for a container
#
# @param form_element [FormElement] Form element
# @param locator [FormElementLocator] Form element locator
# @return [Widgets::PagerTreeItem]
def build_container_tree_item(form_element, locator)
build_tree_item(form_element, locator).tap { |t| t.main = true }
end

# Builds a tree item for a given form element
#
# @param form_element [FormElement] Form element
# @param locator [FormElementLocator] Form element locator
# @return [Widgets::PagerTreeItem]
def build_tree_item(form_element, locator)
if form_element.respond_to?(:elements)
same_page, other_page = form_element.elements.partition { |e| shared_page?(e) }
else
same_page = [form_element]
other_page = []
end

widgets = same_page.map { |e| build_element(e, locator) }
children = other_page.map { |e| build_tree_item(e, locator.join(e.id.to_sym)) }

page = Widgets::Page.new(locator.last.to_s, form_element.name, widgets)
Widgets::PagerTreeItem.new(page, children: children)
end

# Determines whether a form element should be placed in a different page or share one
#
# @return [Boolean]
def shared_page?(form_element)
form_element.is_a?(FormInput) || form_element.type == :namespace
end
end
end
end
2 changes: 1 addition & 1 deletion src/lib/y2configuration_management/salt/form_condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def initialize(locator:, value:)
# @param context [FormElement] for resolving relative expressions
def evaluate(data, context:)
left_locator = @locator.relative? ? context.locator.join(@locator) : @locator
left = data.get(left_locator).to_s
left = data.get(left_locator).value.to_s
right = @value.to_s
left == right
end
Expand Down
2 changes: 1 addition & 1 deletion src/lib/y2configuration_management/salt/form_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def update(locator, value)
# @param value [Object] Value to add
def add_item(locator, value)
collection = find_by_locator(@data, locator)
collection.push(value)
collection.push(value.value)
end

# @param locator [FormElementLocator] Locator of the collection
Expand Down
7 changes: 6 additions & 1 deletion src/lib/y2configuration_management/widgets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,22 @@

require "y2configuration_management/widgets/base_mixin"
require "y2configuration_management/widgets/boolean"
require "y2configuration_management/widgets/color"
require "y2configuration_management/widgets/collection"
require "y2configuration_management/widgets/color"
require "y2configuration_management/widgets/date"
require "y2configuration_management/widgets/date_time"
require "y2configuration_management/widgets/email"
require "y2configuration_management/widgets/form"
require "y2configuration_management/widgets/group"
require "y2configuration_management/widgets/key_value"
require "y2configuration_management/widgets/number"
require "y2configuration_management/widgets/page"
require "y2configuration_management/widgets/pager_tree_item"
require "y2configuration_management/widgets/password"
require "y2configuration_management/widgets/select"
require "y2configuration_management/widgets/single_value_form"
require "y2configuration_management/widgets/text"
require "y2configuration_management/widgets/time"
require "y2configuration_management/widgets/tree"
require "y2configuration_management/widgets/tree_pager"
require "y2configuration_management/widgets/url"
7 changes: 7 additions & 0 deletions src/lib/y2configuration_management/widgets/base_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ def relative_locator
return parent.relative_locator.join(id.to_sym) if respond_to?(:parent) && parent
Y2ConfigurationManagement::Salt::FormElementLocator.new([])
end

# Minimal height
#
# @return [Integer]
def min_height
2
end
end
end
end
30 changes: 25 additions & 5 deletions src/lib/y2configuration_management/widgets/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,22 @@ def initialize(spec, controller, data_locator)
self.value = []
end

# Reserve some lines for buttons
BUTTONS_HEIGHT = 1

# Widget contents
#
# @return [Term]
def contents
VBox(
Table(
Id("table:#{locator}"),
Opt(:notify, :immediate),
Header(*headers),
[]
MinHeight(
min_height - BUTTONS_HEIGHT,
Table(
Id("table:#{locator}"),
Opt(:notify, :immediate),
Header(*headers),
[]
)
),
HBox(
HStretch(),
Expand All @@ -101,6 +107,13 @@ def handle_all_events
true
end

# Returns the relative locator
#
# @return [FormElementLocator]
def relative_locator
parent.relative_locator
end

# Events handler
#
# @todo Partially implemented only
Expand All @@ -125,6 +138,13 @@ def validate
false
end

# Minimal height
#
# @return [Integer]
def min_height
18
end

private

# @return [Array<String>] Header identifiers
Expand Down
2 changes: 1 addition & 1 deletion src/lib/y2configuration_management/widgets/date_time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def value
end

def value=(val)
t = val.strip.to_s.empty? ? ::Time.new : ::Time.parse(val)
t = val.to_s.strip.empty? ? ::Time.new : ::Time.parse(val)
date_value = t.strftime("%Y-%m-%d")
time_value = t.strftime("%H:%M:%S")
date.value = date_value
Expand Down
77 changes: 18 additions & 59 deletions src/lib/y2configuration_management/widgets/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ module Widgets
# * and storing the final result (see #store and #result).
# It is able
class Form < ::CWM::CustomWidget
# @return [Array<CWM::AbstractWidget>] Widgets included in the form
attr_reader :children
# @return [PagerTree] Widgets included in the form
attr_reader :tree_pager
# @return [Hash] Form values from included widgets when this one is removed from the UI
attr_reader :result
# @return [String] Form title
Expand All @@ -46,12 +46,9 @@ class Form < ::CWM::CustomWidget
# form.value = { "ranges" => [ { "start" => "10.0.0.10", "end" => "10.0.0.20" } ] }
attr_accessor :value

attr_reader :scalar

# Constructor
#
# Usually, a form stores a set of keys and values. However, it is possible to define a
# "scalar" form, which holds a single value only.
# A form stores a set of keys and values.
#
# @example Regular form
# form.value = { "name" => "John Doe" }
Expand All @@ -63,14 +60,12 @@ class Form < ::CWM::CustomWidget
# form.store
# form.result #=> "John Doe"
#
# @param children [Array<CWM::AbstractWidget>] Widgets included in the form
# @param tree_pager [PagerTree] Widgets included in the form
# @param controller [Salt::FormController] Form controller
# @param scalar [Boolean] Determines whether the form stores are scalar value
# @param title [String] Form title
def initialize(children, controller, scalar: false, title: "")
@value = scalar ? nil : {}
@scalar = scalar
add_children(*children)
def initialize(tree_pager, controller, title: "")
@value = {}
@tree_pager = tree_pager
@controller = controller
@title = title
self.handle_all_events = true
Expand All @@ -82,14 +77,14 @@ def initialize(children, controller, scalar: false, title: "")
#
# @see CWM::AbstractWidget#init
def init
set_widgets_content
set_children_contents
end

# Widget's content
#
# @see CWM::AbstractWidget
def contents
VBox(*children)
VBox(tree_pager)
end

# Stores the widget's value
Expand All @@ -99,6 +94,7 @@ def contents
#
# @see CWM::AbstractWidget
def store
tree_pager.store
@result = current_values
end

Expand All @@ -107,9 +103,7 @@ def store
# @return [Hash] values including the ones from the underlying widgets; values are
# `nil` when the form has been removed from the UI.
def current_values
return children_values unless scalar?
first_value = children_values.values.first
first_value.is_a?(Hash) ? first_value : { "$value" => first_value }
tree_pager.value
end

# Refreshes the widget's content
Expand All @@ -127,61 +121,26 @@ def handle
end

def update_visibility(data)
children.each do |widget|
widgets.each do |widget|
widget.update_visibility(data) if widget.respond_to? :update_visibility
end
end

# Add children widgets
#
# @param widgets [Array<CWM::AbstractWidget>] Widgets to add to the form
def add_children(*widgets)
@children ||= []
widgets.each { |w| w.parent = self }
@children.concat(widgets)
end

def relative_locator
Y2ConfigurationManagement::Salt::FormElementLocator.new([])
end

def scalar?
@scalar
end

private

# Returns children values
# Return all widgets
#
# @return [Hash] Hash containing the children ids and their values
def children_values
children.reduce({}) { |a, e| a.merge(e.id => e.value) }
# @return [Array<::CWM::AbstractWidget>]
def widgets
tree_pager.widgets
end

def set_widgets_content
if scalar?
set_child_content
else
set_children_contents
end
end

def set_child_content
children.first.value = value.key?("$key") ? value : value["$value"]
end
private

def set_children_contents
set_children_contents_precond!
children.each do |widget|
widget.value = value[widget.id] if value[widget.id]
end
end

def set_children_contents_precond!
child_ids = children.map(&:id).sort
value_keys = value.keys.sort
return if value_keys.all? { |k| child_ids.include?(k) }
raise "Form expects ids #{child_ids}, got #{value_keys}"
tree_pager.refresh(value)
end
end
end
Expand Down

0 comments on commit 7e6077e

Please sign in to comment.