fron-ui 1.0.0rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +38 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/.yardopts +8 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +105 -0
- data/Rakefile +37 -0
- data/Readme.md +4 -0
- data/db.json +192 -0
- data/fron-ui.gemspec +21 -0
- data/lib/fron-ui.rb +1 -0
- data/lib/fron_ui.rb +5 -0
- data/lib/fron_ui/version.rb +7 -0
- data/opal/fron-ui/base.rb +49 -0
- data/opal/fron-ui/behaviors/action.rb +40 -0
- data/opal/fron-ui/behaviors/actions.rb +40 -0
- data/opal/fron-ui/behaviors/confirmation.rb +23 -0
- data/opal/fron-ui/behaviors/dropdown.rb +27 -0
- data/opal/fron-ui/behaviors/file.rb +48 -0
- data/opal/fron-ui/behaviors/intendable_children.rb +76 -0
- data/opal/fron-ui/behaviors/keydown.rb +31 -0
- data/opal/fron-ui/behaviors/loop.rb +41 -0
- data/opal/fron-ui/behaviors/render.rb +30 -0
- data/opal/fron-ui/behaviors/rest.rb +121 -0
- data/opal/fron-ui/behaviors/selectable_children.rb +67 -0
- data/opal/fron-ui/behaviors/serialize.rb +32 -0
- data/opal/fron-ui/behaviors/shortcuts.rb +35 -0
- data/opal/fron-ui/behaviors/state.rb +56 -0
- data/opal/fron-ui/behaviors/transition.rb +63 -0
- data/opal/fron-ui/components/action.rb +18 -0
- data/opal/fron-ui/components/box.rb +17 -0
- data/opal/fron-ui/components/button.rb +61 -0
- data/opal/fron-ui/components/calendar.rb +129 -0
- data/opal/fron-ui/components/checkbox.rb +57 -0
- data/opal/fron-ui/components/chooser.rb +246 -0
- data/opal/fron-ui/components/color_panel.rb +235 -0
- data/opal/fron-ui/components/color_picker.rb +111 -0
- data/opal/fron-ui/components/container.rb +61 -0
- data/opal/fron-ui/components/date_picker.rb +141 -0
- data/opal/fron-ui/components/drag.rb +76 -0
- data/opal/fron-ui/components/dropdown.rb +72 -0
- data/opal/fron-ui/components/icon.rb +29 -0
- data/opal/fron-ui/components/image.rb +77 -0
- data/opal/fron-ui/components/input.rb +30 -0
- data/opal/fron-ui/components/label.rb +9 -0
- data/opal/fron-ui/components/list.rb +34 -0
- data/opal/fron-ui/components/loader.rb +63 -0
- data/opal/fron-ui/components/modal.rb +0 -0
- data/opal/fron-ui/components/notifications.rb +73 -0
- data/opal/fron-ui/components/number.rb +202 -0
- data/opal/fron-ui/components/progress.rb +52 -0
- data/opal/fron-ui/components/slider.rb +47 -0
- data/opal/fron-ui/components/tabs.rb +149 -0
- data/opal/fron-ui/components/textarea.rb +13 -0
- data/opal/fron-ui/components/time.rb +65 -0
- data/opal/fron-ui/components/title.rb +34 -0
- data/opal/fron-ui/examples/blog/index.rb +289 -0
- data/opal/fron-ui/examples/comments/components/comment.rb +75 -0
- data/opal/fron-ui/examples/comments/components/comments.rb +93 -0
- data/opal/fron-ui/examples/comments/components/footer.rb +36 -0
- data/opal/fron-ui/examples/comments/components/header.rb +35 -0
- data/opal/fron-ui/examples/comments/components/list.rb +12 -0
- data/opal/fron-ui/examples/comments/index.rb +6 -0
- data/opal/fron-ui/examples/contacts/components/contacts.rb +100 -0
- data/opal/fron-ui/examples/contacts/components/details.rb +92 -0
- data/opal/fron-ui/examples/contacts/components/item.rb +46 -0
- data/opal/fron-ui/examples/contacts/components/list.rb +10 -0
- data/opal/fron-ui/examples/contacts/components/sidebar.rb +30 -0
- data/opal/fron-ui/examples/contacts/index.rb +6 -0
- data/opal/fron-ui/examples/editor/index.rb +164 -0
- data/opal/fron-ui/examples/kitchensink/index.rb +193 -0
- data/opal/fron-ui/examples/todos/components/item.rb +84 -0
- data/opal/fron-ui/examples/todos/components/options.rb +26 -0
- data/opal/fron-ui/examples/todos/components/todos.rb +145 -0
- data/opal/fron-ui/examples/todos/index.rb +6 -0
- data/opal/fron-ui/examples/webshop/index.rb +0 -0
- data/opal/fron-ui/fonts/ionicons.rb +2954 -0
- data/opal/fron-ui/fonts/open_sans.rb +19 -0
- data/opal/fron-ui/lib/collection.rb +138 -0
- data/opal/fron-ui/lib/date.rb +23 -0
- data/opal/fron-ui/lib/debounce.rb +14 -0
- data/opal/fron-ui/lib/image_loader.rb +13 -0
- data/opal/fron-ui/lib/lorem.rb +93 -0
- data/opal/fron-ui/lib/nil.rb +29 -0
- data/opal/fron-ui/lib/record.rb +23 -0
- data/opal/fron-ui/lib/state_serializer.rb +129 -0
- data/opal/fron-ui/lib/storage.rb +57 -0
- data/opal/fron-ui/spec/setup.rb +40 -0
- data/opal/fron-ui/ui.rb +40 -0
- data/opal/fron-ui/utils/theme_roller.rb +63 -0
- data/opal/fron-ui/vendor/autoprefixer.js +21114 -0
- data/opal/fron-ui/vendor/marked.js +1291 -0
- data/opal/fron-ui/vendor/md5.js +274 -0
- data/opal/fron-ui/vendor/moment.js +3083 -0
- data/opal/fron-ui/vendor/uuid.js +92 -0
- data/opal/fron_ui.rb +13 -0
- data/spec/behaviors/action_spec.rb +34 -0
- data/spec/behaviors/actions_spec.rb +38 -0
- data/spec/behaviors/confirmation_spec.rb +23 -0
- data/spec/behaviors/dropdown_spec.rb +32 -0
- data/spec/behaviors/render_spec.rb +20 -0
- data/spec/behaviors/rest_spec.rb +70 -0
- data/spec/behaviors/selectable_children_spec.rb +40 -0
- data/spec/behaviors/serialize_spec.rb +34 -0
- data/spec/components/action_spec.rb +7 -0
- data/spec/components/base_spec.rb +19 -0
- data/spec/components/box_spec.rb +7 -0
- data/spec/components/button_spec.rb +9 -0
- data/spec/components/calendar_spec.rb +58 -0
- data/spec/components/checkbox_spec.rb +20 -0
- data/spec/components/chooser_spec.rb +75 -0
- data/spec/components/color_panel_spec.rb +49 -0
- data/spec/components/color_picker_spec.rb +41 -0
- data/spec/components/container_spec.rb +23 -0
- data/spec/components/date_picker_spec.rb +71 -0
- data/spec/components/drag_spec.rb +20 -0
- data/spec/components/dropdown_spec.rb +33 -0
- data/spec/components/image_spec.rb +33 -0
- data/spec/components/input_spec.rb +8 -0
- data/spec/components/list_spec.rb +10 -0
- data/spec/components/loader_spec.rb +9 -0
- data/spec/components/notifications_spec.rb +17 -0
- data/spec/components/number_spec.rb +64 -0
- data/spec/components/progress_spec.rb +23 -0
- data/spec/components/slider_spec.rb +25 -0
- data/spec/components/tabs_spec.rb +50 -0
- data/spec/components/textarea_spec.rb +7 -0
- data/spec/components/time_spec.rb +37 -0
- data/spec/components/title_spec.rb +11 -0
- data/spec/examples/comments_spec.rb +72 -0
- data/spec/examples/todos_spec.rb +39 -0
- data/spec/lib/collection_spec.rb +38 -0
- data/spec/lib/lorem_spec.rb +55 -0
- data/spec/lib/state_serializer_spec.rb +58 -0
- data/spec/lib/storage_spec.rb +39 -0
- data/spec/spec_helper.rb +1 -0
- metadata +223 -0
data/lib/fron-ui.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'fron_ui'
|
data/lib/fron_ui.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# UI Module
|
|
2
|
+
module UI
|
|
3
|
+
# Base Component
|
|
4
|
+
class Base < Fron::Component
|
|
5
|
+
tag 'ui-base'
|
|
6
|
+
|
|
7
|
+
style '&[disabled]' => { pointerEvents: :none,
|
|
8
|
+
userSelect: :none,
|
|
9
|
+
opacity: 0.4 }
|
|
10
|
+
|
|
11
|
+
attribute_accessor :tabindex
|
|
12
|
+
|
|
13
|
+
# Disabled state
|
|
14
|
+
#
|
|
15
|
+
# * Doesn't trigger events -> ???
|
|
16
|
+
# * Not selectable -> pointer-events: none;
|
|
17
|
+
# * Cannot be tabbed -> remove tabindex if there is one?
|
|
18
|
+
def disabled=(value)
|
|
19
|
+
super
|
|
20
|
+
if disabled
|
|
21
|
+
self[:_tabindex] = self[:tabindex] if self[:tabindex]
|
|
22
|
+
remove_attribute :tabindex
|
|
23
|
+
self[:disabled] = ''
|
|
24
|
+
else
|
|
25
|
+
self[:tabindex] = self[:_tabindex] if self[:_tabindex]
|
|
26
|
+
remove_attribute :_tabindex
|
|
27
|
+
remove_attribute :disabled
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Sets the readonly state
|
|
32
|
+
#
|
|
33
|
+
# @param value [Boolean] The value
|
|
34
|
+
def readonly=(value)
|
|
35
|
+
if value
|
|
36
|
+
self[:readonly] = ''
|
|
37
|
+
else
|
|
38
|
+
remove_attribute :readonly
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Sets the flex value
|
|
43
|
+
#
|
|
44
|
+
# @param value [Numeric] The value
|
|
45
|
+
def flex=(value)
|
|
46
|
+
@style.flex = value
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
# Behaviors
|
|
3
|
+
module Behaviors
|
|
4
|
+
# Behavior for managing components
|
|
5
|
+
# that can respond to **action** - enter / space
|
|
6
|
+
#
|
|
7
|
+
# @author Gusztáv Szikszai
|
|
8
|
+
# @since 0.1.0
|
|
9
|
+
module Action
|
|
10
|
+
# Sets up the behavior:
|
|
11
|
+
#
|
|
12
|
+
# * Includes keydown behavior
|
|
13
|
+
# * Sets styles for :focus and :hover states
|
|
14
|
+
# * Sets up actions for enter and space
|
|
15
|
+
#
|
|
16
|
+
# @param base [Fron::Component] The includer
|
|
17
|
+
def self.included(base)
|
|
18
|
+
base.include Behaviors::Keydown
|
|
19
|
+
base.style cursor: :pointer,
|
|
20
|
+
userSelect: :none,
|
|
21
|
+
'> *' => { pointerEvents: :none },
|
|
22
|
+
'&:focus, &:hover' => {
|
|
23
|
+
color: -> { colors.focus },
|
|
24
|
+
outline: :none
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
base.keydown [:enter, :space], :action
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Action method, to be overriden.
|
|
31
|
+
#
|
|
32
|
+
# * Triggers click event
|
|
33
|
+
#
|
|
34
|
+
# @abstract
|
|
35
|
+
def action
|
|
36
|
+
trigger :click
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behaviors to handle basic method
|
|
4
|
+
# delegation via **action** attributes
|
|
5
|
+
# of the child components
|
|
6
|
+
#
|
|
7
|
+
# @author Gusztáv Szikszai
|
|
8
|
+
# @since 0.1.0
|
|
9
|
+
module Actions
|
|
10
|
+
IS_TOUCH = `'ontouchstart' in window && !window._phantom`
|
|
11
|
+
|
|
12
|
+
METHOD = IS_TOUCH ? :touchstart : :click
|
|
13
|
+
|
|
14
|
+
# Sets up the behavior:
|
|
15
|
+
#
|
|
16
|
+
# * Sets up event for the action
|
|
17
|
+
#
|
|
18
|
+
# @param base [Fron::Component] The includer
|
|
19
|
+
def self.included(base)
|
|
20
|
+
base.on METHOD, '[action]', :handle_action
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
# Handles the action event:
|
|
26
|
+
#
|
|
27
|
+
# * calls the method named as the
|
|
28
|
+
# targets action attribute
|
|
29
|
+
# * stops the event
|
|
30
|
+
#
|
|
31
|
+
# @param event [DOM::Event] The event
|
|
32
|
+
def handle_action(event)
|
|
33
|
+
method = event.target[:action]
|
|
34
|
+
return unless respond_to?(method)
|
|
35
|
+
event.stop
|
|
36
|
+
send method, event
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behavior for defining methods with
|
|
4
|
+
# a confirmation dialog, the given method
|
|
5
|
+
# only will be called if the user accepts.
|
|
6
|
+
#
|
|
7
|
+
# @author Gusztáv Szikszai
|
|
8
|
+
# @since 0.1.0
|
|
9
|
+
module Confirmation
|
|
10
|
+
# Sets up the behavior.
|
|
11
|
+
#
|
|
12
|
+
# @param base [Fron::Component] The includer
|
|
13
|
+
def self.included(base)
|
|
14
|
+
base.meta_def :confirmation do |name, message|
|
|
15
|
+
base.define_method "confirm_#{name}" do |*args|
|
|
16
|
+
break if message && !confirm(message)
|
|
17
|
+
send name, *args
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behavior for managing opening / closing
|
|
4
|
+
# of a dropdown.
|
|
5
|
+
#
|
|
6
|
+
# @author Gusztáv Szikszai
|
|
7
|
+
# @since 0.1.0
|
|
8
|
+
module Dropdown
|
|
9
|
+
# Sets up the behavior.
|
|
10
|
+
#
|
|
11
|
+
# @param base [Fron::Component] The includer
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.register self, [:dropdown]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Handles the initialization of
|
|
17
|
+
# the component
|
|
18
|
+
#
|
|
19
|
+
# @param item [Hash] The arguments
|
|
20
|
+
def self.dropdown(item)
|
|
21
|
+
input, dropdown = item[:args].map { |id| instance_variable_get("@#{id}") }
|
|
22
|
+
input.on(:focus) { dropdown.open }
|
|
23
|
+
input.on(:blur) { dropdown.close }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
module File
|
|
4
|
+
class << self
|
|
5
|
+
def handle_change
|
|
6
|
+
return unless file
|
|
7
|
+
@instance.send(@instance._on_file_select, file)
|
|
8
|
+
file_input.value = ''
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def file_input
|
|
12
|
+
@file_input ||= create_file_input
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def file
|
|
16
|
+
file_input.files[0]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_file_input
|
|
20
|
+
input = DOM::Element.new :input
|
|
21
|
+
input[:type] = :file
|
|
22
|
+
input.on(:change) { handle_change }
|
|
23
|
+
input >> DOM::Document.body
|
|
24
|
+
input.hide
|
|
25
|
+
input
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def included(base)
|
|
29
|
+
base.register self, [:on_file_select]
|
|
30
|
+
base.attr_reader :_on_file_select
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def select(instance)
|
|
34
|
+
@instance = instance
|
|
35
|
+
file_input.click
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def on_file_select(item)
|
|
39
|
+
@_on_file_select = item[:args][0]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def select_file
|
|
44
|
+
UI::Behaviors::File.select self
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behavior for handling intent for selecting
|
|
4
|
+
# elements.
|
|
5
|
+
#
|
|
6
|
+
# @author Gusztáv Szikszai
|
|
7
|
+
# @since 0.1.0
|
|
8
|
+
module IntendableChildren
|
|
9
|
+
# Sets up the behavior:
|
|
10
|
+
#
|
|
11
|
+
# * Sets styles for children
|
|
12
|
+
#
|
|
13
|
+
# @param base [Fron::Component] The includer
|
|
14
|
+
def self.included(base)
|
|
15
|
+
base.style '> .hidden' => { display: :none },
|
|
16
|
+
'> *:hover' => { background: -> { dampen colors.input, 0.05 } },
|
|
17
|
+
'> *.intended' => { background: -> { dampen colors.input, 0.1 } }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Intends selection for the
|
|
21
|
+
# next intendable item
|
|
22
|
+
def intend_next
|
|
23
|
+
intend_with :first, :next
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Intends selection for the
|
|
27
|
+
# previous intendable item
|
|
28
|
+
def intend_previous
|
|
29
|
+
intend_with :last, :previous
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Intends an item
|
|
33
|
+
#
|
|
34
|
+
# @param tail [Symbol] First or last
|
|
35
|
+
# @param method [Symbol] Next or previous
|
|
36
|
+
def intend_with(tail, method)
|
|
37
|
+
children = intend_children
|
|
38
|
+
index = children.index(intended)
|
|
39
|
+
next_indenteded = begin
|
|
40
|
+
case method
|
|
41
|
+
when :next
|
|
42
|
+
children[index + 1]
|
|
43
|
+
when :previous
|
|
44
|
+
children[index - 1]
|
|
45
|
+
end
|
|
46
|
+
rescue
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
intend next_indenteded || intend_children.send(tail)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Intends the given item
|
|
53
|
+
#
|
|
54
|
+
# @param item [Fron::Component] The item
|
|
55
|
+
def intend(item)
|
|
56
|
+
return unless item
|
|
57
|
+
intended.remove_class(:intended) if intended
|
|
58
|
+
item.add_class(:intended)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns the currently intended item
|
|
62
|
+
#
|
|
63
|
+
# @return [Fron::Component] The item
|
|
64
|
+
def intended
|
|
65
|
+
find('.intended')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns the children that can be intended
|
|
69
|
+
#
|
|
70
|
+
# @return [Array<Fron::Component>] The items
|
|
71
|
+
def intend_children
|
|
72
|
+
children.select { |child| !child.has_class :hidden }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behavior for managing key presses
|
|
4
|
+
#
|
|
5
|
+
# @author Gusztáv Szikszai
|
|
6
|
+
# @since 0.1.0
|
|
7
|
+
module Keydown
|
|
8
|
+
class << self
|
|
9
|
+
TYPES = %w(keyup keydown)
|
|
10
|
+
|
|
11
|
+
# Sets up the behavior.
|
|
12
|
+
#
|
|
13
|
+
# @param base [Fron::Component] The includer
|
|
14
|
+
def included(base)
|
|
15
|
+
base.register self, TYPES
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
TYPES.each do |type|
|
|
19
|
+
define_method type do |item|
|
|
20
|
+
on type do |event|
|
|
21
|
+
keys = Array(item[:args].first)
|
|
22
|
+
break unless keys.include?(event.key)
|
|
23
|
+
event.stop
|
|
24
|
+
send item[:args][1], event
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
module Loop
|
|
4
|
+
# Update / Render Loop
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.register self, [:act]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def data
|
|
10
|
+
@data ||= {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def update!(type, *args)
|
|
14
|
+
if type.is_a?(Array)
|
|
15
|
+
type.each { |item| update_act(*item) }
|
|
16
|
+
else
|
|
17
|
+
update_act(type, *args)
|
|
18
|
+
end
|
|
19
|
+
raise "Could not render #{self} because it's not defined!" unless respond_to?(:render)
|
|
20
|
+
render
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def replace!(data)
|
|
24
|
+
@data = data
|
|
25
|
+
render
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def update_act(type, *args)
|
|
29
|
+
raise "There is no update with the name #{type}!" unless @acts[type]
|
|
30
|
+
updated_data = @acts[type].call(*(args + [data]))
|
|
31
|
+
raise "Update didn't return a hash insted I got #{udpated_data}!" unless updated_data.is_a?(Hash)
|
|
32
|
+
data.merge! updated_data
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.act(item)
|
|
36
|
+
@acts ||= {}
|
|
37
|
+
@acts[item[:args].first] = item[:block]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module UI
|
|
2
|
+
module Behaviors
|
|
3
|
+
# Behavior for rendering with requestAnimationFrame
|
|
4
|
+
#
|
|
5
|
+
# @author Gusztáv Szikszai
|
|
6
|
+
# @since 0.1.0
|
|
7
|
+
module Render
|
|
8
|
+
# Sets up the behavior:
|
|
9
|
+
#
|
|
10
|
+
# * Defines the render method that will call
|
|
11
|
+
# the render proc
|
|
12
|
+
#
|
|
13
|
+
# @param base [Fron::Component] The includer
|
|
14
|
+
def self.included(base)
|
|
15
|
+
base.register self, [:render]
|
|
16
|
+
base.define_method :render do |&block|
|
|
17
|
+
@render_proc.call
|
|
18
|
+
block.call if block
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Defines the render proc from the item
|
|
23
|
+
#
|
|
24
|
+
# @param item [Hash] The arguments
|
|
25
|
+
def self.render(item)
|
|
26
|
+
@render_proc = Fron::RenderProc.new method(item[:args].first)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'promise'
|
|
2
|
+
|
|
3
|
+
module UI
|
|
4
|
+
module Behaviors
|
|
5
|
+
# Behavior for giving a component REST methods.
|
|
6
|
+
#
|
|
7
|
+
# @see http://en.wikipedia.org/wiki/Representational_state_transfer
|
|
8
|
+
#
|
|
9
|
+
# @author Gusztáv Szikszai
|
|
10
|
+
# @since 0.1.0
|
|
11
|
+
module Rest
|
|
12
|
+
extend Fron::Eventable
|
|
13
|
+
|
|
14
|
+
# Sets up the behavior.
|
|
15
|
+
#
|
|
16
|
+
# @param base [Fron::Component] The includer
|
|
17
|
+
def self.included(base)
|
|
18
|
+
base.register self, [:rest]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Sets the rest options from the registry
|
|
22
|
+
#
|
|
23
|
+
# @param item [Hash] The item
|
|
24
|
+
def self.rest(item)
|
|
25
|
+
@rest_options = OpenStruct.new item[:args].first
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Updates the model with the given data.
|
|
29
|
+
#
|
|
30
|
+
# @param data [Hash] The data
|
|
31
|
+
#
|
|
32
|
+
# @yield The updated data
|
|
33
|
+
def update(data, &block)
|
|
34
|
+
request :patch, @data[:id], data, &block
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Destroyes the model
|
|
38
|
+
#
|
|
39
|
+
# @yield if the action was successfull
|
|
40
|
+
def destroy(&block)
|
|
41
|
+
request :delete, @data[:id], &block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Creates a new model with the given data.
|
|
45
|
+
#
|
|
46
|
+
# @param data [Hash] The data
|
|
47
|
+
#
|
|
48
|
+
# @yield The actual created data
|
|
49
|
+
def create(data, &block)
|
|
50
|
+
request :post, '', data, &block
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns all recrods
|
|
54
|
+
#
|
|
55
|
+
# @yieldreturn [Array<Hash>] The recrods
|
|
56
|
+
def all(&block)
|
|
57
|
+
request :get, '', &block
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Makes a requests to server
|
|
61
|
+
#
|
|
62
|
+
# :reek:FeatureEnvy
|
|
63
|
+
#
|
|
64
|
+
# @param method [Symbol, String] The request method
|
|
65
|
+
# @param path [String] The URL
|
|
66
|
+
# @param params [Hash] The parameters
|
|
67
|
+
#
|
|
68
|
+
# @yield [Hash] The returned data
|
|
69
|
+
def request(method, path, params = {})
|
|
70
|
+
promise = Promise.new
|
|
71
|
+
req = create_request path
|
|
72
|
+
req.request method.upcase, params do |response|
|
|
73
|
+
if response.status == 0
|
|
74
|
+
raise_error :no_connection, "Could not connect to: #{req.url}", promise
|
|
75
|
+
elsif (200..300).cover?(response.status)
|
|
76
|
+
data = response_json(response)
|
|
77
|
+
promise.resolve data unless promise.realized?
|
|
78
|
+
yield data if block_given?
|
|
79
|
+
else
|
|
80
|
+
raise_error :wrong_status, response_json(response)['error'], promise
|
|
81
|
+
yield nil if block_given?
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
promise
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# Raises an error on the parent class.
|
|
90
|
+
#
|
|
91
|
+
# @param type [Symbol] The type
|
|
92
|
+
# @param message [String] The message
|
|
93
|
+
def raise_error(type, message, promise)
|
|
94
|
+
promise.reject(message) unless promise.realized?
|
|
95
|
+
UI::Behaviors::Rest.trigger type, message
|
|
96
|
+
UI::Behaviors::Rest.trigger :error, [type, message]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Tries to parse the json response,
|
|
100
|
+
# raises error if it's invalid.
|
|
101
|
+
#
|
|
102
|
+
# @param response [Fron::Response] The response
|
|
103
|
+
#
|
|
104
|
+
# @return [Hash] The parsed data
|
|
105
|
+
def response_json(response)
|
|
106
|
+
response.json
|
|
107
|
+
rescue StandardError
|
|
108
|
+
raise_error :invalid_json, 'Invalid JSON data!'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Creates a request object
|
|
112
|
+
#
|
|
113
|
+
# @param path [String] The URL
|
|
114
|
+
#
|
|
115
|
+
# @return [Fron::Request] The request
|
|
116
|
+
def create_request(path)
|
|
117
|
+
Fron::Request.new "#{@rest_options.url}/#{path}", 'Content-Type' => 'application/json'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|