glib-web 4.3.0 → 4.4.1
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 +4 -4
- data/app/controllers/glib/glib_direct_uploads_controller.rb +1 -1
- data/app/controllers/glib/home_controller.rb +5 -0
- data/app/helpers/glib/enum_helper.rb +5 -6
- data/app/helpers/glib/json_ui/abstract_builder.rb +1 -1
- data/app/helpers/glib/json_ui/action_builder/browsers.rb +12 -0
- data/app/helpers/glib/json_ui/action_builder/fields.rb +6 -0
- data/app/helpers/glib/json_ui/action_builder/files.rb +8 -0
- data/app/helpers/glib/json_ui/action_builder/logics.rb +9 -0
- data/app/helpers/glib/json_ui/action_builder/storage_items.rb +23 -0
- data/app/helpers/glib/json_ui/action_builder.rb +0 -18
- data/app/helpers/glib/json_ui/list_builders.rb +16 -1
- data/app/helpers/glib/json_ui/menu_builder.rb +1 -1
- data/app/helpers/glib/json_ui/page_helper.rb +3 -2
- data/app/helpers/glib/json_ui/view_builder/charts.rb +3 -2
- data/app/helpers/glib/json_ui/view_builder/fields.rb +37 -29
- data/app/helpers/glib/json_ui/view_builder/panels.rb +40 -11
- data/app/helpers/glib/json_ui/view_builder.rb +20 -8
- data/app/models/glib/dummy_job_application.rb +3 -2
- data/app/views/json_ui/garage/_nav_menu.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/_alert_post_all_data.json.jbuilder +4 -0
- data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +2 -2
- data/app/views/json_ui/garage/forms/generic_post_all.json.jbuilder +3 -0
- data/app/views/json_ui/garage/forms/selects.json.jbuilder +0 -1
- data/app/views/json_ui/garage/forms/show_hide.json.jbuilder +41 -7
- data/app/views/json_ui/garage/forms/submit_on_change.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/text_validation.json.jbuilder +13 -8
- data/app/views/json_ui/garage/panels/index.json.jbuilder +4 -0
- data/app/views/json_ui/garage/panels/tree.json.jbuilder +77 -0
- data/app/views/json_ui/garage/test_page/_header.json.jbuilder +14 -0
- data/app/views/json_ui/garage/test_page/auto_validate.json.jbuilder +77 -0
- data/app/views/json_ui/garage/test_page/dialog.json.jbuilder +38 -0
- data/app/views/json_ui/garage/test_page/dialog_open.json.jbuilder +14 -0
- data/app/views/json_ui/garage/test_page/form.json.jbuilder +111 -0
- data/app/views/json_ui/garage/test_page/form_dynamic.json.jbuilder +63 -0
- data/app/views/json_ui/garage/test_page/multiupload.json.jbuilder +65 -0
- data/lib/glib/mailer_tester.rb +1 -1
- metadata +14 -2
- data/app/views/json_ui/garage/test_page/index.json.jbuilder +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 324be9293b997d23666ea14d20515bb5e8aef6e7fa962f4cf1ccba6ade3d6d1e
|
4
|
+
data.tar.gz: 0b4a0e7f36dfb0e6cbac8f83dbc904451d1c59e02d212b5a6c2af4bda8e8c092
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 752f7e4b42626d97625f169b933a9e44eb6d968a54c3adfc0945434e785a2d0ef03daf7708cd63f36cb28c6f6e235d3eb5e0cc491abd9ad10da3e377fcdeabd4
|
7
|
+
data.tar.gz: 7b9d408aeff03b974f026a26c96128569d0976f2d5bd4745cebaa0c3877a652fc335dc03e62b2ab3949c7dbff53a922b8462243b2f4a1bcc83df19b29409c515
|
@@ -19,12 +19,11 @@ module Glib
|
|
19
19
|
# TZInfo::Timezone.default_dst = true
|
20
20
|
return [] if Rails.env.test?
|
21
21
|
|
22
|
-
ActiveSupport::TimeZone.all.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
22
|
+
ActiveSupport::TimeZone.all.group_by { |tz| tz.tzinfo.identifier }.map do |identifier, timezones|
|
23
|
+
utc_offset = "#{timezones.first.utc_offset >= 0 ? '+' : ''}#{timezones.first.utc_offset / 60 / 60}h"
|
24
|
+
locations = timezones.map(&:name).join(', ')
|
25
|
+
{ value: identifier, text: "#{utc_offset} #{locations}" }
|
26
|
+
end
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -287,7 +287,7 @@ module Glib
|
|
287
287
|
optional = options[:optional] || []
|
288
288
|
|
289
289
|
required.each do |req|
|
290
|
-
raise ArgumentError, "Hash property: '#{req}' is
|
290
|
+
raise ArgumentError, "Hash property: '#{req}' is required" if value[req.to_s].blank?
|
291
291
|
end
|
292
292
|
|
293
293
|
if optional.present?
|
@@ -7,6 +7,8 @@ class Glib::JsonUi::ActionBuilder
|
|
7
7
|
hash :data
|
8
8
|
hash :variables
|
9
9
|
action :onSet
|
10
|
+
bool :cacheData
|
11
|
+
bool :debug
|
10
12
|
|
11
13
|
def dataBuilder(block)
|
12
14
|
json.data do
|
@@ -15,6 +17,13 @@ class Glib::JsonUi::ActionBuilder
|
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
20
|
+
class Run < Action
|
21
|
+
hash :condition
|
22
|
+
hash :variables
|
23
|
+
action :onTrue
|
24
|
+
action :onFalse
|
25
|
+
end
|
26
|
+
|
18
27
|
# Under consideration, likely not a good idea.
|
19
28
|
# class Append < Action
|
20
29
|
# string :targetId
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Glib::JsonUi::ActionBuilder
|
2
|
+
# FUTURE
|
3
|
+
module StorageItems
|
4
|
+
class Set < Action
|
5
|
+
string :key
|
6
|
+
string :value
|
7
|
+
action :onSet
|
8
|
+
end
|
9
|
+
|
10
|
+
class Get < Action
|
11
|
+
string :key
|
12
|
+
action :onGet
|
13
|
+
end
|
14
|
+
|
15
|
+
class Remove < Action
|
16
|
+
action :onRemove
|
17
|
+
end
|
18
|
+
|
19
|
+
class Clear < Action
|
20
|
+
action :onClear
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -157,24 +157,6 @@ module Glib
|
|
157
157
|
# class Clear < Action
|
158
158
|
# end
|
159
159
|
end
|
160
|
-
|
161
|
-
# FUTURE
|
162
|
-
|
163
|
-
module Data
|
164
|
-
class Save < Action
|
165
|
-
string :key
|
166
|
-
string :value
|
167
|
-
action :onSave
|
168
|
-
end
|
169
|
-
|
170
|
-
class Remove < Action
|
171
|
-
end
|
172
|
-
|
173
|
-
class Clear < Action
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
###
|
178
160
|
end
|
179
161
|
end
|
180
162
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Glib
|
2
2
|
module JsonUi
|
3
3
|
module ListBuilders
|
4
|
-
class
|
4
|
+
class ListTemplate < AbstractBuilder
|
5
5
|
def method_missing(m, *args)
|
6
6
|
add_element_to_array 'template', m, *args
|
7
7
|
end
|
@@ -76,6 +76,21 @@ module Glib
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
class TreeTemplate < AbstractBuilder
|
80
|
+
def method_missing(m, *args)
|
81
|
+
add_element_to_array 'template', m, *args
|
82
|
+
end
|
83
|
+
|
84
|
+
class Standard < JsonUiElement
|
85
|
+
string :id
|
86
|
+
string :title
|
87
|
+
action :onClick
|
88
|
+
hash :dropData
|
89
|
+
hash :icon, required: [:name], optional: [:color]
|
90
|
+
array :rows
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
79
94
|
class Section < AbstractBuilder
|
80
95
|
def initialize(json, page, template)
|
81
96
|
super json, page
|
@@ -85,7 +85,7 @@ module Glib
|
|
85
85
|
include Glib::JsonUi::Default
|
86
86
|
|
87
87
|
attr_reader :json, :context, :view_builder, :sview_builder, :action_builder, :menu_builder
|
88
|
-
attr_reader :list_section_builder, :table_section_builder, :drawer_content_builder
|
88
|
+
attr_reader :list_section_builder, :table_section_builder, :drawer_content_builder, :tree_section_builder
|
89
89
|
|
90
90
|
# See Panels::Form
|
91
91
|
attr_accessor :current_form
|
@@ -99,7 +99,8 @@ module Glib
|
|
99
99
|
@action_builder = ActionBuilder.new(json, self, false)
|
100
100
|
@menu_builder = MenuBuilder.new(json, self)
|
101
101
|
|
102
|
-
@list_section_builder = ListBuilders::Section.new(json, self, ListBuilders::
|
102
|
+
@list_section_builder = ListBuilders::Section.new(json, self, ListBuilders::ListTemplate.new(json, self))
|
103
|
+
@tree_section_builder = ListBuilders::Section.new(json, self, ListBuilders::TreeTemplate.new(json, self))
|
103
104
|
@drawer_content_builder = ListBuilders::Section.new(json, self, @menu_builder)
|
104
105
|
@table_section_builder = TableBuilders::Section.new(json, self, TableBuilders::Template.new(json, self))
|
105
106
|
# @split_content_builder = SplitBuilders::Content.new(json, self, @view_builder)
|
@@ -43,8 +43,9 @@ class Glib::JsonUi::ViewBuilder
|
|
43
43
|
string :suffix
|
44
44
|
int :min
|
45
45
|
int :max
|
46
|
-
|
47
|
-
hash :
|
46
|
+
# https://www.chartjs.org/docs/latest/configuration/legend.html
|
47
|
+
hash :legend, optional: [:position, :align, :display, :maxHeight, :maxWidth, :fullSize, :reverse, :labels, :rtl, :title]
|
48
|
+
hash :plugins, optional: [:datalabels, :centerLabel, :customTooltip]
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
@@ -6,7 +6,6 @@ class Glib::JsonUi::ViewBuilder
|
|
6
6
|
|
7
7
|
bool :readOnly
|
8
8
|
bool :disabled
|
9
|
-
hash :validation
|
10
9
|
bool :disableDirtyCheck
|
11
10
|
action :onChange
|
12
11
|
action :onChangeAndLoad
|
@@ -17,6 +16,16 @@ class Glib::JsonUi::ViewBuilder
|
|
17
16
|
{ only_path: true }
|
18
17
|
end
|
19
18
|
|
19
|
+
def validation(validation)
|
20
|
+
return if validation.blank?
|
21
|
+
|
22
|
+
if validation[:format].present?
|
23
|
+
context.cast_to_js_regex(validation[:format])
|
24
|
+
end
|
25
|
+
|
26
|
+
json.validation validation
|
27
|
+
end
|
28
|
+
|
20
29
|
def label(label)
|
21
30
|
@label = label
|
22
31
|
end
|
@@ -66,7 +75,9 @@ class Glib::JsonUi::ViewBuilder
|
|
66
75
|
@label ||= context.field_label(@prop, @label_args || {})
|
67
76
|
@hint ||= context.hint_label(@prop, @hint_args || {})
|
68
77
|
@placeholder ||= context.placeholder_label(@prop, @placeholder_args || {})
|
69
|
-
|
78
|
+
if form._autoValidate && @autoValidate.nil? || !@autoValidate.nil? && @autoValidate
|
79
|
+
@validation ||= context.field_validation(@prop)
|
80
|
+
end
|
70
81
|
|
71
82
|
if form.current_dynamic_group.nil?
|
72
83
|
# This is not relevant inside a dynamic group
|
@@ -127,7 +138,7 @@ class Glib::JsonUi::ViewBuilder
|
|
127
138
|
end
|
128
139
|
|
129
140
|
class Timer < Text
|
130
|
-
hash :actionCable
|
141
|
+
# hash :actionCable
|
131
142
|
int :min
|
132
143
|
int :max
|
133
144
|
bool :forward
|
@@ -142,6 +153,8 @@ class Glib::JsonUi::ViewBuilder
|
|
142
153
|
string :text
|
143
154
|
color :color
|
144
155
|
icon :icon
|
156
|
+
# This will not work if the form contains multiple fields with the same name,
|
157
|
+
# even if only one field is showing at any one time"
|
145
158
|
bool :disableIfFormInvalid
|
146
159
|
end
|
147
160
|
|
@@ -156,6 +169,7 @@ class Glib::JsonUi::ViewBuilder
|
|
156
169
|
string :onIcon
|
157
170
|
string :offIcon
|
158
171
|
string :onLabel
|
172
|
+
hash :image, required: [:url, :template], optional: [:width, :height]
|
159
173
|
|
160
174
|
def value(value)
|
161
175
|
@value = value if value != Glib::Value::DEFAULT
|
@@ -168,7 +182,7 @@ class Glib::JsonUi::ViewBuilder
|
|
168
182
|
|
169
183
|
class RichText < Text
|
170
184
|
array :images
|
171
|
-
hash :imageUploader
|
185
|
+
hash :imageUploader, required: [:name], optional: [:accepts, :directUploadUrl]
|
172
186
|
# `html` or `markdown`
|
173
187
|
string :produce
|
174
188
|
string :accept
|
@@ -180,7 +194,7 @@ class Glib::JsonUi::ViewBuilder
|
|
180
194
|
# bool :readOnly
|
181
195
|
bool :multiple, cache: true
|
182
196
|
# bool :manualEntry
|
183
|
-
hash :append
|
197
|
+
hash :append, optional: [:icon]
|
184
198
|
|
185
199
|
panels_builder :accessory, :header, :footer
|
186
200
|
end
|
@@ -257,10 +271,15 @@ class Glib::JsonUi::ViewBuilder
|
|
257
271
|
action :onClick
|
258
272
|
string :offIcon
|
259
273
|
string :onIcon
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
274
|
+
hash :image, required: [:url, :template], optional: [:width, :height]
|
275
|
+
hash :icon, required: [:name, :template], optional: [:color, :size]
|
276
|
+
# bool :featured
|
277
|
+
# bool :thumbnail
|
278
|
+
# hash :image
|
279
|
+
# string :imageUrl
|
280
|
+
# string :icon
|
281
|
+
# string :iconColor
|
282
|
+
# string :iconSize
|
264
283
|
|
265
284
|
views :childViews
|
266
285
|
end
|
@@ -269,16 +288,14 @@ class Glib::JsonUi::ViewBuilder
|
|
269
288
|
# file_rules = { fileType: 'image/*', maxFileSize: 5000 }
|
270
289
|
# file_rules = { fileType: 'video/*', maxFileSize: 50000 }
|
271
290
|
# file_rules = { fileType: 'application/pdf', maxFileSize: 5000 }
|
272
|
-
hash :accepts
|
273
291
|
|
274
|
-
|
292
|
+
include Glib::JsonUi::Upload
|
293
|
+
|
275
294
|
string :fileUrl
|
276
295
|
string :fileTitle
|
277
296
|
string :uploadText
|
278
|
-
hash :placeholderView
|
279
|
-
hash :infoSpec
|
280
|
-
string :storagePrefix
|
281
|
-
hash :metadata
|
297
|
+
hash :placeholderView # deprecated
|
298
|
+
hash :infoSpec # deprecated
|
282
299
|
|
283
300
|
def buttonLabels(obj)
|
284
301
|
@buttonLabels = ActiveSupport::HashWithIndifferentAccess.new(obj)
|
@@ -314,23 +331,14 @@ class Glib::JsonUi::ViewBuilder
|
|
314
331
|
|
315
332
|
class MultiUpload < AbstractField
|
316
333
|
include Glib::JsonUi::Default
|
334
|
+
include Glib::JsonUi::Upload
|
317
335
|
|
318
|
-
# hash :accepts
|
319
336
|
array :files
|
320
|
-
string :directUploadUrl
|
321
337
|
string :uploadTitle
|
322
338
|
action :onFinishUpload
|
323
|
-
string :strategy # can be "delegate" or "dropUpload"
|
324
339
|
string :url # http post end point if you don't want to use onFinishUpload
|
325
|
-
|
326
|
-
string :storagePrefix
|
327
|
-
hash :metadata
|
328
|
-
string :tagging
|
329
|
-
hash :tags
|
330
|
-
|
331
340
|
required :accepts, :directUploadUrl
|
332
341
|
|
333
|
-
|
334
342
|
def accepts(value)
|
335
343
|
@accepts = value
|
336
344
|
end
|
@@ -354,10 +362,10 @@ class Glib::JsonUi::ViewBuilder
|
|
354
362
|
@responseMessages[status] = I18n.t(key) if I18n.exists?(key)
|
355
363
|
end
|
356
364
|
json.responseMessages (@responseMessages || {}).reverse_merge({
|
357
|
-
'200' => '
|
365
|
+
'200' => 'Completed',
|
358
366
|
'403' => 'Forbidden',
|
359
367
|
'401' => 'Session expired',
|
360
|
-
'else' => '
|
368
|
+
'else' => 'Failed'
|
361
369
|
})
|
362
370
|
|
363
371
|
json.placeholder @placeholder if @placeholder
|
@@ -378,7 +386,6 @@ class Glib::JsonUi::ViewBuilder
|
|
378
386
|
|
379
387
|
class Sign < AbstractField
|
380
388
|
string :directUploadUrl
|
381
|
-
|
382
389
|
required :directUploadUrl
|
383
390
|
|
384
391
|
# Override
|
@@ -422,7 +429,8 @@ class Glib::JsonUi::ViewBuilder
|
|
422
429
|
hash :latitudeField
|
423
430
|
hash :longitudeField
|
424
431
|
hash :zoomField
|
425
|
-
|
432
|
+
# https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions
|
433
|
+
hash :autocompleteOptions, optional: [:bounds, :componentRestrictions, :fields, :strictBounds, :types]
|
426
434
|
end
|
427
435
|
|
428
436
|
class StripeToken < AbstractField
|
@@ -125,6 +125,10 @@ class Glib::JsonUi::ViewBuilder
|
|
125
125
|
self.class.field_validation(@model, prop)
|
126
126
|
end
|
127
127
|
|
128
|
+
def cast_to_js_regex(format_validation)
|
129
|
+
self.class.cast_to_js_regex(format_validation)
|
130
|
+
end
|
131
|
+
|
128
132
|
def self.lookup_error_message(model_name, attribute_name, key)
|
129
133
|
message = I18n.t("activerecord.errors.models.#{model_name}.attributes.#{attribute_name}.#{key}", default: nil) if model_name.present? && attribute_name.present?
|
130
134
|
message ||= I18n.t("activerecord.errors.models.#{model_name}.#{key}", default: nil) if model_name.present?
|
@@ -134,6 +138,18 @@ class Glib::JsonUi::ViewBuilder
|
|
134
138
|
message
|
135
139
|
end
|
136
140
|
|
141
|
+
def self.cast_to_js_regex(format_validation)
|
142
|
+
if format_validation[:with].instance_of?(Regexp)
|
143
|
+
format_validation[:with] = JsRegex.new(format_validation[:with]).source
|
144
|
+
end
|
145
|
+
if format_validation[:without].instance_of?(Regexp)
|
146
|
+
format_validation[:without] = JsRegex.new(format_validation[:without]).source
|
147
|
+
end
|
148
|
+
if format_validation[:regex].instance_of?(Regexp)
|
149
|
+
format_validation[:regex] = JsRegex.new(format_validation[:regex]).source
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
137
153
|
def self.field_validation(model, prop)
|
138
154
|
validations = {}
|
139
155
|
ignored = ['confirmation', 'comparison', 'uniqueness', 'validates_associated', 'validates_each', 'validates_with']
|
@@ -157,12 +173,7 @@ class Glib::JsonUi::ViewBuilder
|
|
157
173
|
'less_than_or_equal_to', 'other_than', 'in', 'odd', 'even'
|
158
174
|
].inject({}) { |prev, curr| prev.merge(curr => lookup_error_message(model.to_s.underscore, prop, curr)) }
|
159
175
|
when :format
|
160
|
-
|
161
|
-
validations[validator.kind][:with] = JsRegex.new(validations[validator.kind][:with]).source
|
162
|
-
end
|
163
|
-
if validations[validator.kind][:without].instance_of?(Regexp)
|
164
|
-
validations[validator.kind][:without] = JsRegex.new(validations[validator.kind][:without]).source
|
165
|
-
end
|
176
|
+
cast_to_js_regex(validations[validator.kind])
|
166
177
|
validations[validator.kind][:message] ||= lookup_error_message(model.to_s.underscore, prop, 'invalid')
|
167
178
|
when :inclusion
|
168
179
|
validations[validator.kind][:message] ||= lookup_error_message(model.to_s.underscore, prop, 'inclusion')
|
@@ -250,10 +261,11 @@ class Glib::JsonUi::ViewBuilder
|
|
250
261
|
string :fieldSubsubtitleName
|
251
262
|
|
252
263
|
# This can be used to implement "check all" and "uncheck all".
|
264
|
+
# deprecated?
|
253
265
|
hash :fieldCheckValueIf
|
254
266
|
|
255
267
|
hash :phoenixSocket
|
256
|
-
hash :actionCable
|
268
|
+
# hash :actionCable
|
257
269
|
|
258
270
|
hash :nextPage
|
259
271
|
hash :prevPage
|
@@ -289,8 +301,8 @@ class Glib::JsonUi::ViewBuilder
|
|
289
301
|
|
290
302
|
class Table < View
|
291
303
|
hash :nextPage
|
292
|
-
hash :export
|
293
|
-
hash :import
|
304
|
+
hash :export, required: [:label, :fileName]
|
305
|
+
hash :import, required: [:submitUrl, :paramName]
|
294
306
|
action :onScrollToTop
|
295
307
|
action :onScrollToBottom
|
296
308
|
|
@@ -371,11 +383,11 @@ class Glib::JsonUi::ViewBuilder
|
|
371
383
|
string :distribution
|
372
384
|
string :align
|
373
385
|
action :onClick
|
374
|
-
hash :dragSupport
|
386
|
+
hash :dragSupport, optional: [:onDrop, :paramNameForFormData, :paramNameForNewIndex]
|
375
387
|
end
|
376
388
|
|
377
389
|
class Flow < View
|
378
|
-
hash :innerPadding
|
390
|
+
hash :innerPadding, optional: [:top, :right, :bottom, :left, :x, :y]
|
379
391
|
views :childViews
|
380
392
|
|
381
393
|
required :innerPadding
|
@@ -412,6 +424,23 @@ class Glib::JsonUi::ViewBuilder
|
|
412
424
|
views :childViews
|
413
425
|
end
|
414
426
|
|
427
|
+
class Tree < View
|
428
|
+
include Glib::JsonUi::Upload
|
429
|
+
|
430
|
+
string :selected
|
431
|
+
action :onDrop
|
432
|
+
|
433
|
+
def sections(blocks)
|
434
|
+
json.sections do
|
435
|
+
blocks.each do |block|
|
436
|
+
json.child! do
|
437
|
+
block.call page.tree_section_builder
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
415
444
|
class Web < View
|
416
445
|
string :url
|
417
446
|
end
|
@@ -1,5 +1,20 @@
|
|
1
1
|
module Glib
|
2
2
|
module JsonUi
|
3
|
+
|
4
|
+
module Upload
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
string :directUploadUrl
|
9
|
+
hash :accepts, optional: [:fileType, :maxFileSize, :maxFileLength, :maxFileSizeErrorText, :maxFileLengthErrorText]
|
10
|
+
string :strategy # can be "delegate" or "dropUpload"
|
11
|
+
string :storagePrefix
|
12
|
+
hash :metadata
|
13
|
+
string :tagging
|
14
|
+
hash :tags
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
3
18
|
class ViewBuilder < AbstractBuilder
|
4
19
|
def initialize(json, page, multiple)
|
5
20
|
super(json, page)
|
@@ -38,7 +53,7 @@ module Glib
|
|
38
53
|
length :width
|
39
54
|
length :height
|
40
55
|
color :backgroundColor
|
41
|
-
hash :padding
|
56
|
+
hash :padding, optional: [:top, :right, :bottom, :left, :x, :y, :all]
|
42
57
|
singleton_array :styleClass, :styleClasses
|
43
58
|
|
44
59
|
hash :showIf
|
@@ -49,7 +64,7 @@ module Glib
|
|
49
64
|
bool :displayed
|
50
65
|
bool :submitWhenNotDisplayed
|
51
66
|
|
52
|
-
hash :analytics
|
67
|
+
hash :analytics, optional: [:featured, :disabled]
|
53
68
|
hash :dragData
|
54
69
|
|
55
70
|
def self.component_name
|
@@ -139,7 +154,7 @@ module Glib
|
|
139
154
|
end
|
140
155
|
|
141
156
|
class Label < AbstractText
|
142
|
-
hash :actionCable
|
157
|
+
# hash :actionCable
|
143
158
|
# string :format
|
144
159
|
action :onClick
|
145
160
|
end
|
@@ -315,16 +330,13 @@ module Glib
|
|
315
330
|
end
|
316
331
|
|
317
332
|
class TreeView < View
|
333
|
+
include Glib::JsonUi::Upload
|
334
|
+
|
318
335
|
string :inputName
|
319
336
|
string :url
|
320
|
-
string :directUploadUrl
|
321
|
-
hash :accepts
|
322
337
|
string :selected
|
323
338
|
array :items
|
324
339
|
hash :dropData
|
325
|
-
string :strategy
|
326
|
-
string :storagePrefix
|
327
|
-
hash :metadata
|
328
340
|
end
|
329
341
|
end
|
330
342
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Glib
|
2
2
|
class DummyJobApplication
|
3
|
+
include ActiveModel::Model
|
3
4
|
include ActiveModel::Validations
|
4
5
|
include ActiveModel::AttributeMethods
|
5
6
|
|
6
|
-
attr_accessor :name, :age, :position, :words, :accept
|
7
|
+
attr_accessor :name, :age, :position, :words, :accept, :pet_you_have
|
7
8
|
|
8
9
|
validates :name, :position, presence: true
|
9
10
|
validates :accept, acceptance: {}, allow_nil: false
|
@@ -11,6 +12,6 @@ module Glib
|
|
11
12
|
validates :age, numericality: { only_integer: true, less_than_or_equal_to: 30, greater_than_or_equal_to: 18 }, allow_blank: true
|
12
13
|
validates :name, format: { with: /Doe\z/, message: 'This job is for person end with Doe' }
|
13
14
|
validates :position, inclusion: { in: ['programmer', 'devops', 'designer'] }, allow_blank: true
|
14
|
-
|
15
|
+
validates :pet_you_have, exclusion: { in: ['crocodile', 'shark' ], message: 'We dont accept that kind of animal!' }, allow_blank: true
|
15
16
|
end
|
16
17
|
end
|
@@ -52,7 +52,7 @@ if local_assigns[:top_nav] || json_ui_app_is_web?
|
|
52
52
|
end
|
53
53
|
|
54
54
|
menu.button text: 'Test Page', onClick: ->(action) do
|
55
|
-
action.windows_open url: json_ui_garage_url(path: 'test_page/
|
55
|
+
action.windows_open url: json_ui_garage_url(path: 'test_page/form')
|
56
56
|
end
|
57
57
|
|
58
58
|
menu.divider
|
@@ -17,7 +17,7 @@ page.form options.merge(childViews: ->(form) do
|
|
17
17
|
fileTitle: '1 month ago',
|
18
18
|
placeholderView: { type: 'image', width: 100, height: 75, url: 'https://www.atms.com.au/wp-content/uploads/2019/10/placeholder-1-1024x683.png?x93630' }
|
19
19
|
|
20
|
-
rules = { fileType: 'image', maxFileSize: 1,
|
20
|
+
rules = { fileType: 'image', maxFileSize: 1, maxFileSizeErrorText: 'Too big!' }
|
21
21
|
form.fields_file name: 'user[photo][]', width: 'matchParent', label: 'Avatar', accepts: rules, directUploadUrl: glib_direct_uploads_url,
|
22
22
|
placeholderView: { type: 'avatar', width: 100, height: 100, url: 'data:image/jpeg;base64,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' }
|
23
23
|
|
@@ -32,7 +32,7 @@ page.form options.merge(childViews: ->(form) do
|
|
32
32
|
form.fields_file name: 'user[zip][]', width: 'matchParent', label: 'ZIP Document', accepts: rules, directUploadUrl: glib_direct_uploads_url
|
33
33
|
|
34
34
|
# TODO
|
35
|
-
# rules = { fileType: 'image/*', maxFileSize: 1,
|
35
|
+
# rules = { fileType: 'image/*', maxFileSize: 1, maxFileSizeErrorText: 'Too big!' }
|
36
36
|
# form.fields_multiImage name: 'user[photos][]', width: 'matchParent', label: 'Avatar', accepts: rules, directUploadUrl: glib_direct_uploads_url,
|
37
37
|
# placeholderView: { type: 'avatar', width: 100, height: 100, url: 'data:image/jpeg;base64,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' }
|
38
38
|
|