glib-web 0.5.76 → 0.5.80

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e195cf56a4e446bc732f67732bd213af40b14bb6fb5d04eee102d28a2e552de4
4
- data.tar.gz: fce259c689b6eb4e886f132f396dd2f4b0c93bbf9d5665442dd6950bbcf90a2e
3
+ metadata.gz: e353f7685e62fafe9e1b265db2226f4d9c81def42152c51a4fd87508f90b8341
4
+ data.tar.gz: e4d4636d3b385b49c89efd0120e0fec04b1e259527377fa0cacd87912d0a4cd1
5
5
  SHA512:
6
- metadata.gz: b9f97af017b745de55389d63b6d8bdfef4ab479c1eca98287e00464ef8fad0a617c7ad4121a6da0905f13579ff81662dc056dd53df926010eb0c67b866cfdd5c
7
- data.tar.gz: 0042d88e51f14d8e52f859f27592aa81b3c594e4463845a067c84541495ff46055df363f0713b97222f01d37f91fbcae478ecddc7aaeeec704c09dd59571c724
6
+ metadata.gz: 52525e97d08b324b45d6c695fe4c033f58594a1e267125220e043d4fb004cfd56c9c7afb91cbd6b92a4ea76321fb9544115e5b034823c9a5335e33aafcf3ee75
7
+ data.tar.gz: f108306d3c3994752caf3a52801b278c9512b49b05f2c94b8835f51af7ec76ba88570ce08b28daeef1abeb798d6caea0b33a240f62e93d6f4fa9b24e2152b075
@@ -20,7 +20,7 @@ module Glib::Auth
20
20
  module Overrides
21
21
 
22
22
  public # Override
23
- def policy(record, policy_name = nil)
23
+ def policy(record, policy_name = nil, attributes = {})
24
24
  policy_name ||= record
25
25
 
26
26
  @__pundit_policies ||= {}
@@ -34,7 +34,7 @@ module Glib::Auth
34
34
 
35
35
  raise "Policy not found for #{policy_name.is_a?(Symbol) || policy_name.is_a?(Class) ? policy_name : policy_name.class}" unless policy_class
36
36
 
37
- @__pundit_policies[policy_name] = policy_class.new(current_user, record, policy_name, self, request, params, *policy_class.args_builder.call(self))
37
+ @__pundit_policies[policy_name] = policy_class.new(current_user, record, policy_name, self, request, params, attributes: attributes)
38
38
  end
39
39
 
40
40
  # Expose protected method
@@ -42,16 +42,17 @@ module Glib::Auth
42
42
  def policy_scope(*args)
43
43
  super
44
44
  end
45
+
45
46
  end
46
47
 
47
48
  private
48
- def raise_access_denied(record, policy)
49
- raise UnauthorizedError.new(record: record, policy: policy, query: "#{action_name}?")
50
- end
49
+ def raise_access_denied(record, policy)
50
+ raise UnauthorizedError.new(record: record, policy: policy, query: "#{action_name}?")
51
+ end
51
52
 
52
53
  public
53
- def can?(action, record)
54
- policy(record).send("#{action}?")
54
+ def can?(action, record, attributes = {})
55
+ policy(record, nil, attributes).send("#{action}?")
55
56
  end
56
57
 
57
58
  public
@@ -71,19 +72,19 @@ module Glib::Auth
71
72
  policy_name = resource_name.camelize.constantize
72
73
  else
73
74
  policy_name = case resource_key
74
- when false
75
- resource_name.to_sym
76
- when Symbol, Class
77
- resource_key
78
- else
79
- raise "Invalid resource class: #{resource_key}"
75
+ when false
76
+ resource_name.to_sym
77
+ when Symbol, Class
78
+ resource_key
79
+ else
80
+ raise "Invalid resource class: #{resource_key}"
80
81
  end
81
82
  end
82
83
 
83
84
  resource_instance = instance_variable_get("@#{resource_name}") || policy_name
84
85
 
85
86
  query = "#{action_name}?"
86
- policy_instance = policy(resource_instance, policy_name)
87
+ policy_instance = policy(resource_instance, policy_name, options.except(:class))
87
88
  raise_access_denied(resource_instance, policy_instance) unless policy_instance.public_send(query)
88
89
  end
89
90
 
@@ -118,12 +119,12 @@ module Glib::Auth
118
119
  begin
119
120
  if !(resource_key = options[:class]).nil?
120
121
  resource = case resource_key
121
- when false
122
- resource_name.to_sym
123
- when Symbol, Class
124
- resource_key
125
- else
126
- raise "Invalid resource class: #{resource_key}"
122
+ when false
123
+ resource_name.to_sym
124
+ when Symbol, Class
125
+ resource_key
126
+ else
127
+ raise "Invalid resource class: #{resource_key}"
127
128
  end
128
129
 
129
130
  authorize resource
@@ -0,0 +1,15 @@
1
+ class Glib::JsonUi::ActionBuilder
2
+ module Iap
3
+
4
+ class InitiatePurchase < Action
5
+ # Either `purchase` or `restore`
6
+ string :mode
7
+
8
+ string :productId
9
+
10
+ action :onSuccess
11
+ action :onFailure
12
+ end
13
+
14
+ end
15
+ end
@@ -29,5 +29,10 @@ class Glib::JsonUi::ActionBuilder
29
29
 
30
30
  required :fallbackUrl
31
31
  end
32
+
33
+ # Any component can listen to the refresh_state event and react appropriately.
34
+ # E.g. Stripe credit card component can refresh its token to make sure it is not stale.
35
+ class RefreshState < Action
36
+ end
32
37
  end
33
38
  end
@@ -225,6 +225,19 @@ class Glib::JsonUi::ViewBuilder
225
225
  hash :placeholderView
226
226
  end
227
227
 
228
+ # TODO
229
+ # class MultiImage < Text
230
+ # # file_rules = { fileType: 'image/*', maxFileSize: 5000 }
231
+ # # file_rules = { fileType: 'video/*', maxFileSize: 50000 }
232
+ # # file_rules = { fileType: 'application/pdf', maxFileSize: 5000 }
233
+ # # hash :accepts
234
+
235
+ # string :directUploadUrl
236
+ # # string :fileUrl
237
+ # # string :fileTitle
238
+ # hash :placeholderView
239
+ # end
240
+
228
241
  class Date < AbstractField
229
242
  date :min
230
243
  date :max
@@ -0,0 +1,11 @@
1
+ class Glib::JsonUi::ViewBuilder
2
+ module Iap
3
+
4
+ class ProductButton < View
5
+ string :text
6
+ string :productId
7
+ action :onClick
8
+ end
9
+
10
+ end
11
+ end
@@ -3,98 +3,123 @@
3
3
  module Glib
4
4
  class ApplicationPolicy
5
5
  attr_reader :user, :record, :policy_name, :controller, :request, :params
6
+ class_attribute :should_exist_attributes, instance_writer: false, default: []
6
7
 
7
8
  private
8
- def initialize(user, record, policy_name, 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
- @policy_name = policy_name
17
- end
9
+ def initialize(user, record, policy_name, controller, request, params, attributes: {})
10
+ @user = user
11
+ @record = record
12
+ @controller = controller
13
+ @request = request
14
+ # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
15
+ # See Presenter::Model::inside_mock_controller()
16
+ @params = params
17
+ @policy_name = policy_name
18
+
19
+ if attributes.present? && controller.action_name != 'index'
20
+ self.class.module_eval { attr_accessor(*attributes.keys) }
21
+ attributes.each do |key, value|
22
+ send("#{key}=", value)
23
+ end
24
+ end
18
25
 
19
- class << self
20
- attr_reader :catch_all
21
-
22
- # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
23
- # authorize().
24
- private # Used by child
25
- def authorize(*actions, &block)
26
- actions.each do |action|
27
- if action == :glib_all
28
- # Serve as a catch-all to all actions that have not been specified in the policy.
29
- @catch_all = block
30
- else
31
- method_name = "#{action}?"
32
- # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
33
- # wants to override the parent's authorization method.
34
- raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
35
- define_method method_name, &block
26
+ if controller.user_signed_in?
27
+ should_exist_attributes.each do |attribute|
28
+ if try(attribute).blank? && !['index'].include?(controller.action_name)
29
+ raise "Attribute #{attribute} is blank, policy will not working properly"
30
+ end
36
31
  end
37
32
  end
38
33
  end
39
- end
34
+
35
+ class << self
36
+ attr_reader :catch_all
37
+
38
+ def inherited(base)
39
+ base.should_exist_attributes = should_exist_attributes.dup
40
+ super
41
+ end
42
+
43
+ # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
44
+ # authorize().
45
+ private # Used by child
46
+ def authorize(*actions, &block)
47
+ actions.each do |action|
48
+ if action == :glib_all
49
+ # Serve as a catch-all to all actions that have not been specified in the policy.
50
+ @catch_all = block
51
+ else
52
+ method_name = "#{action}?"
53
+ # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
54
+ # wants to override the parent's authorization method.
55
+ raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
56
+ define_method method_name, &block
57
+ end
58
+ end
59
+ end
60
+
61
+ def should_exist(*attributes)
62
+ should_exist_attributes.push(*attributes)
63
+ end
64
+ end
40
65
 
41
66
  private
42
- def catch_all
43
- self.class.catch_all
44
- end
67
+ def catch_all
68
+ self.class.catch_all
69
+ end
45
70
 
46
71
  private
47
- # To ensure the block is called on the policy's instance instead class.
48
- def call_catch_all
49
- instance_eval(&catch_all)
50
- end
72
+ # To ensure the block is called on the policy's instance instead class.
73
+ def call_catch_all
74
+ instance_eval(&catch_all)
75
+ end
51
76
 
52
- authorize :index do
53
- # We need this line because in `index` action, this method will be called instead of method_missing().
54
- # Having this line ensures that the catch_all behaviour works according to the priority below:
55
- # - child_policy#index?
56
- # - child_policy#manage? -- catch_all
57
- # - application_policy@index?
58
- return call_catch_all if catch_all
77
+ authorize :index do
78
+ # We need this line because in `index` action, this method will be called instead of method_missing().
79
+ # Having this line ensures that the catch_all behaviour works according to the priority below:
80
+ # - child_policy#index?
81
+ # - child_policy#manage? -- catch_all
82
+ # - application_policy@index?
83
+ return call_catch_all if catch_all
59
84
 
60
- false
61
- end
85
+ false
86
+ end
62
87
 
63
- authorize :show do
64
- return call_catch_all if catch_all
88
+ authorize :show do
89
+ return call_catch_all if catch_all
65
90
 
66
- scope.where(id: record.id).exists?
67
- end
91
+ scope.where(id: record.id).exists?
92
+ end
68
93
 
69
- authorize :create do
70
- return call_catch_all if catch_all
94
+ authorize :create do
95
+ return call_catch_all if catch_all
71
96
 
72
- false
73
- end
97
+ false
98
+ end
74
99
 
75
- authorize :new do
76
- return call_catch_all if catch_all
100
+ authorize :new do
101
+ return call_catch_all if catch_all
77
102
 
78
- create?
79
- end
103
+ create?
104
+ end
80
105
 
81
- authorize :update do
82
- return call_catch_all if catch_all
106
+ authorize :update do
107
+ return call_catch_all if catch_all
83
108
 
84
- false
85
- end
109
+ false
110
+ end
86
111
 
87
- authorize :edit do
88
- return call_catch_all if catch_all
112
+ authorize :edit do
113
+ return call_catch_all if catch_all
89
114
 
90
- update?
91
- end
115
+ update?
116
+ end
92
117
 
93
- authorize :destroy do
94
- return call_catch_all if catch_all
118
+ authorize :destroy do
119
+ return call_catch_all if catch_all
95
120
 
96
- false
97
- end
121
+ false
122
+ end
98
123
 
99
124
  public
100
125
  def method_missing(name, *args, &block)
@@ -118,6 +143,11 @@ module Glib
118
143
  Proc.new { |controller| [] }
119
144
  end
120
145
 
146
+ public
147
+ def helpers
148
+ controller.helpers
149
+ end
150
+
121
151
  # TODO: Remove. Deprecated
122
152
  # private # Used by child
123
153
  # def public?
@@ -3,5 +3,8 @@ params.require(:user).each do |k, v|
3
3
  value = v.is_a?(String) ? '"' + v + '"' : v
4
4
  info += " #{k} => #{value}\n"
5
5
  end
6
- info += "}"
7
- action.dialogs_alert message: info
6
+ info += '}'
7
+
8
+ action.dialogs_alert message: info, onClose: ->(action) do
9
+ action.windows_refreshState
10
+ end
@@ -28,5 +28,10 @@ page.form options.merge(childViews: ->(form) do
28
28
  rules = { fileType: 'pdf', maxFileSize: 5000 }
29
29
  form.fields_file name: 'user[pdf2][]', width: 'matchParent', label: 'PDF Document', accepts: rules, directUploadUrl: rails_direct_uploads_url
30
30
 
31
+ # TODO
32
+ # rules = { fileType: 'image/*', maxFileSize: 1, fileTypeErrorText: 'Invalid!', maxFileSizeErrorText: 'Too big!' }
33
+ # form.fields_multiImage name: 'user[photos][]', width: 'matchParent', label: 'Avatar', accepts: rules, directUploadUrl: rails_direct_uploads_url,
34
+ # placeholderView: { type: 'avatar', width: 100, height: 100, url: 'data:image/jpeg;base64,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' }
35
+
31
36
  form.fields_submit text: 'Submit'
32
37
  end)
@@ -65,6 +65,9 @@ page.list sections: [
65
65
  template.thumbnail title: 'Timers', onClick: ->(action) do
66
66
  action.windows_open url: json_ui_garage_url(path: 'forms/timers')
67
67
  end
68
+ template.thumbnail title: 'Payments', onClick: ->(action) do
69
+ action.windows_open url: json_ui_garage_url(path: 'forms/payments')
70
+ end
68
71
  end
69
72
  end, ->(section) do
70
73
  section.header padding: glib_json_padding_list, childViews: ->(header) do
@@ -81,13 +84,13 @@ page.list sections: [
81
84
  end
82
85
 
83
86
  section.rows builder: ->(template) do
84
- template.thumbnail title: 'Rich Text Editor', onClick: ->(action) do
87
+ template.thumbnail title: 'Basic Rich Text Editor', onClick: ->(action) do
85
88
  action.windows_open url: json_ui_garage_url(path: 'forms/rich_text')
86
89
  end
87
90
  end
88
91
 
89
92
  section.rows builder: ->(template) do
90
- template.thumbnail title: 'New Rich Text Editor', onClick: ->(action) do
93
+ template.thumbnail title: 'Advanced Rich Text Editor', onClick: ->(action) do
91
94
  action.windows_open url: json_ui_garage_url(path: 'forms/new_rich_text')
92
95
  end
93
96
 
@@ -4,7 +4,7 @@ page = json_ui_page json
4
4
  render "#{@path_prefix}/nav_menu", json: json, page: page
5
5
 
6
6
  page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', padding: { top: 12, left: 20, right: 20, bottom: 12 }, childViews: ->(form) do
7
- form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name'
7
+ form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name', value: 'Rich Text Editor'
8
8
 
9
9
  # images = [
10
10
  # {
@@ -30,6 +30,7 @@ page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', pad
30
30
  end
31
31
 
32
32
  json.imageUploader do
33
+ json.fieldName 'user[images_attributes]'
33
34
  json.accepts(fileType: "image/*", maxFileSize: 5000)
34
35
  json.directUploadUrl rails_direct_uploads_url
35
36
  end
@@ -0,0 +1,34 @@
1
+ json.title 'Forms'
2
+
3
+ page = json_ui_page json
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ # Pass `refresh_state` to refresh the CC token after submission.
7
+ page.form \
8
+ url: json_ui_garage_url(path: 'forms/generic_post', refresh_state: true),
9
+ method: 'post',
10
+ padding: glib_json_padding_body,
11
+ childViews: ->(form) do
12
+ form.spacer height: 20
13
+ form.h2 text: 'Credit card'
14
+ form.spacer height: 6
15
+ form.fields_stripeToken \
16
+ name: 'user[stripe_token]',
17
+ width: 'matchParent',
18
+ publicKey: 'pk_test_TYooMQauvdEDq54NiTphI7jx'
19
+
20
+ form.spacer height: 20
21
+ form.h2 text: 'Bank account'
22
+ form.spacer height: 6
23
+ form.fields_stripeExternalAccount \
24
+ name: 'user[stripe_external_account]',
25
+ width: 'matchParent',
26
+ publicKey: 'pk_test_TYooMQauvdEDq54NiTphI7jx',
27
+ accountHolderName: 'John Doe',
28
+ accountHolderType: 'individual',
29
+ country: 'AU',
30
+ currency: 'AUD'
31
+
32
+ form.spacer height: 30
33
+ form.fields_submit text: 'Submit'
34
+ end
@@ -5,7 +5,7 @@ page = json_ui_page json
5
5
  render "#{@path_prefix}/nav_menu", json: json, page: page
6
6
 
7
7
  page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', padding: { top: 12, left: 20, right: 20, bottom: 12 }, childViews: ->(form) do
8
- form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name'
8
+ form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name', value: 'Rich Text Editor'
9
9
 
10
10
  # images = [
11
11
  # {
@@ -48,6 +48,26 @@ page.form url: json_ui_garage_url(path: 'forms/generic_post'), method: 'post', p
48
48
  ]
49
49
  }
50
50
 
51
+ form.spacer height: 6
52
+ form.fields_check name: 'user[check1]', checkValue: 'on', label: 'Show text'
53
+ form.spacer height: 10
54
+ form.label text: 'Checked', showIf: {
55
+ "==": [
56
+ {
57
+ "var": 'user[check1]'
58
+ },
59
+ 'on'
60
+ ]
61
+ }
62
+ form.label text: 'Checked', showIf: {
63
+ "!=": [
64
+ {
65
+ "var": 'user[check1]'
66
+ },
67
+ 'on'
68
+ ]
69
+ }
70
+
51
71
  form.spacer height: 20
52
72
  form.h1 text: 'Radio Group'
53
73
  form.fields_radioGroup name: 'user[radio1]', value: 'F', childViews: ->(group) do
@@ -34,7 +34,7 @@ page.form \
34
34
  form.fields_phone \
35
35
  name: 'user[phone2]',
36
36
  width: 'matchParent',
37
- label: "Phone field with Australia as the default country",
37
+ label: 'Phone field with Australia as the default country',
38
38
  disableAutoDetect: true, # Disable country auto detect by user IP
39
39
  defaultCountry: 'AU' # ISO Country code, see: https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
40
40
 
@@ -60,22 +60,6 @@ page.form \
60
60
  validation: { required: { message: 'Required' } },
61
61
  options: options
62
62
 
63
- form.spacer height: 20
64
- form.fields_stripeToken \
65
- name: 'user[stripe_token]',
66
- width: 'matchParent',
67
- publicKey: 'pk_test_TYooMQauvdEDq54NiTphI7jx'
68
-
69
- form.spacer height: 20
70
- form.fields_stripeExternalAccount \
71
- name: 'user[stripe_external_account]',
72
- width: 'matchParent',
73
- publicKey: 'pk_test_TYooMQauvdEDq54NiTphI7jx',
74
- accountHolderName: 'John Doe',
75
- accountHolderType: 'individual',
76
- country: 'AU',
77
- currency: 'AUD'
78
-
79
63
  form.spacer height: 30
80
64
  form.fields_submit text: 'Submit'
81
65
  end
@@ -7,30 +7,31 @@ json_ui_page json do |page|
7
7
  render "#{@path_prefix}/nav_menu", json: json, page: page
8
8
 
9
9
  page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
10
- scroll.label text: "\n"
11
10
  scroll.h1 text: 'Carousel with labels'
12
11
  scroll.panels_carousel width: 'matchParent', childViews: ->(carousel) do
13
12
  carousel.label text: 'Item 1'
14
13
  carousel.label text: 'Item 2'
15
14
  end
16
15
 
17
- scroll.label text: "\n"
16
+ scroll.spacer height: 20
18
17
  scroll.h1 text: 'Carousel with images'
19
18
  scroll.panels_carousel width: 'matchParent', childViews: ->(carousel) do
20
19
  carousel.image url: image_url1, width: 'matchParent'
21
20
  carousel.image url: image_url2, width: 'matchParent'
22
21
  end
23
22
 
24
- scroll.label text: "\n"
23
+ scroll.spacer height: 20
25
24
  scroll.h1 text: 'Carousel with complex layout'
26
25
  scroll.panels_carousel width: 'matchParent', childViews: ->(carousel) do
27
- carousel.panels_vertical childViews: ->(panel) do
26
+ height = 480
27
+
28
+ carousel.panels_vertical align: 'center', childViews: ->(panel) do
28
29
  panel.h3 text: 'Item 1'
29
- panel.image url: image_url1, width: 'matchParent'
30
+ panel.image height: height, url: image_url1
30
31
  end
31
- carousel.panels_vertical childViews: ->(panel) do
32
+ carousel.panels_vertical align: 'center', childViews: ->(panel) do
32
33
  panel.h3 text: 'Item 2'
33
- panel.image url: image_url2, width: 'matchParent'
34
+ panel.image height: height, url: image_url2
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,21 @@
1
+ json.title 'Views'
2
+
3
+ json_ui_page json do |page|
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
7
+
8
+ product_id = 'APP_STORE_PRODUCT_KEY'
9
+
10
+ scroll.h2 text: 'IAP product button'
11
+ scroll.spacer height: 6
12
+ scroll.iap_productButton text: 'GET', productId: product_id, onClick: ->(action) do
13
+ action.iap_initiatePurchase mode: 'purchase', productId: product_id, onSuccess: ->(subaction) do
14
+ subaction.dialogs_alert message: 'Success'
15
+ end, onFailure: ->(subaction) do
16
+ subaction.dialogs_alert message: 'Failure'
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -50,6 +50,17 @@ json_ui_page json do |page|
50
50
  end
51
51
  end
52
52
  end,
53
+ ->(section) do
54
+ section.header padding: glib_json_padding_list, childViews: ->(header) do
55
+ header.h2 text: 'Android and iOS only (experimental)'
56
+ end
57
+
58
+ section.rows builder: ->(template) do
59
+ template.thumbnail title: 'In-App Purchase', onClick: ->(action) do
60
+ action.windows_open url: json_ui_garage_url(path: 'views/iap')
61
+ end
62
+ end
63
+ end,
53
64
  ->(section) do
54
65
  section.header padding: glib_json_padding_list, childViews: ->(header) do
55
66
  header.h2 text: 'Reference'
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="<%= I18n.locale %>">
3
3
 
4
4
  <head>
5
5
  <meta charset="utf-8" />
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glib-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.76
4
+ version: 0.5.80
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -93,6 +93,7 @@ files:
93
93
  - app/helpers/glib/json_ui/action_builder.rb
94
94
  - app/helpers/glib/json_ui/action_builder/dialogs.rb
95
95
  - app/helpers/glib/json_ui/action_builder/http.rb
96
+ - app/helpers/glib/json_ui/action_builder/iap.rb
96
97
  - app/helpers/glib/json_ui/action_builder/panels.rb
97
98
  - app/helpers/glib/json_ui/action_builder/sheets.rb
98
99
  - app/helpers/glib/json_ui/action_builder/snackbars.rb
@@ -111,6 +112,7 @@ files:
111
112
  - app/helpers/glib/json_ui/view_builder/banners.rb
112
113
  - app/helpers/glib/json_ui/view_builder/charts.rb
113
114
  - app/helpers/glib/json_ui/view_builder/fields.rb
115
+ - app/helpers/glib/json_ui/view_builder/iap.rb
114
116
  - app/helpers/glib/json_ui/view_builder/panels.rb
115
117
  - app/helpers/glib/urls_helper.rb
116
118
  - app/models/concerns/glib/soft_deletable.rb
@@ -150,6 +152,7 @@ files:
150
152
  - app/views/json_ui/garage/forms/new_rich_text.json.jbuilder
151
153
  - app/views/json_ui/garage/forms/online_participant1.json.jbuilder
152
154
  - app/views/json_ui/garage/forms/online_participant2.json.jbuilder
155
+ - app/views/json_ui/garage/forms/payments.json.jbuilder
153
156
  - app/views/json_ui/garage/forms/pickers.json.jbuilder
154
157
  - app/views/json_ui/garage/forms/ratings.json.jbuilder
155
158
  - app/views/json_ui/garage/forms/rich_text.json.jbuilder
@@ -216,6 +219,7 @@ files:
216
219
  - app/views/json_ui/garage/views/calendar_data.json.jbuilder
217
220
  - app/views/json_ui/garage/views/charts.json.jbuilder
218
221
  - app/views/json_ui/garage/views/controls.json.jbuilder
222
+ - app/views/json_ui/garage/views/iap.json.jbuilder
219
223
  - app/views/json_ui/garage/views/icon_names.json.jbuilder
220
224
  - app/views/json_ui/garage/views/icons.json.jbuilder
221
225
  - app/views/json_ui/garage/views/images.json.jbuilder