motion-prime 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTdmYjFmM2NhYWE3ZGQyNzFjYWZjYjg2NzUzOTFkMTkwZmVjYTBjMw==
4
+ NTVhZjliNTBlNWFkYWY5ODA2NGEzYmFiYmQ2OTZlMTUwODZjNzNkNw==
5
5
  data.tar.gz: !binary |-
6
- NmI1OTFjNGRmYmZjOTYyNWExOGJlMjQ4YjVjYzc4M2M0Y2M3ZWQ4Zg==
6
+ YmRkODY4MTE5ZmUzNDZiMzE1YmU0MGVhN2YxOTQyOTgzM2YxOGY2Yg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ODdiZTc3ZmIyM2ZlZDJhOTg1YTU2OGEyODFhZWE5MGI2NWUzY2ZiYTQ5NzU5
10
- ZGFlYmRkZDllYjY4MjA4YjA3YTE5YmZlNmE4NjU5Zjk3OTVhNTJkM2IwMDI4
11
- NGIzYTRjYzg5MzBhMmM1NjY0NmJmY2U4MWMzN2JiODczZWNmMjY=
9
+ MmJiMTg3YmM4ZjIxNGNhZWM5Njc5NzEwNmIyNTI4MTMyYzk0ODRiYzQzZTRm
10
+ MWIwNzdkNTBmMmM3NWZiYTNjNmY4NTRiZWUzZDVmODY5NTI4ZWRiNzY0MWVj
11
+ NzNlYTZkMTQ3YTMyOTFhOGZiYmM5ZDk0OWZhNzkyMzczMzJlMTk=
12
12
  data.tar.gz: !binary |-
13
- MjBiMDY2NTg1ZWM1OGU3ZDUzYTcyYmY5YTgyMWVlNmE2M2EzYTE0YjVmYjBk
14
- YzExOTI5ZDQ3MDZlN2Q1MDkwNjE0ZTU0OTRlM2Q1NjA2Y2ZmNThmZmUxNzUy
15
- OThlMzU4NTI5ZDJkOTIwMmE3MDA2OTZkM2I2OTAwZDViY2ZmMzU=
13
+ YTY0NjliMWM1Y2Q4NGMyMjc3OTcwOThjNTUxNGYxM2JiNjc0NzVkZTdlZmI4
14
+ NjliNjlmZjJjNTVjN2Q1ZjU5MjBlYzdlNmNkMjEzM2FkNjgwZDU0YjI5Mzcw
15
+ YTM1ZjE3ZjJjOWE5NTI1ODAwN2M2OTMwNjBkN2VlMGEyOGExYjE=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ === 0.2.1
2
+ * Bug fixes
3
+
1
4
  === 0.2.0
2
5
  * MP::BaseModel improvements
3
6
  * Added ability to observe form field errors
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.2.0)
4
+ motion-prime (0.2.1)
5
5
  bubble-wrap
6
6
  cocoapods
7
7
  motion-cocoapods
@@ -5,7 +5,7 @@ module MotionPrime
5
5
  end
6
6
 
7
7
  def [](key)
8
- fetch(key.to_sym) || store(key, self.class.new)
8
+ @attributes.has_key?(key.to_sym) ? fetch(key) : store(key, self.class.new)
9
9
  end
10
10
 
11
11
  def store(key, value)
@@ -26,6 +26,10 @@ module MotionPrime
26
26
  !self[key].is_a?(self.class)
27
27
  end
28
28
 
29
+ def to_hash
30
+ @attributes
31
+ end
32
+
29
33
  class << self
30
34
  def method_missing(name, *args, &block)
31
35
  @base_config ||= self.new()
@@ -31,6 +31,7 @@ module MotionPrime
31
31
 
32
32
  def render!(&block)
33
33
  @view = screen.add_view view_class.constantize, computed_options, &block
34
+ @view
34
35
  end
35
36
 
36
37
  # Lazy-computing options
@@ -0,0 +1,7 @@
1
+ module MotionPrime
2
+ class MapElement < BaseElement
3
+ def view_class
4
+ "MKMapView"
5
+ end
6
+ end
7
+ end
@@ -18,6 +18,8 @@ module MotionPrime
18
18
  # @param [String] name - the name of bag
19
19
  # @return [Nil]
20
20
  def bag(name)
21
+ klass = self
22
+
21
23
  define_method(name) do |*args, &block|
22
24
  return _bags[name] if _bags[name]
23
25
 
@@ -61,7 +63,6 @@ module MotionPrime
61
63
 
62
64
  define_method("#{association_name}=") do |value|
63
65
  self.send(bag_name).clear
64
-
65
66
  self.send(:"#{bag_name}") << value
66
67
  value
67
68
  end
@@ -93,21 +94,27 @@ module MotionPrime
93
94
  define_method("#{association_name}_attributes=") do |value|
94
95
  self.send(bag_name).clear
95
96
 
96
- association = []
97
- value.each do |attrs|
97
+ pending_save_counter = 0
98
+ collection = value.inject({}) do |result, attrs|
98
99
  model = association_name.classify.constantize.new
99
100
  model.fetch_with_attributes(attrs)
100
- association << model
101
+ unique_key = model.id || "pending_#{pending_save_counter+=1}"
102
+ result.merge(unique_key => model)
101
103
  end
102
- self.send(:"#{bag_name}=", association)
103
- association
104
+ association_data = collection.values
105
+ self.send(:"#{bag_name}=", association_data)
106
+ association_data
104
107
  end
105
108
  define_method("#{association_name}=") do |value|
106
109
  self.send(bag_name).clear
107
110
  self.send(:"#{bag_name}=", value)
108
111
  end
109
- define_method("#{association_name}") do
110
- self.send(:"#{bag_name}").to_a
112
+ define_method("#{association_name}") do |options = {}|
113
+ bag = self.send(:"#{bag_name}")
114
+ collection_options = {
115
+ association_name: association_name
116
+ }
117
+ AssociationCollection.new(bag, collection_options, options)
111
118
  end
112
119
  end
113
120
  end
@@ -0,0 +1,43 @@
1
+ module MotionPrime
2
+ class AssociationCollection < ::Array
3
+ attr_reader :bag
4
+
5
+ delegate :<<, to: :bag
6
+
7
+ def initialize(bag, options, fetch_options = {})
8
+ @bag = bag
9
+ @association_name = options[:association_name]
10
+ super(all(fetch_options))
11
+ end
12
+
13
+ def all(fetch_options = {})
14
+ data = bag.to_a
15
+ if sort_options = sort_options(fetch_options[:sort])
16
+ data = data.sort do |a, b|
17
+ left = []
18
+ right = []
19
+ sort_options.each do |key, order|
20
+ if order == :desc
21
+ left << b.send(key)
22
+ right << a.send(key)
23
+ else
24
+ left << a.send(key)
25
+ right << b.send(key)
26
+ end
27
+ end
28
+ left <=> right
29
+ end
30
+ end
31
+ data
32
+ end
33
+
34
+ def sort_options(options)
35
+ return options if options
36
+ model_class.default_sort_options
37
+ end
38
+
39
+ def model_class
40
+ @model_class ||= @association_name.classify.constantize
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,4 @@
1
+ motion_require './finder.rb'
1
2
  module MotionPrime
2
3
  module BagInstanceMethods
3
4
  def self.included(base)
@@ -1,34 +1,35 @@
1
1
  module MotionPrime
2
2
  class Errors
3
3
  attr_accessor :keys
4
- attr_accessor :errors
5
4
 
6
5
  def initialize(model)
7
6
  @keys = []
8
- @errors = {}
9
7
  model.class.attributes.map(&:to_sym).each do |key|
10
8
  initialize_for_key key
11
9
  end
12
10
  end
13
11
 
14
12
  def initialize_for_key(key)
13
+ return if @keys.include?(key.to_sym)
15
14
  @keys << key.to_sym unless @keys.include?(key.to_sym)
16
- @errors[key.to_sym] ||= []
15
+ unless instance_variable_get("@#{key}")
16
+ instance_variable_set("@#{key}", [])
17
+ end
18
+ self.class.send :attr_accessor, key.to_sym
17
19
  end
18
20
 
19
21
  def get(key)
20
22
  initialize_for_key(key)
21
- @errors[key.to_sym]
23
+ send(:"#{key.to_sym}")
22
24
  end
23
25
 
24
26
  def set(key, errors)
25
27
  initialize_for_key(key)
26
- @errors[key.to_sym] = Array.wrap(errors)
28
+ send :"#{key.to_sym}=", Array.wrap(errors)
27
29
  end
28
30
 
29
31
  def add(key, error)
30
- initialize_for_key(key)
31
- @errors[key.to_sym] << error
32
+ get(key) << error
32
33
  end
33
34
 
34
35
  def [](key)
@@ -46,7 +47,7 @@ module MotionPrime
46
47
  end
47
48
 
48
49
  def messages
49
- errors.values.compact.flatten
50
+ @keys.map{ |k| get(k)}.compact.flatten
50
51
  end
51
52
 
52
53
  def blank?
@@ -4,6 +4,8 @@ module MotionPrime
4
4
  #
5
5
  # @return [Array] array of models
6
6
  def all(*args)
7
+ return [] unless self.store
8
+
7
9
  if args[0].is_a?(Hash)
8
10
  sort_options = args[0][:sort] || {}
9
11
  else
@@ -1,5 +1,9 @@
1
1
  module MotionPrime
2
2
  module ModelMethods
3
+ def self.included(base)
4
+ base.class_attribute :default_sort_options
5
+ end
6
+
3
7
  def save
4
8
  raise StoreError, 'No store provided' unless self.store
5
9
  error_ptr = Pointer.new(:id)
@@ -146,5 +150,9 @@ module MotionPrime
146
150
  keys = find_keys(*args)
147
151
  self.store.delete_keys(keys)
148
152
  end
153
+
154
+ def default_sort(sort_options)
155
+ self.default_sort_options = sort_options
156
+ end
149
157
  end
150
158
  end
@@ -8,7 +8,7 @@ module MotionPrime
8
8
 
9
9
  def sync_url(method = :get)
10
10
  url = self.class.sync_url
11
- url = url.call(method) if url.is_a?(Proc)
11
+ url = url.call(method, self) if url.is_a?(Proc)
12
12
  normalize_sync_url(url)
13
13
  end
14
14
 
@@ -51,7 +51,7 @@ module MotionPrime
51
51
  end
52
52
 
53
53
  should_fetch = !new_record? if should_fetch.nil?
54
- should_update = new_record? if should_update.nil?
54
+ should_update ||= new_record? unless should_fetch
55
55
 
56
56
  fetch_with_url url do
57
57
  save if sync_options[:save]
@@ -186,8 +186,7 @@ module MotionPrime
186
186
  updatable_attributes = self.class.updatable_attributes
187
187
 
188
188
  if updatable_attributes.blank?
189
- attrs = attributes_hash.slice(*slice_attributes) if slice_attributes
190
- return attrs
189
+ return slice_attributes ? attributes_hash.slice(*slice_attributes) : attributes_hash
191
190
  end
192
191
 
193
192
  updatable_attributes = updatable_attributes.slice(*slice_attributes) if slice_attributes
@@ -11,6 +11,8 @@ module MotionPrime
11
11
  # element :avatar, type: :image, image: 'defaults/avatar.jpg'
12
12
  # end
13
13
  #
14
+ KEYBOARD_HEIGHT_PORTRAIT = 216
15
+ KEYBOARD_HEIGHT_LANDSCAPE = 162
14
16
  DEFAULT_CONTENT_HEIGHT = 65
15
17
  include ::MotionSupport::Callbacks
16
18
  include MotionPrime::HasAuthorization
@@ -56,6 +58,11 @@ module MotionPrime
56
58
  options.merge(section: self)
57
59
  end
58
60
 
61
+ def cell
62
+ first_element = elements.values.first
63
+ first_element.view.superview
64
+ end
65
+
59
66
  def render(container_options = {})
60
67
  self.container_options.merge!(container_options)
61
68
  self.screen = container_options.delete(:to)
@@ -104,6 +111,30 @@ module MotionPrime
104
111
  container_options[:styles]
105
112
  end
106
113
 
114
+ def on_keyboard_show; end
115
+ def on_keyboard_hide; end
116
+ def keyboard_will_show; end
117
+ def keyboard_will_hide; end
118
+
119
+ def bind_keyboard_events
120
+ NSNotificationCenter.defaultCenter.addObserver self,
121
+ selector: :on_keyboard_show,
122
+ name: UIKeyboardDidShowNotification,
123
+ object: nil
124
+ NSNotificationCenter.defaultCenter.addObserver self,
125
+ selector: :on_keyboard_hide,
126
+ name: UIKeyboardDidHideNotification,
127
+ object: nil
128
+ NSNotificationCenter.defaultCenter.addObserver self,
129
+ selector: :keyboard_will_show,
130
+ name: UIKeyboardWillShowNotification,
131
+ object: nil
132
+ NSNotificationCenter.defaultCenter.addObserver self,
133
+ selector: :keyboard_will_hide,
134
+ name: UIKeyboardWillHideNotification,
135
+ object: nil
136
+ end
137
+
107
138
  class << self
108
139
  def element(name, options = {}, &block)
109
140
  options[:type] ||= :label
@@ -123,5 +154,7 @@ module MotionPrime
123
154
  set_callback :render, :after, method_name
124
155
  end
125
156
  end
157
+ after_render :bind_keyboard_events
158
+
126
159
  end
127
160
  end
@@ -17,15 +17,10 @@ module MotionPrime
17
17
  # end
18
18
  #
19
19
 
20
- KEYBOARD_HEIGHT_PORTRAIT = 216
21
- KEYBOARD_HEIGHT_LANDSCAPE = 162
22
-
23
20
  class_attribute :text_field_limits, :text_view_limits
24
21
  class_attribute :fields_options
25
22
  attr_accessor :fields, :field_indexes, :keyboard_visible
26
23
 
27
- after_render :bind_keyboard_events
28
-
29
24
  def table_data
30
25
  fields.values
31
26
  end
@@ -90,6 +85,10 @@ module MotionPrime
90
85
  self.fields[field_name.to_sym]
91
86
  end
92
87
 
88
+ def fields_hash
89
+ fields.to_hash
90
+ end
91
+
93
92
  # Set focus on field cell
94
93
  #
95
94
  # Examples:
@@ -118,31 +117,6 @@ module MotionPrime
118
117
  self.keyboard_visible = false
119
118
  end
120
119
 
121
-
122
-
123
- def on_keyboard_show; end
124
- def on_keyboard_hide; end
125
- def keyboard_will_show; end
126
- def keyboard_will_hide; end
127
-
128
- def bind_keyboard_events
129
- NSNotificationCenter.defaultCenter.addObserver self,
130
- selector: :on_keyboard_show,
131
- name: UIKeyboardDidShowNotification,
132
- object: nil
133
- NSNotificationCenter.defaultCenter.addObserver self,
134
- selector: :on_keyboard_hide,
135
- name: UIKeyboardDidHideNotification,
136
- object: nil
137
- NSNotificationCenter.defaultCenter.addObserver self,
138
- selector: :keyboard_will_show,
139
- name: UIKeyboardWillShowNotification,
140
- object: nil
141
- NSNotificationCenter.defaultCenter.addObserver self,
142
- selector: :keyboard_will_hide,
143
- name: UIKeyboardWillHideNotification,
144
- object: nil
145
- end
146
120
  # ALIASES
147
121
  def on_input_change(text_field); end
148
122
  def on_input_edit(text_field); end
@@ -58,11 +58,6 @@ module MotionPrime
58
58
  @container_options || super
59
59
  end
60
60
 
61
- def cell
62
- first_element = elements.values.first
63
- first_element.view.superview
64
- end
65
-
66
61
  def focus(begin_editing = true)
67
62
  # scroll to cell
68
63
  path = form.table_view.indexPathForCell cell
@@ -1,14 +1,24 @@
1
1
  motion_require '../table.rb'
2
2
  module MotionPrime
3
3
  class TableFieldSection < TableSection
4
- attr_accessor :form, :cell_element
4
+ attr_accessor :form, :cell_element, :delegate
5
+ after_render :on_render
5
6
 
6
7
  def initialize(options = {})
7
8
  @form = options.delete(:form)
9
+ @delegate = options.delete(:delegate) || form
8
10
  @container_options = options.delete(:container)
9
11
  super
10
12
  end
11
13
 
14
+ def on_render
15
+ add_pull_to_refresh do
16
+ model.sync! do
17
+ finish_pull_to_refresh
18
+ end
19
+ end if @options[:pull_to_refresh] && model.present?
20
+ end
21
+
12
22
  def render_table
13
23
  @styles ||= []
14
24
  @styles += [
@@ -24,17 +34,18 @@ module MotionPrime
24
34
  end
25
35
  end
26
36
 
27
- def table_data
28
- form.send("#{name}_table_data")
37
+ def on_click(table, index)
38
+ section = data[index.row]
39
+ delegate.send("#{name}_selected", section) if delegate.respond_to?("#{name}_selected")
29
40
  end
30
41
 
31
- def container_height
32
- form.send("#{name}_height")
42
+ def self.delegate_method(method_name)
43
+ define_method method_name do |*args|
44
+ delegate.send("#{name}_#{method_name}", *args) if delegate.respond_to?("#{name}_#{method_name}")
45
+ end
33
46
  end
34
47
 
35
- def on_click(table, index)
36
- section = data[index.row]
37
- form.send("#{name}_selected", section)
38
- end
48
+ delegate_method :table_data
49
+ delegate_method :container_height
39
50
  end
40
51
  end
@@ -0,0 +1,59 @@
1
+ module MotionPrime
2
+ class TextWithButtonFieldSection < BaseFieldSection
3
+ element :label, type: :label do
4
+ {
5
+ styles: [
6
+ :base_field_label,
7
+ :base_text_field_label,
8
+ :"#{form_name}_field_label",
9
+ :"#{form_name}_#{name}_field_label"
10
+ ]
11
+ }.merge(options[:label] || {})
12
+ end
13
+ element :input, type: :text_view do
14
+ styles = [
15
+ :base_field_input,
16
+ :base_text_field_input,
17
+ :"#{form_name}_field_input",
18
+ :"#{form_name}_#{name}_field_input"
19
+ ]
20
+ styles << :base_field_input_with_errors if form.model && form.model.errors[name].present?
21
+
22
+ {
23
+ styles: styles,
24
+ editable: true
25
+ }.merge(options[:input] || {})
26
+ end
27
+ element :button, type: :button do
28
+ {
29
+ styles: [
30
+ :base_text_button,
31
+ :"#{form_name}_text_button",
32
+ :"#{form_name}_#{name}_text_button"
33
+ ]
34
+ }.merge(options[:button] || {}).except(:action)
35
+ end
36
+ element :error_message, type: :error_message do
37
+ {
38
+ styles: [
39
+ :base_field_label,
40
+ :base_string_field_label,
41
+ :"#{form_name}_field_label",
42
+ :"#{form_name}_#{name}_field_label",
43
+ :base_error_message
44
+ ],
45
+ hidden: proc { form.model && form.model.errors[name].blank? },
46
+ text: proc { form.model and form.model.errors[name].join("\n") }
47
+ }
48
+ end
49
+
50
+ after_render :bind_text_input
51
+ after_render :bind_button_action
52
+
53
+ def bind_button_action
54
+ view(:button).on :touch do
55
+ form.send(options[:button][:action])
56
+ end if options[:button].try(:[], :action)
57
+ end
58
+ end
59
+ end
@@ -59,7 +59,6 @@ module MotionPrime
59
59
  if item.respond_to?(:name) && item.name.present?
60
60
  styles += [item.name.to_sym]
61
61
  end
62
-
63
62
  # DrawSection allows as to draw inside the cell view, so we can setup
64
63
  # to use cell view as container
65
64
  if item.is_a?(MotionPrime::DrawSection)
@@ -5,7 +5,7 @@ module MotionPrime
5
5
  screen.setup table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
6
6
  end
7
7
 
8
- def fisnish_pull_to_refresh
8
+ def finish_pull_to_refresh
9
9
  reload_data
10
10
  table_view.pullToRefreshView.stopAnimating
11
11
  end
@@ -71,11 +71,11 @@ MotionPrime::Styles.define :base do
71
71
  # @background_image: PATH_TO_FILE
72
72
  style :submit_button,
73
73
  background_color: :gray,
74
+ title_color: :white,
74
75
  left: 0,
75
76
  right: 0,
76
77
  top: 10,
77
- height: 44,
78
- title_color: :white
78
+ height: 44
79
79
 
80
80
  style :select_field_button,
81
81
  background_color: :white,
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -90,9 +90,8 @@ module MotionPrime
90
90
  search_bar
91
91
  },
92
92
  'GMSMapView' => Proc.new{|klass, options|
93
- camera = GMSCameraPosition.cameraWithLatitude(35.689466, longitude: 139.700196, zoom: 15)
94
- map = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
95
- map
93
+ camera = GMSCameraPosition.cameraWithLatitude(23.42, longitude: 127.42, zoom: 15)
94
+ GMSMapView.mapWithFrame(CGRectZero, camera: camera)
96
95
  }
97
96
  }
98
97
  end
@@ -106,9 +106,9 @@ module MotionPrime
106
106
  # apply options
107
107
  if key.end_with?('title_color')
108
108
  view.setTitleColor value.uicolor, forState: UIControlStateNormal
109
- elsif key.end_with?('alignment')
109
+ elsif key.end_with?('alignment') && value.is_a?(Symbol)
110
110
  view.setValue value.uitextalignment, forKey: key.camelize
111
- elsif key.end_with?('line_break_mode')
111
+ elsif key.end_with?('line_break_mode') && value.is_a?(Symbol)
112
112
  view.setValue value.uilinebreakmode, forKey: key.camelize
113
113
  elsif key.end_with?('title_shadow_color')
114
114
  view.setTitleShadowColor value.uicolor, forState: UIControlStateNormal
@@ -23,7 +23,7 @@ describe "Model Errors" do
23
23
 
24
24
  it "should be convertable to string" do
25
25
  @user.errors.add(:foo, 'bar')
26
- @user.errors.to_s.match(/foo/).should != nil
26
+ @user.errors.to_s.match(/bar/).should != nil
27
27
  end
28
28
  end
29
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-prime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Haziev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-09 00:00:00.000000000 Z
11
+ date: 2013-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -199,12 +199,14 @@ files:
199
199
  - motion-prime/elements/google_map.rb
200
200
  - motion-prime/elements/image.rb
201
201
  - motion-prime/elements/label.rb
202
+ - motion-prime/elements/map.rb
202
203
  - motion-prime/elements/text_field.rb
203
204
  - motion-prime/elements/text_view.rb
204
205
  - motion-prime/helpers/has_authorization.rb
205
206
  - motion-prime/helpers/has_normalizer.rb
206
207
  - motion-prime/helpers/has_search_bar.rb
207
208
  - motion-prime/models/association.rb
209
+ - motion-prime/models/association_collection.rb
208
210
  - motion-prime/models/bag.rb
209
211
  - motion-prime/models/base.rb
210
212
  - motion-prime/models/errors.rb
@@ -234,6 +236,7 @@ files:
234
236
  - motion-prime/sections/form/switch_field_section.rb
235
237
  - motion-prime/sections/form/table_field_section.rb
236
238
  - motion-prime/sections/form/text_field_section.rb
239
+ - motion-prime/sections/form/text_with_button_field_section.rb
237
240
  - motion-prime/sections/tabbed.rb
238
241
  - motion-prime/sections/table.rb
239
242
  - motion-prime/sections/table/refresh_mixin.rb