glib-web 0.4.22 → 0.4.23

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.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/app/controllers/concerns/glib/auth/policy.rb +0 -0
  3. data/app/controllers/concerns/glib/json/new_dynamic_text.rb +0 -0
  4. data/app/controllers/concerns/glib/json/traversal.rb +0 -0
  5. data/app/controllers/glib/home_controller.rb +0 -0
  6. data/app/helpers/glib/dynamic_images_helper.rb +0 -0
  7. data/app/helpers/glib/dynamic_texts_helper.rb +0 -0
  8. data/app/helpers/glib/json_ui/abstract_builder.rb +6 -0
  9. data/app/helpers/glib/json_ui/action_builder/dialogs.rb +63 -0
  10. data/app/helpers/glib/json_ui/action_builder/sheets.rb +15 -0
  11. data/app/helpers/glib/json_ui/action_builder/snackbars.rb +41 -0
  12. data/app/helpers/glib/json_ui/action_builder/windows.rb +25 -0
  13. data/app/helpers/glib/json_ui/action_builder.rb +0 -113
  14. data/app/helpers/glib/json_ui/dynamic_field_builders.rb +25 -0
  15. data/app/helpers/glib/json_ui/generic_builders.rb +28 -0
  16. data/app/helpers/glib/json_ui/list_builders.rb +0 -0
  17. data/app/helpers/glib/json_ui/menu_builder.rb +0 -0
  18. data/app/helpers/glib/json_ui/page_helper.rb +13 -1
  19. data/app/helpers/glib/json_ui/response_helper.rb +3 -3
  20. data/app/helpers/glib/json_ui/split_builders.rb +2 -2
  21. data/app/helpers/glib/json_ui/styling_helper.rb +0 -0
  22. data/app/helpers/glib/json_ui/table_builders.rb +0 -0
  23. data/app/helpers/glib/json_ui/view_builder/banners.rb +3 -2
  24. data/app/helpers/glib/json_ui/view_builder/fields.rb +6 -3
  25. data/app/helpers/glib/json_ui/view_builder/panels.rb +0 -0
  26. data/app/helpers/glib/json_ui/view_builder.rb +0 -0
  27. data/app/models/glib/active_storage/attachment.rb +0 -0
  28. data/app/models/glib/active_storage/blob.rb +0 -0
  29. data/app/models/glib/dynamic_text_record.rb +0 -0
  30. data/app/models/glib/text.rb +0 -0
  31. data/app/policies/glib/application_policy.rb +148 -148
  32. data/app/views/app/views/json_ui/vue/renderer.html.erb +0 -0
  33. data/app/views/json_ui/garage/_nav_menu.json.jbuilder +0 -0
  34. data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +95 -0
  35. data/app/views/json_ui/garage/actions/_sheets.json.jbuilder +19 -0
  36. data/app/views/json_ui/garage/actions/_snackbars.json.jbuilder +33 -0
  37. data/app/views/json_ui/garage/actions/_windows.json.jbuilder +24 -0
  38. data/app/views/json_ui/garage/actions/index.json.jbuilder +5 -109
  39. data/app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder +0 -0
  40. data/app/views/json_ui/garage/forms/basic.json.jbuilder +0 -0
  41. data/app/views/json_ui/garage/forms/basic_post.json.jbuilder +0 -0
  42. data/app/views/json_ui/garage/forms/checkboxes.json.jbuilder +0 -0
  43. data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +21 -4
  44. data/app/views/json_ui/garage/forms/dynamic_select.json.jbuilder +0 -0
  45. data/app/views/json_ui/garage/forms/dynamic_select_data.json.jbuilder +0 -0
  46. data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +0 -0
  47. data/app/views/json_ui/garage/forms/floating_submit.json.jbuilder +0 -0
  48. data/app/views/json_ui/garage/forms/generic_post.json.jbuilder +0 -0
  49. data/app/views/json_ui/garage/forms/get_request.json.jbuilder +0 -0
  50. data/app/views/json_ui/garage/forms/index.json.jbuilder +0 -0
  51. data/app/views/json_ui/garage/forms/pickers.json.jbuilder +0 -0
  52. data/app/views/json_ui/garage/forms/rich_text.json.jbuilder +0 -0
  53. data/app/views/json_ui/garage/forms/selects.json.jbuilder +0 -0
  54. data/app/views/json_ui/garage/forms/submission_flow.json.jbuilder +0 -0
  55. data/app/views/json_ui/garage/forms/submission_flow_post.json.jbuilder +0 -0
  56. data/app/views/json_ui/garage/forms/submission_indicator.json.jbuilder +0 -0
  57. data/app/views/json_ui/garage/forms/submission_indicator_post.json.jbuilder +0 -0
  58. data/app/views/json_ui/garage/forms/text_validation.json.jbuilder +0 -0
  59. data/app/views/json_ui/garage/home/blank.json.jbuilder +0 -0
  60. data/app/views/json_ui/garage/home/index.json.jbuilder +0 -0
  61. data/app/views/json_ui/garage/lists/_infinite_scroll_section.json.jbuilder +0 -0
  62. data/app/views/json_ui/garage/lists/edit_actions.json.jbuilder +0 -0
  63. data/app/views/json_ui/garage/lists/fab.json.jbuilder +0 -0
  64. data/app/views/json_ui/garage/lists/index.json.jbuilder +0 -0
  65. data/app/views/json_ui/garage/lists/infinite_scroll.json.jbuilder +0 -0
  66. data/app/views/json_ui/garage/lists/templating.json.jbuilder +0 -0
  67. data/app/views/json_ui/garage/notifications/index.json.jbuilder +2 -2
  68. data/app/views/json_ui/garage/pages/flat_centered.json.jbuilder +0 -0
  69. data/app/views/json_ui/garage/pages/full_width.json.jbuilder +0 -0
  70. data/app/views/json_ui/garage/pages/full_width_height.json.jbuilder +0 -0
  71. data/app/views/json_ui/garage/pages/index.json.jbuilder +0 -0
  72. data/app/views/json_ui/garage/pages/layout.json.jbuilder +0 -0
  73. data/app/views/json_ui/garage/pages/nav_buttons.json.jbuilder +0 -0
  74. data/app/views/json_ui/garage/pages/tab_bar.json.jbuilder +0 -0
  75. data/app/views/json_ui/garage/panels/card.json.jbuilder +0 -0
  76. data/app/views/json_ui/garage/panels/carousel.json.jbuilder +0 -0
  77. data/app/views/json_ui/garage/panels/custom.json.jbuilder +0 -0
  78. data/app/views/json_ui/garage/panels/horizontal.json.jbuilder +0 -0
  79. data/app/views/json_ui/garage/panels/index.json.jbuilder +0 -0
  80. data/app/views/json_ui/garage/panels/responsive.json.jbuilder +0 -0
  81. data/app/views/json_ui/garage/panels/split.json.jbuilder +0 -0
  82. data/app/views/json_ui/garage/panels/vertical.json.jbuilder +0 -0
  83. data/app/views/json_ui/garage/services/dynamic_text.json.jbuilder +0 -0
  84. data/app/views/json_ui/garage/services/image.json.jbuilder +0 -0
  85. data/app/views/json_ui/garage/services/index.json.jbuilder +0 -0
  86. data/app/views/json_ui/garage/tables/_autoload_section.json.jbuilder +0 -0
  87. data/app/views/json_ui/garage/tables/autoload_all.json.jbuilder +0 -0
  88. data/app/views/json_ui/garage/tables/export_import.json.jbuilder +0 -0
  89. data/app/views/json_ui/garage/tables/horizontal_scroll.json.jbuilder +0 -0
  90. data/app/views/json_ui/garage/tables/index.json.jbuilder +0 -0
  91. data/app/views/json_ui/garage/views/banners.json.jbuilder +22 -5
  92. data/app/views/json_ui/garage/views/calendar_data.json.jbuilder +0 -0
  93. data/app/views/json_ui/garage/views/carousels.json.jbuilder +0 -0
  94. data/app/views/json_ui/garage/views/charts.json.jbuilder +0 -0
  95. data/app/views/json_ui/garage/views/images.json.jbuilder +0 -0
  96. data/app/views/json_ui/garage/views/index.json.jbuilder +2 -32
  97. data/app/views/json_ui/garage/views/links.json.jbuilder +0 -0
  98. data/app/views/json_ui/garage/views/map_data.json.jbuilder +0 -0
  99. data/app/views/json_ui/garage/views/misc.json.jbuilder +0 -0
  100. data/app/views/json_ui/garage/views/texts.json.jbuilder +0 -0
  101. data/config/routes.rb +0 -0
  102. data/lib/generators/glib/install_generator.rb +0 -0
  103. data/lib/generators/templates/20191017062519_create_texts.rb +0 -0
  104. data/lib/generators/templates/20191024063257_add_scope_to_texts.rb +0 -0
  105. data/lib/generators/templates/20191112095018_add_lang_to_texts.rb +0 -0
  106. data/lib/generators/templates/20191126071051_create_active_storage_tables.active_storage.rb +0 -0
  107. data/lib/generators/templates/database.yml +0 -0
  108. data/lib/generators/templates/dynamic_text.rb +0 -0
  109. data/lib/glib/dynamic_text/config.rb +0 -0
  110. data/lib/glib/dynamic_text.rb +0 -0
  111. data/lib/glib/engine.rb +0 -0
  112. data/lib/glib/json_crawler/action_crawler.rb +0 -0
  113. data/lib/glib/json_crawler/action_crawlers/action_http.rb +0 -0
  114. data/lib/glib/json_crawler/action_crawlers/forms_submit.rb +0 -0
  115. data/lib/glib/json_crawler/action_crawlers/nav_initiate.rb +0 -0
  116. data/lib/glib/json_crawler/action_crawlers/windows_open.rb +0 -0
  117. data/lib/glib/json_crawler/http.rb +10 -4
  118. data/lib/glib/json_crawler/router.rb +2 -2
  119. data/lib/glib/json_crawler.rb +0 -0
  120. data/lib/glib/value.rb +0 -0
  121. data/lib/glib/version.rb +0 -0
  122. data/lib/glib-web.rb +0 -0
  123. data/lib/tasks/db.rake +82 -0
  124. metadata +13 -2
File without changes
File without changes
@@ -1,9 +1,10 @@
1
1
  class Glib::JsonUi::ViewBuilder
2
2
  module Banners
3
-
3
+
4
4
  class Alert < View
5
5
  icon :icon
6
6
  string :message
7
+ # string :message_format
7
8
  singleton_array :styleClass, :styleClasses
8
9
  end
9
10
 
@@ -12,7 +13,7 @@ class Glib::JsonUi::ViewBuilder
12
13
  icon :icon
13
14
  string :message
14
15
  singleton_array :styleClass, :styleClasses
15
-
16
+
16
17
  def buttons(block)
17
18
  json.buttons do
18
19
  block.call page.menu_builder
@@ -138,8 +138,11 @@ class Glib::JsonUi::ViewBuilder
138
138
  end
139
139
 
140
140
  class DynamicGroup < AbstractField
141
- string :groupTitlePrefix
142
- views :groupTemplateViews
141
+ string :titlePrefix
142
+ panels_builder :content, :template
143
+
144
+ # NOTE: Consider using sub-panel instead (e.g. groupTemplate)
145
+ # views :groupTemplateViews
143
146
  end
144
147
 
145
148
  class RadioGroup < View
@@ -189,6 +192,6 @@ class Glib::JsonUi::ViewBuilder
189
192
  class StripeToken < AbstractField
190
193
  string :publicKey
191
194
  end
192
-
195
+
193
196
  end
194
197
  end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,148 +1,148 @@
1
- # The main purpose of this is for security. If it is important to display useful error message or to provide a "banana", then
2
- # it's better to perform an explicit check (e.g. as a validation in the model or using a before_action).
3
- module Glib
4
- class ApplicationPolicy
5
- attr_reader :user, :record, :controller, :request, :params
6
-
7
- private
8
- def initialize(user, record, controller, request, params)
9
- @user = user
10
- @record = record
11
- @controller = controller
12
- @request = request
13
- # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
14
- # See Presenter::Model::inside_mock_controller()
15
- @params = params
16
- end
17
-
18
- class << self
19
- attr_reader :catch_all
20
-
21
- # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
22
- # authorize().
23
- private # Used by child
24
- def authorize(*actions, &block)
25
- actions.each do |action|
26
- if action == :manage
27
- # Serve as a catch-all to all actions that have not been specified in the policy.
28
- @catch_all = block
29
- else
30
- method_name = "#{action}?"
31
- # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
32
- # wants to override the parent's authorization method.
33
- raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
34
- define_method method_name, &block
35
- end
36
- end
37
- end
38
- end
39
-
40
- private
41
- def catch_all
42
- self.class.catch_all
43
- end
44
-
45
- private
46
- # To ensure the block is called on the policy's instance instead class.
47
- def call_catch_all
48
- instance_eval(&catch_all)
49
- end
50
-
51
- authorize :index do
52
- # We need this line because in `index` action, this method will be called instead of method_missing().
53
- # Having this line ensures that the catch_all behaviour works according to the priority below:
54
- # - child_policy#index?
55
- # - child_policy#manage? -- catch_all
56
- # - application_policy@index?
57
- return call_catch_all if catch_all
58
-
59
- false
60
- end
61
-
62
- authorize :show do
63
- return call_catch_all if catch_all
64
-
65
- scope.where(id: record.id).exists?
66
- end
67
-
68
- authorize :create do
69
- return call_catch_all if catch_all
70
-
71
- false
72
- end
73
-
74
- authorize :new do
75
- return call_catch_all if catch_all
76
-
77
- create?
78
- end
79
-
80
- authorize :update do
81
- return call_catch_all if catch_all
82
-
83
- false
84
- end
85
-
86
- authorize :edit do
87
- return call_catch_all if catch_all
88
-
89
- update?
90
- end
91
-
92
- authorize :destroy do
93
- return call_catch_all if catch_all
94
-
95
- false
96
- end
97
-
98
- public
99
- def method_missing(name, *args, &block)
100
- if name.to_s.end_with?('?') && catch_all
101
- call_catch_all
102
- else
103
- super
104
- end
105
- end
106
-
107
- public
108
- def scope
109
- Pundit.policy_scope!(user, record.class)
110
- end
111
-
112
- private # Used by child
113
- def public?
114
- true
115
- end
116
-
117
- # # TODO: Revise because it seems there is no justification for allowing owner to see any of the deleted entities, which include User, Guild, and Post
118
- # private # Used by child
119
- # def not_deleted_unless_owner_or_moderator?(&block)
120
- # block ||= lambda { |unused_arg| @user.moderator? }
121
- # !@record.deleted? || (@user && (@user.id == @record.user_owner_id || block.call(@record)))
122
- # end
123
-
124
- # private # Used by child
125
- # def not_deleted_unless_moderator?(&block)
126
- # block ||= lambda { |unused_arg| @user.moderator? }
127
- # !@record.deleted? || (@user && block.call(@record))
128
- # end
129
-
130
- public
131
- def self.args_builder
132
- Proc.new { |controller| [] }
133
- end
134
-
135
- class Scope
136
- attr_reader :user, :scope
137
-
138
- def initialize(user, scope)
139
- @user = user
140
- @scope = scope
141
- end
142
-
143
- def resolve
144
- scope
145
- end
146
- end
147
- end
148
- end
1
+ # The main purpose of this is for security. If it is important to display useful error message or to provide a "banana", then
2
+ # it's better to perform an explicit check (e.g. as a validation in the model or using a before_action).
3
+ module Glib
4
+ class ApplicationPolicy
5
+ attr_reader :user, :record, :controller, :request, :params
6
+
7
+ private
8
+ def initialize(user, record, controller, request, params)
9
+ @user = user
10
+ @record = record
11
+ @controller = controller
12
+ @request = request
13
+ # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
14
+ # See Presenter::Model::inside_mock_controller()
15
+ @params = params
16
+ end
17
+
18
+ class << self
19
+ attr_reader :catch_all
20
+
21
+ # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
22
+ # authorize().
23
+ private # Used by child
24
+ def authorize(*actions, &block)
25
+ actions.each do |action|
26
+ if action == :manage
27
+ # Serve as a catch-all to all actions that have not been specified in the policy.
28
+ @catch_all = block
29
+ else
30
+ method_name = "#{action}?"
31
+ # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
32
+ # wants to override the parent's authorization method.
33
+ raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
34
+ define_method method_name, &block
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ def catch_all
42
+ self.class.catch_all
43
+ end
44
+
45
+ private
46
+ # To ensure the block is called on the policy's instance instead class.
47
+ def call_catch_all
48
+ instance_eval(&catch_all)
49
+ end
50
+
51
+ authorize :index do
52
+ # We need this line because in `index` action, this method will be called instead of method_missing().
53
+ # Having this line ensures that the catch_all behaviour works according to the priority below:
54
+ # - child_policy#index?
55
+ # - child_policy#manage? -- catch_all
56
+ # - application_policy@index?
57
+ return call_catch_all if catch_all
58
+
59
+ false
60
+ end
61
+
62
+ authorize :show do
63
+ return call_catch_all if catch_all
64
+
65
+ scope.where(id: record.id).exists?
66
+ end
67
+
68
+ authorize :create do
69
+ return call_catch_all if catch_all
70
+
71
+ false
72
+ end
73
+
74
+ authorize :new do
75
+ return call_catch_all if catch_all
76
+
77
+ create?
78
+ end
79
+
80
+ authorize :update do
81
+ return call_catch_all if catch_all
82
+
83
+ false
84
+ end
85
+
86
+ authorize :edit do
87
+ return call_catch_all if catch_all
88
+
89
+ update?
90
+ end
91
+
92
+ authorize :destroy do
93
+ return call_catch_all if catch_all
94
+
95
+ false
96
+ end
97
+
98
+ public
99
+ def method_missing(name, *args, &block)
100
+ if name.to_s.end_with?('?') && catch_all
101
+ call_catch_all
102
+ else
103
+ super
104
+ end
105
+ end
106
+
107
+ public
108
+ def scope
109
+ Pundit.policy_scope!(user, record.class)
110
+ end
111
+
112
+ private # Used by child
113
+ def public?
114
+ true
115
+ end
116
+
117
+ # # TODO: Revise because it seems there is no justification for allowing owner to see any of the deleted entities, which include User, Guild, and Post
118
+ # private # Used by child
119
+ # def not_deleted_unless_owner_or_moderator?(&block)
120
+ # block ||= lambda { |unused_arg| @user.moderator? }
121
+ # !@record.deleted? || (@user && (@user.id == @record.user_owner_id || block.call(@record)))
122
+ # end
123
+
124
+ # private # Used by child
125
+ # def not_deleted_unless_moderator?(&block)
126
+ # block ||= lambda { |unused_arg| @user.moderator? }
127
+ # !@record.deleted? || (@user && block.call(@record))
128
+ # end
129
+
130
+ public
131
+ def self.args_builder
132
+ Proc.new { |controller| [] }
133
+ end
134
+
135
+ class Scope
136
+ attr_reader :user, :scope
137
+
138
+ def initialize(user, scope)
139
+ @user = user
140
+ @scope = scope
141
+ end
142
+
143
+ def resolve
144
+ scope
145
+ end
146
+ end
147
+ end
148
+ end
File without changes
File without changes
@@ -0,0 +1,95 @@
1
+
2
+ section.header padding: glib_json_padding_list, childViews: ->(header) do
3
+ header.h3 text: 'Dialogs'
4
+ end
5
+
6
+ section.rows builder: ->(template) do
7
+ template.thumbnail title: 'dialogs/alert', onClick: ->(action) do
8
+ action.dialogs_alert message: 'This is an alert dialog', onClose: ->(action) do
9
+ action.snackbars_alert message: 'Closed'
10
+ end
11
+ end
12
+
13
+ # markdown = '# h1 Heading' + "\n" +
14
+ # '## h2 Heading' + "\n" +
15
+ # '### h3 Heading' + "\n" +
16
+ # '#### h4 Heading' + "\n" +
17
+ # '##### h5 Heading' + "\n" +
18
+ # '###### h6 Heading' + "\n" +
19
+ # "\n" +
20
+ # '## Emphasis' + "\n" +
21
+ # "\n" +
22
+ # '**This is bold text**' + "\n" +
23
+ # "\n" +
24
+ # '__This is bold text__' + "\n" +
25
+ # "\n" +
26
+ # '*This is italic text*' + "\n" +
27
+ # "\n" +
28
+ # '_This is italic text_' + "\n" +
29
+ # "\n" +
30
+ # '~~Strikethrough~~' + "\n"
31
+ # template.thumbnail title: 'dialogs/alert with markdown', onClick: ->(action) do
32
+ # action.dialogs_alert message: markdown, message_format: 'markdown'
33
+ # end
34
+
35
+ # template.thumbnail title: 'dialogs/confirm (Experimental)', onClick: ->(action) do
36
+ # action.dialogs_confirm message: 'This is a confirm dialog', onCancel: ->(action) do
37
+ # action.snackbars_alert message: 'Canceled'
38
+ # end, onConfirm: ->(action) do
39
+ # action.snackbars_alert message: 'Confirmed'
40
+ # end
41
+ # end
42
+
43
+ # TODO: Deprecate
44
+ template.thumbnail title: 'dialogs/option (Deprecated)', onClick: ->(action) do
45
+ # TODO: Rename to `dialogs/menu`
46
+ action.dialogs_options message: 'Select one', buttons: ->(menu) do
47
+ menu.button text: 'Option1', onClick: ->(action) do
48
+ action.dialogs_alert message: 'Option 1'
49
+ end
50
+ menu.button text: 'Option2', onClick: ->(action) do
51
+ action.dialogs_alert message: 'Option 2'
52
+ end
53
+ menu.button text: 'Cancel'
54
+ end
55
+ end
56
+
57
+ markdown = '## Emphasis' + "\n" +
58
+ '**This is bold text**' + "\n" +
59
+ "\n" +
60
+ '*This is italic text*' + "\n" +
61
+ "\n" +
62
+ '~~Strikethrough~~' + "\n"
63
+ template.thumbnail title: 'dialogs/show', onClick: ->(action) do
64
+ action.dialogs_show content: ->(dialog) do
65
+ dialog.body padding: glib_json_padding_body, childViews: ->(body) do
66
+ body.markdown text: markdown
67
+
68
+ body.panels_split width: 'matchParent', content: ->(split) do
69
+ split.right childViews: ->(right) do
70
+ right.button text: 'OK', onClick: ->(subaction) { subaction.dialogs_close }
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ template.thumbnail title: 'dialogs/open', onClick: ->(action) do
78
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/basic', mode: 'dialog')
79
+ end
80
+
81
+ template.thumbnail title: 'dialogs/oauth', onClick: ->(action) do
82
+ provider = {
83
+ name: "facebook",
84
+ webRequestUrl: "https://www.facebook.com/v3.1/dialog/oauth?auth_type=rerequest&client_id=CLIENT_ID&redirect_uri=http%3A%2F%2Fwww.lvh.me%3A3000%2Foauth_callback%2Ffacebook&response_type=code&scope=email",
85
+ requestUrl: "https://www.facebook.com/v3.1/dialog/oauth",
86
+ clientId: "CLIENT_ID",
87
+ redirectUrl: "http://www.lvh.me:3000/oauth_callback/facebook.json"
88
+ }
89
+
90
+ action.dialogs_oauth provider: provider, providerParamName: "session[oauth_provider]", callbackUrlParamName: "session[[oauth_callback_url]", onSuccess: ->(action) do
91
+ action.http_post url: 'TODO: post params to server'
92
+ end
93
+ end
94
+
95
+ end