motion-prime 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +6 -6
- data/README.md +1 -10
- data/Rakefile +0 -1
- data/app/app_delegate.rb +1 -1
- data/bin/prime +1 -1
- data/files/Gemfile +1 -1
- data/motion-prime/api_client.rb +87 -31
- data/motion-prime/config/base.rb +20 -11
- data/motion-prime/config/config.rb +9 -3
- data/motion-prime/core_ext/kernel.rb +2 -1
- data/motion-prime/core_ext/nil_class.rb +5 -0
- data/motion-prime/delegate/app_delegate.rb +5 -0
- data/motion-prime/elements/base_element.rb +21 -2
- data/motion-prime/elements/draw.rb +6 -16
- data/motion-prime/helpers/has_authorization.rb +1 -1
- data/motion-prime/models/_base_mixin.rb +1 -1
- data/motion-prime/prime.rb +4 -0
- data/motion-prime/screens/extensions/_indicators_mixin.rb +16 -10
- data/motion-prime/screens/screen.rb +1 -1
- data/motion-prime/sections/_async_table_mixin.rb +1 -2
- data/motion-prime/sections/_draw_section_mixin.rb +3 -1
- data/motion-prime/sections/base_section.rb +37 -26
- data/motion-prime/sections/form.rb +23 -8
- data/motion-prime/sections/form/base_field_section.rb +1 -15
- data/motion-prime/sections/form/date_field_section.rb +1 -1
- data/motion-prime/sections/form/password_field_section.rb +1 -1
- data/motion-prime/sections/form/select_field_section.rb +1 -1
- data/motion-prime/sections/form/string_field_section.rb +1 -1
- data/motion-prime/sections/form/submit_field_section.rb +1 -1
- data/motion-prime/sections/form/text_field_section.rb +1 -1
- data/motion-prime/sections/table.rb +58 -27
- data/motion-prime/sections/table/refresh_mixin.rb +1 -1
- data/motion-prime/services/logger.rb +60 -21
- data/motion-prime/support/consts.rb +11 -0
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +5 -4
- data/motion-prime/views/view_styler.rb +3 -0
- data/spec/{helpers → factories}/delegates.rb +0 -3
- data/spec/{helpers → factories}/init.rb +0 -0
- data/spec/{helpers → factories}/models.rb +0 -0
- data/spec/factories/scaffold/models/task.rb +4 -0
- data/spec/factories/scaffold/screens/tasks.rb +45 -0
- data/spec/factories/scaffold/sections/tasks/form.rb +31 -0
- data/spec/factories/scaffold/sections/tasks/index_cell.rb +4 -0
- data/spec/factories/scaffold/sections/tasks/index_table.rb +12 -0
- data/spec/factories/scaffold/sections/tasks/show.rb +3 -0
- data/spec/factories/scaffold/styles/tasks.rb +18 -0
- data/spec/{helpers → factories}/screens.rb +0 -0
- data/spec/factories/sections.rb +9 -0
- data/spec/features/scaffold/index.rb +14 -0
- data/spec/features/screens/open_screen.rb +14 -2
- data/spec/helpers/has_content.rb +25 -0
- data/spec/unit/models/dirty_spec.rb +0 -1
- data/spec/unit/models/model_spec.rb +2 -0
- data/spec/unit/prime/logger.rb +49 -0
- data/spec/unit/sections/section_spec.rb +59 -0
- data/travis.sh +1 -1
- metadata +36 -41
- data/doc/FAQ.md +0 -2
- data/doc/SECTION.md +0 -7
- data/doc/STYLE.md +0 -39
- data/doc/code/getting_started.rb +0 -106
- data/doc/code/models.rb +0 -36
- data/doc/code/screens.rb +0 -93
- data/doc/code/sections.rb +0 -65
- data/doc/code/tables.rb +0 -54
- data/doc/docs/docco.css +0 -337
- data/doc/docs/getting_started.html +0 -195
- data/doc/docs/index.html +0 -205
- data/doc/docs/models.html +0 -115
- data/doc/docs/public/fonts/aller-bold.eot +0 -0
- data/doc/docs/public/fonts/aller-bold.ttf +0 -0
- data/doc/docs/public/fonts/aller-bold.woff +0 -0
- data/doc/docs/public/fonts/aller-light.eot +0 -0
- data/doc/docs/public/fonts/aller-light.ttf +0 -0
- data/doc/docs/public/fonts/aller-light.woff +0 -0
- data/doc/docs/public/fonts/fleurons.eot +0 -0
- data/doc/docs/public/fonts/fleurons.ttf +0 -0
- data/doc/docs/public/fonts/fleurons.woff +0 -0
- data/doc/docs/public/fonts/novecento-bold.eot +0 -0
- data/doc/docs/public/fonts/novecento-bold.ttf +0 -0
- data/doc/docs/public/fonts/novecento-bold.woff +0 -0
- data/doc/docs/public/images/gray.png +0 -0
- data/doc/docs/public/stylesheets/normalize.css +0 -375
- data/doc/docs/screens.html +0 -187
- data/doc/docs/sections.html +0 -138
- data/doc/docs/tables.html +0 -128
- data/spec/helpers/sections.rb +0 -3
@@ -11,7 +11,7 @@ module MotionPrime
|
|
11
11
|
end
|
12
12
|
element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
|
13
13
|
|
14
|
-
|
14
|
+
after_element_render :button, :bind_select_button
|
15
15
|
|
16
16
|
def bind_select_button
|
17
17
|
view(:button).on :touch_down do
|
@@ -9,7 +9,7 @@ module MotionPrime
|
|
9
9
|
end
|
10
10
|
|
11
11
|
element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
|
12
|
-
|
12
|
+
after_element_render :input, :bind_text_input
|
13
13
|
|
14
14
|
def value
|
15
15
|
view(:input).text
|
@@ -5,7 +5,7 @@ module MotionPrime
|
|
5
5
|
end
|
6
6
|
element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
|
7
7
|
|
8
|
-
|
8
|
+
after_element_render :button, :bind_button
|
9
9
|
|
10
10
|
def bind_button
|
11
11
|
view(:button).on :touch do
|
@@ -8,7 +8,7 @@ module MotionPrime
|
|
8
8
|
end
|
9
9
|
|
10
10
|
element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
|
11
|
-
|
11
|
+
after_element_render :input, :bind_text_input
|
12
12
|
|
13
13
|
def value
|
14
14
|
view(:input).text
|
@@ -14,7 +14,7 @@ module MotionPrime
|
|
14
14
|
before_render :render_table
|
15
15
|
after_render :init_pull_to_refresh
|
16
16
|
delegate :init_pull_to_refresh, to: :table_delegate
|
17
|
-
|
17
|
+
delegate :set_options, :update_options, to: :table_element, allow_nil: true
|
18
18
|
|
19
19
|
# Return sections which will be used to render as table cells.
|
20
20
|
#
|
@@ -49,7 +49,7 @@ module MotionPrime
|
|
49
49
|
#
|
50
50
|
# @return [Boolean] true
|
51
51
|
def reload_data
|
52
|
-
|
52
|
+
reset_table_data
|
53
53
|
reload_table_data
|
54
54
|
end
|
55
55
|
|
@@ -60,7 +60,7 @@ module MotionPrime
|
|
60
60
|
reload_data
|
61
61
|
end
|
62
62
|
|
63
|
-
# Reload table view
|
63
|
+
# Reload table view data
|
64
64
|
#
|
65
65
|
# @return [Boolean] true
|
66
66
|
def reload_table_data
|
@@ -78,7 +78,7 @@ module MotionPrime
|
|
78
78
|
# Reset all table data.
|
79
79
|
#
|
80
80
|
# @return [Boolean] true
|
81
|
-
def
|
81
|
+
def reset_table_data
|
82
82
|
@did_appear = false
|
83
83
|
@data = nil
|
84
84
|
@data_stamp = nil
|
@@ -104,7 +104,7 @@ module MotionPrime
|
|
104
104
|
#
|
105
105
|
# @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be removed from table view.
|
106
106
|
# @return [Array<NSIndexPath>] index paths of removed cells.
|
107
|
-
def delete_cell_sections(sections)
|
107
|
+
def delete_cell_sections(sections, &block)
|
108
108
|
paths = []
|
109
109
|
Array.wrap(sections).each do |section|
|
110
110
|
index = index_for_cell_section(section)
|
@@ -113,13 +113,46 @@ module MotionPrime
|
|
113
113
|
delete_from_data(index)
|
114
114
|
end
|
115
115
|
if paths.any?
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
UIView.animate(duration: 0, after: block) do
|
117
|
+
table_view.beginUpdates
|
118
|
+
table_view.deleteRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimationLeft)
|
119
|
+
table_view.endUpdates
|
120
|
+
end
|
119
121
|
end
|
120
122
|
paths
|
121
123
|
end
|
122
124
|
|
125
|
+
# Reloads cells with animation, executes given block before reloading.
|
126
|
+
#
|
127
|
+
# @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be updated.
|
128
|
+
# @param around callback [Proc] Callback which will be executed before reloading.
|
129
|
+
# @return [Array<NSIndexPath>] index paths of reloaded cells.
|
130
|
+
def reload_cell_sections(sections, &block)
|
131
|
+
paths = []
|
132
|
+
Array.wrap(sections).each_with_index do |section, counter|
|
133
|
+
index = index_for_cell_section(section)
|
134
|
+
next Prime.logger.debug("Reload section: `#{section.name}` is not in the list") unless index
|
135
|
+
paths << index
|
136
|
+
block.call(section, index, counter)
|
137
|
+
set_data_stamp(section.object_id)
|
138
|
+
section.reload
|
139
|
+
end
|
140
|
+
table_view.reloadRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimationFade)
|
141
|
+
paths
|
142
|
+
end
|
143
|
+
|
144
|
+
# Changes height of cells with animation.
|
145
|
+
#
|
146
|
+
# @param cell sections [Prime::Section, Array<Prime::Section>] cells which will be updated.
|
147
|
+
# @param height [Integer, Array<Integer>] new height of all cells, or height for each cell.
|
148
|
+
# @return [Array<NSIndexPath>] index paths of removed cells.
|
149
|
+
def resize_cell_sections(sections, height)
|
150
|
+
reload_cell_sections(sections) do |section, index, counter|
|
151
|
+
container_height = height.is_a?(Array) ? height[counter] : height
|
152
|
+
section.container_options[:height] = container_height
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
123
156
|
# Delete section from data at index
|
124
157
|
#
|
125
158
|
# @param index [NSIndexPath] index of cell which will be removed from table data.
|
@@ -127,24 +160,18 @@ module MotionPrime
|
|
127
160
|
if flat_data?
|
128
161
|
delete_from_flat_data(index)
|
129
162
|
else
|
130
|
-
|
163
|
+
delete_from_grouped_data(index)
|
131
164
|
end
|
132
165
|
end
|
133
166
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
def delete_from_groped_data(index)
|
140
|
-
@data[index.section][index.row] = nil
|
141
|
-
@data[index.section].delete_at(index.row)
|
142
|
-
end
|
143
|
-
|
167
|
+
# Get index path for cell section
|
168
|
+
#
|
169
|
+
# @param section [Prime::Section] cell section.
|
170
|
+
# @return index [NSIndexPath] index of cell section.
|
144
171
|
def index_for_cell_section(section)
|
145
172
|
if flat_data?
|
146
173
|
row = @data.try(:index, section)
|
147
|
-
NSIndexPath.indexPathForRow(row, inSection: 0)
|
174
|
+
NSIndexPath.indexPathForRow(row, inSection: 0) if row
|
148
175
|
else
|
149
176
|
(@data || []).each_with_index do |cell_sections, group|
|
150
177
|
row = cell_sections.index(section)
|
@@ -153,12 +180,6 @@ module MotionPrime
|
|
153
180
|
end
|
154
181
|
end
|
155
182
|
|
156
|
-
def reload_cell_section(section)
|
157
|
-
section.elements.values.each(&:compute_options!)
|
158
|
-
section.cached_draw_image = nil
|
159
|
-
# TODO: reset date stamps, reload row
|
160
|
-
end
|
161
|
-
|
162
183
|
def table_styles
|
163
184
|
type = self.is_a?(FormSection) ? :base_form : :base_table
|
164
185
|
|
@@ -326,7 +347,7 @@ module MotionPrime
|
|
326
347
|
styles: styles,
|
327
348
|
parent_view: table_view,
|
328
349
|
reuse_identifier: reuse_identifier,
|
329
|
-
section: header
|
350
|
+
section: header.weak_ref
|
330
351
|
)
|
331
352
|
wrapper.render do |container_view, container_element|
|
332
353
|
header.container_element = container_element
|
@@ -355,6 +376,16 @@ module MotionPrime
|
|
355
376
|
end
|
356
377
|
|
357
378
|
private
|
379
|
+
def delete_from_flat_data(index)
|
380
|
+
@data[index.row] = nil
|
381
|
+
@data.delete_at(index.row)
|
382
|
+
end
|
383
|
+
|
384
|
+
def delete_from_grouped_data(index)
|
385
|
+
@data[index.section][index.row] = nil
|
386
|
+
@data[index.section].delete_at(index.row)
|
387
|
+
end
|
388
|
+
|
358
389
|
def display_pending_cells
|
359
390
|
table_view.visibleCells.each do |cell_view|
|
360
391
|
if cell_view.section && cell_view.section.pending_display
|
@@ -4,7 +4,7 @@ module MotionPrime
|
|
4
4
|
screen.automaticallyAdjustsScrollViewInsets = false
|
5
5
|
|
6
6
|
table_view.addPullToRefreshWithActionHandler(block) # block must be a variable
|
7
|
-
screen.
|
7
|
+
screen.set_options_for table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
|
8
8
|
end
|
9
9
|
|
10
10
|
def finish_pull_to_refresh
|
@@ -5,50 +5,89 @@ module MotionPrime
|
|
5
5
|
LOGGER_DEBUG_LEVEL = 2
|
6
6
|
LOGGER_DEALLOC_LEVEL = 3
|
7
7
|
|
8
|
+
COLORS = {
|
9
|
+
red: [ "\e[0;31m", "\e[0m" ],
|
10
|
+
green: [ "\e[0;32m", "\e[0m" ],
|
11
|
+
yellow: [ "\e[0;33m", "\e[0m" ],
|
12
|
+
blue: [ "\e[0;34m", "\e[0m" ],
|
13
|
+
none: [ "", ""]
|
14
|
+
}
|
15
|
+
|
8
16
|
class_attribute :level, :dealloc_items
|
17
|
+
attr_accessor :disabled
|
9
18
|
|
10
19
|
def initialize
|
11
20
|
@default_level = Config.logger.level.nil? ? :info : Config.logger.level
|
21
|
+
@disabled = false
|
22
|
+
end
|
23
|
+
|
24
|
+
# Log message, colorized if using simulator.
|
25
|
+
# @param message [Array<String>, String] Message or array of messages to log.
|
26
|
+
# @param color [Symbol] Color of message: red, green, yellow, blue.
|
27
|
+
# @return message [Array<String>, String] Logged message
|
28
|
+
def log(objects, label = '', color = :none)
|
29
|
+
message = "#{label || 'PRIME_LOG'} : " + Array.wrap(objects).map(&:inspect).join(',')
|
30
|
+
if Device.simulator?
|
31
|
+
color_parts = COLORS[color] || COLORS[:none]
|
32
|
+
output(color_parts.first + message + color_parts.last)
|
33
|
+
else
|
34
|
+
output(message)
|
35
|
+
end
|
36
|
+
objects
|
37
|
+
end
|
38
|
+
|
39
|
+
# Output message, using "puts" for simulator and NSLog for Device.
|
40
|
+
# @param message [String] Message or array of messages to output.
|
41
|
+
# @return message [Array<String>, String] Message
|
42
|
+
def output(message)
|
43
|
+
return if disabled
|
44
|
+
if Device.simulator?
|
45
|
+
puts(message)
|
46
|
+
else
|
47
|
+
NSLog(message)
|
48
|
+
end
|
49
|
+
message
|
12
50
|
end
|
13
51
|
|
14
52
|
def error(*args)
|
15
|
-
|
53
|
+
log(args, "PRIME_ERROR", :red) if LOGGER_ERROR_LEVEL <= current_level
|
16
54
|
end
|
17
55
|
|
18
56
|
def info(*args)
|
19
|
-
|
57
|
+
log(args, "PRIME_INFO", :green) if LOGGER_INFO_LEVEL <= current_level
|
20
58
|
end
|
21
59
|
|
22
60
|
def debug(*args)
|
23
|
-
|
61
|
+
log(args, "PRIME_DEBUG", :yellow) if LOGGER_DEBUG_LEVEL <= current_level
|
24
62
|
end
|
25
63
|
|
26
64
|
def dealloc_message(type, object, *args)
|
27
65
|
if LOGGER_DEALLOC_LEVEL <= current_level
|
28
66
|
if dealloc_items.include?(type.to_s)
|
29
|
-
|
67
|
+
log([object.object_id, object.to_s] + args, "DEALLOC #{type}", :yellow)
|
30
68
|
end
|
31
69
|
end
|
32
70
|
end
|
33
71
|
|
34
|
-
|
35
|
-
|
36
|
-
|
72
|
+
private
|
73
|
+
def dealloc_items
|
74
|
+
self.class.dealloc_items || []
|
75
|
+
end
|
37
76
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
77
|
+
def current_level
|
78
|
+
current_level = self.class.level || @default_level
|
79
|
+
case current_level.to_s
|
80
|
+
when 'error'
|
81
|
+
LOGGER_ERROR_LEVEL
|
82
|
+
when 'info'
|
83
|
+
LOGGER_INFO_LEVEL
|
84
|
+
when 'debug'
|
85
|
+
LOGGER_DEBUG_LEVEL
|
86
|
+
when 'dealloc'
|
87
|
+
LOGGER_DEALLOC_LEVEL
|
88
|
+
else
|
89
|
+
2
|
90
|
+
end
|
51
91
|
end
|
52
|
-
end
|
53
92
|
end
|
54
93
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# this constants should be listed here to be accessible in constantize
|
2
|
+
|
3
|
+
UIControlContentHorizontalAlignmentCenter
|
4
|
+
UIControlContentHorizontalAlignmentLeft
|
5
|
+
UIControlContentHorizontalAlignmentRight
|
6
|
+
UIControlContentHorizontalAlignmentFill
|
7
|
+
|
8
|
+
UIControlContentVerticalAlignmentCenter
|
9
|
+
UIControlContentVerticalAlignmentTop
|
10
|
+
UIControlContentVerticalAlignmentBottom
|
11
|
+
UIControlContentVerticalAlignmentFill
|
data/motion-prime/version.rb
CHANGED
@@ -18,7 +18,7 @@ module MotionPrime
|
|
18
18
|
view = builder.view
|
19
19
|
insert_index = options.delete(:at_index)
|
20
20
|
|
21
|
-
|
21
|
+
set_options_for(view, options, &block)
|
22
22
|
if superview = render_target || view_stack.last
|
23
23
|
insert_index ? superview.insertSubview(view, atIndex: insert_index) : superview.addSubview(view)
|
24
24
|
end
|
@@ -26,16 +26,17 @@ module MotionPrime
|
|
26
26
|
view
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def set_options_for(view, options = {}, &block)
|
30
30
|
ViewStyler.new(view, options.delete(:parent_bounds), options).apply
|
31
31
|
view_stack.push(view)
|
32
32
|
block.call(view) if block_given?
|
33
33
|
view_stack.pop
|
34
34
|
end
|
35
|
+
alias_method :update_options_for, :set_options_for
|
35
36
|
|
36
37
|
def setup(view, options = {}, &block)
|
37
|
-
puts "DEPRECATION: screen#setup is deprecated, please use screen#
|
38
|
-
|
38
|
+
puts "DEPRECATION: screen#setup is deprecated, please use screen#set_options_for instead"
|
39
|
+
set_options_for(view, options, &block)
|
39
40
|
end
|
40
41
|
|
41
42
|
def view_stack
|
@@ -147,6 +147,9 @@ module MotionPrime
|
|
147
147
|
if key == 'content_horizontal_alignment' && value.is_a?(Symbol) && %[left right center fill].include?(value.to_s)
|
148
148
|
view.setValue "UIControlContentHorizontalAlignment#{value.camelize}".constantize, forKey: camelize_factory(key)
|
149
149
|
true
|
150
|
+
elsif key == 'content_vertical_alignment' && value.is_a?(Symbol) && %[top bottom center fill].include?(value.to_s)
|
151
|
+
view.setValue "UIControlContentHorizontalAlignment#{value.camelize}".constantize, forKey: camelize_factory(key)
|
152
|
+
true
|
150
153
|
elsif key.end_with?('alignment') && value.is_a?(Symbol)
|
151
154
|
view.setValue value.uitextalignment, forKey: camelize_factory(key)
|
152
155
|
true
|
@@ -1,6 +1,3 @@
|
|
1
|
-
# motion_require '../../motion-prime/helpers/has_authorization'
|
2
|
-
# motion_require './../motion-prime/delegate/_base_mixin'
|
3
|
-
# motion_require './../motion-prime/delegate/_navigation_mixin'
|
4
1
|
AppDelegate.send :include, MotionPrime::HasAuthorization
|
5
2
|
AppDelegate.send :include, MotionPrime::DelegateBaseMixin
|
6
3
|
AppDelegate.send :include, MotionPrime::DelegateNavigationMixin
|
File without changes
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class TasksScreen < Prime::Screen
|
2
|
+
title "Tasks"
|
3
|
+
|
4
|
+
# open_screen "tasks#index"
|
5
|
+
def index
|
6
|
+
set_title "Tasks"
|
7
|
+
set_navigation_right_button 'New' do
|
8
|
+
open_screen "tasks#new"
|
9
|
+
end
|
10
|
+
set_section :tasks_index_table
|
11
|
+
end
|
12
|
+
|
13
|
+
# open_screen "tasks#show"
|
14
|
+
def show
|
15
|
+
@model = params[:model]
|
16
|
+
set_title "Show Task"
|
17
|
+
set_navigation_back_button 'Back'
|
18
|
+
set_navigation_right_button 'Edit' do
|
19
|
+
open_screen "tasks#edit", params: { model: @model }
|
20
|
+
end
|
21
|
+
set_section :tasks_show, model: @model
|
22
|
+
end
|
23
|
+
|
24
|
+
# open_screen "tasks#edit"
|
25
|
+
def edit
|
26
|
+
@model = params[:model]
|
27
|
+
set_title "Edit Task"
|
28
|
+
set_navigation_back_button 'Cancel'
|
29
|
+
set_section :tasks_form, model: @model
|
30
|
+
end
|
31
|
+
|
32
|
+
# open_screen "tasks#new"
|
33
|
+
def new
|
34
|
+
@model = Task.new
|
35
|
+
set_title "New Task"
|
36
|
+
set_navigation_back_button 'Cancel'
|
37
|
+
set_section :tasks_form, model: @model
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_return
|
41
|
+
if action?(:index) || action?(:show)
|
42
|
+
refresh
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|