glib-web 4.36.7 → 4.36.9
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/helpers/glib/json_ui/action_builder/popovers.rb +1 -1
- data/app/helpers/glib/json_ui/menu_builder.rb +1 -1
- data/app/helpers/glib/json_ui/view_builder/fields.rb +51 -6
- data/app/helpers/glib/json_ui/view_builder.rb +73 -0
- data/app/views/json_ui/garage/_nav_menu.json.jbuilder +11 -0
- data/app/views/json_ui/garage/actions/_reload.json.jbuilder +6 -0
- data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/file_upload_new.json.jbuilder +128 -0
- data/app/views/json_ui/garage/forms/index.json.jbuilder +3 -0
- data/app/views/json_ui/garage/views/controls.json.jbuilder +3 -1
- data/app/views/json_ui/garage/views/popovers_open.json.jbuilder +4 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a129200d9f396b24db166b36cb58d42ed7b4b82fef85effb1e4782b85b619a31
|
4
|
+
data.tar.gz: 8ff5a30a9cdd8bb2fd89372a239da566a35b4617effd71a35fe73f3bccb436cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 293918253138add8bf8cdac4478a149b70f937fefb30aeb48883ea0e0cc5c85141a1e1210045a91a42780ab625e81c27181253fc234fa7863823e802987a6fbe
|
7
|
+
data.tar.gz: c939145b8d54205bcafb938791a6ab7f837895c8ddd42a80d20a4e963aef843228f2ec87b293c53b7d8578870e118ba7576c69251506e513c4fdb1b472a75bf0
|
@@ -13,6 +13,7 @@ class Glib::JsonUi::ActionBuilder
|
|
13
13
|
bool :persistent
|
14
14
|
hash :overlay, required: [:closeOnFocus]
|
15
15
|
singleton_array :styleClass, :styleClasses
|
16
|
+
bool :updateExisting
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -26,7 +27,6 @@ class Glib::JsonUi::ActionBuilder
|
|
26
27
|
include PopoverAttributes
|
27
28
|
|
28
29
|
string :url
|
29
|
-
bool :updateExisting
|
30
30
|
end
|
31
31
|
|
32
32
|
class Close < Action
|
@@ -324,6 +324,7 @@ class Glib::JsonUi::ViewBuilder
|
|
324
324
|
|
325
325
|
class Radio < View
|
326
326
|
string :label
|
327
|
+
string :subtitle
|
327
328
|
string :value
|
328
329
|
action :onClick
|
329
330
|
string :offIcon
|
@@ -334,6 +335,7 @@ class Glib::JsonUi::ViewBuilder
|
|
334
335
|
views :childViews
|
335
336
|
end
|
336
337
|
|
338
|
+
# Deprecated
|
337
339
|
class File < Text
|
338
340
|
# file_rules = { fileType: 'image/*', maxFileSize: 5000 }
|
339
341
|
# file_rules = { fileType: 'video/*', maxFileSize: 50000 }
|
@@ -379,19 +381,17 @@ class Glib::JsonUi::ViewBuilder
|
|
379
381
|
end
|
380
382
|
end
|
381
383
|
|
384
|
+
# deprecated
|
382
385
|
class MultiUpload < AbstractField
|
383
386
|
include Glib::JsonUi::Default
|
384
387
|
include Glib::JsonUi::Upload
|
388
|
+
include Glib::JsonUi::FileUploadErrorHandler
|
385
389
|
|
386
390
|
array :files
|
387
391
|
string :uploadTitle
|
388
392
|
action :onFinishUpload
|
389
393
|
string :url # http post end point if you don't want to use onFinishUpload
|
390
394
|
|
391
|
-
def accepts(value)
|
392
|
-
@accepts = value
|
393
|
-
end
|
394
|
-
|
395
395
|
def files(values)
|
396
396
|
@files = values
|
397
397
|
end
|
@@ -402,6 +402,7 @@ class Glib::JsonUi::ViewBuilder
|
|
402
402
|
|
403
403
|
def created
|
404
404
|
super
|
405
|
+
file_upload_error_handler_on_create
|
405
406
|
|
406
407
|
@placeholder ||= I18n.t('glib.multi_upload.placeholder', default: nil)
|
407
408
|
@hint ||= I18n.t('glib.multi_upload.hint', default: nil)
|
@@ -420,8 +421,6 @@ class Glib::JsonUi::ViewBuilder
|
|
420
421
|
json.placeholder @placeholder if @placeholder
|
421
422
|
json.hint @hint if @hint
|
422
423
|
|
423
|
-
json.accepts default_accepts(@accepts)
|
424
|
-
|
425
424
|
if @prop && context
|
426
425
|
# association = form.nested_associations.last
|
427
426
|
# context = association || form
|
@@ -433,6 +432,52 @@ class Glib::JsonUi::ViewBuilder
|
|
433
432
|
end
|
434
433
|
end
|
435
434
|
|
435
|
+
class Upload < AbstractField
|
436
|
+
include Glib::JsonUi::Upload
|
437
|
+
include Glib::JsonUi::FileUploadErrorHandler
|
438
|
+
|
439
|
+
action :onFinishUpload
|
440
|
+
bool :multiple
|
441
|
+
hash :placeholderView, required: [:type, :width, :height], optional: [:url]
|
442
|
+
hash :inputView, optional: [:multiple, :files, :variant]
|
443
|
+
|
444
|
+
def multiProgressView(values)
|
445
|
+
@multi_progress = values
|
446
|
+
end
|
447
|
+
|
448
|
+
def created
|
449
|
+
super
|
450
|
+
file_upload_error_handler_on_create
|
451
|
+
|
452
|
+
@placeholder ||= I18n.t('glib.multi_upload.placeholder', default: nil)
|
453
|
+
@hint ||= I18n.t('glib.multi_upload.hint', default: nil)
|
454
|
+
|
455
|
+
if @prop && context && @multi_progress
|
456
|
+
@multi_progress['files'] ||= context.field_value(@prop, collect_ids: false).to_a.map { |file| { name: file.blob&.filename, signed_id: file.signed_id, url: url_for(file) } }
|
457
|
+
end
|
458
|
+
|
459
|
+
if @multi_progress
|
460
|
+
@multi_progress['responseMessages'] ||= {}
|
461
|
+
['200', '403', '401', 'else'].each do |status|
|
462
|
+
key = "glib.multi_upload.responseMessages.#{status}"
|
463
|
+
@multi_progress['responseMessages'][status] = I18n.t(key) if I18n.exists?(key)
|
464
|
+
end
|
465
|
+
|
466
|
+
json.responseMessages (@multi_progress['responseMessages'] || {}).reverse_merge({
|
467
|
+
'200' => 'Completed',
|
468
|
+
'403' => 'Forbidden',
|
469
|
+
'401' => 'Session expired',
|
470
|
+
'else' => 'Failed'
|
471
|
+
})
|
472
|
+
|
473
|
+
json.placeholder @placeholder if @placeholder
|
474
|
+
json.hint @hint if @hint
|
475
|
+
|
476
|
+
json.multiProgressView @multi_progress
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
436
481
|
class Sign < AbstractField
|
437
482
|
string :directUploadUrl
|
438
483
|
required :directUploadUrl
|
@@ -15,6 +15,79 @@ module Glib
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
module FileUploadErrorHandler
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
def accepts(options)
|
23
|
+
@accepts = options.with_indifferent_access
|
24
|
+
end
|
25
|
+
|
26
|
+
def onMaxFileLengthError(handler)
|
27
|
+
@onMaxFileLengthError = handler
|
28
|
+
end
|
29
|
+
|
30
|
+
def onMaxFileSizeError(handler)
|
31
|
+
@onMaxFileSizeError = handler
|
32
|
+
end
|
33
|
+
|
34
|
+
def onFileTypeError(handler)
|
35
|
+
@onFileTypeError = handler
|
36
|
+
end
|
37
|
+
|
38
|
+
def file_upload_error_handler_on_create
|
39
|
+
@accepts ||= {}
|
40
|
+
if @onMaxFileSizeError.blank?
|
41
|
+
@onMaxFileSizeError = ->(action) do
|
42
|
+
action.snackbars_alert \
|
43
|
+
message: I18n.t(
|
44
|
+
'glib.fields.upload.on_max_file_size_error',
|
45
|
+
max: @accepts['maxFileSize'],
|
46
|
+
default: "Your upload failed because your file is too large. Please select a file that is smaller than the maximum allowed size of #{@accepts['maxFileSize']} KB and try again."),
|
47
|
+
styleClass: 'error'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if @onMaxFileLengthError.blank?
|
52
|
+
@onMaxFileLengthError = ->(action) do
|
53
|
+
action.snackbars_alert \
|
54
|
+
message: I18n.t(
|
55
|
+
'glib.fields.upload.on_max_file_length_error',
|
56
|
+
max: @accepts['maxFileLength'],
|
57
|
+
default: "You can't upload more than the maximum number of files allowed. The limit is #{@accepts['maxFileLength']} files."),
|
58
|
+
styleClass: 'error'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if @onMaxFileLengthError.blank?
|
63
|
+
@onMaxFileLengthError = ->(action) do
|
64
|
+
action.snackbars_alert \
|
65
|
+
message: I18n.t(
|
66
|
+
'glib.fields.upload.on_max_file_length_error',
|
67
|
+
max: @accepts['maxFileLength'],
|
68
|
+
default: "You can't upload more than the maximum number of files allowed. The limit is #{@accepts['maxFileLength']} files."),
|
69
|
+
styleClass: 'error'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if @onFileTypeError.blank?
|
74
|
+
@onFileTypeError = ->(action) do
|
75
|
+
action.snackbars_alert \
|
76
|
+
message: I18n.t(
|
77
|
+
'glib.fields.upload.on_file_type_error',
|
78
|
+
default: 'The file you uploaded is not a supported file type.'),
|
79
|
+
styleClass: 'error'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
json.accepts @accepts
|
84
|
+
json.set!('onMaxFileSizeError') { @onMaxFileSizeError.call(page.action_builder) }
|
85
|
+
json.set!('onMaxFileLengthError') { @onMaxFileLengthError.call(page.action_builder) }
|
86
|
+
json.set!('onFileTypeError') { @onFileTypeError.call(page.action_builder) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
18
91
|
class ViewBuilder < AbstractBuilder
|
19
92
|
def initialize(json, page, multiple)
|
20
93
|
super(json, page)
|
@@ -58,6 +58,17 @@ if local_assigns[:top_nav] || json_ui_app_is_web?
|
|
58
58
|
menu.divider
|
59
59
|
menu.label text: 'Misc Menu'
|
60
60
|
|
61
|
+
menu.button icon: 'list', text: 'Parent', expanded: true, onClick: ->(action) do
|
62
|
+
end, childButtons: ->(parent) do
|
63
|
+
parent.button text: 'Child 1', onClick: ->(action) do
|
64
|
+
action.windows_open url: json_ui_garage_url(path: 'lists/index')
|
65
|
+
end
|
66
|
+
parent.button text: 'Child 2', onClick: ->(action) do
|
67
|
+
action.windows_open url: json_ui_garage_url(path: 'forms/index')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
61
72
|
menu.button icon: 'notifications', text: 'Notifications', onClick: ->(action) do
|
62
73
|
action.windows_open url: json_ui_garage_url(path: 'notifications/index')
|
63
74
|
end
|
@@ -16,6 +16,12 @@ section.rows builder: ->(template) do
|
|
16
16
|
action.windows_reload url: json_ui_garage_url(path: 'actions/index', reload_counter: reload_counter + 1)
|
17
17
|
end
|
18
18
|
|
19
|
+
template.thumbnail title: 'windows/reload (onReload)', onClick: ->(action) do
|
20
|
+
action.windows_reload onReload: ->(saction) do
|
21
|
+
saction.snackbars_alert message: 'onReload called'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
19
25
|
template.thumbnail title: "components/replace (counter: #{reload_counter})", onClick: ->(action) do
|
20
26
|
action.http_get url: json_ui_garage_url(path: 'actions/partial_update', reload_counter: reload_counter + 1)
|
21
27
|
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
json.title 'Forms'
|
2
|
+
page = json_ui_page json
|
3
|
+
render "#{@path_prefix}/nav_menu", json: json, page: page
|
4
|
+
|
5
|
+
image = OpenStruct.new(
|
6
|
+
url: 'https://picsum.photos/id/11/100/60',
|
7
|
+
signed_id: 'test',
|
8
|
+
filename: 'upload.png'
|
9
|
+
)
|
10
|
+
|
11
|
+
accepts = {
|
12
|
+
fileType: 'image',
|
13
|
+
maxFileSize: 100,
|
14
|
+
maxFileLength: 2
|
15
|
+
}
|
16
|
+
|
17
|
+
if params[:mode] == 'html'
|
18
|
+
directUploadUrl = nil
|
19
|
+
else
|
20
|
+
directUploadUrl = glib_direct_uploads_url
|
21
|
+
end
|
22
|
+
|
23
|
+
properties = {
|
24
|
+
styleClass: 'pb-2',
|
25
|
+
directUploadUrl: params,
|
26
|
+
accepts: accepts,
|
27
|
+
directUploadUrl: directUploadUrl,
|
28
|
+
value: image&.signed_id
|
29
|
+
}
|
30
|
+
|
31
|
+
# properties[:onMaxFileLengthError] = ->(action) do
|
32
|
+
# action.snackbars_alert message: 'max file length exceeded'
|
33
|
+
# end
|
34
|
+
|
35
|
+
# properties[:onMaxFileSizeError] = ->(action) do
|
36
|
+
# action.snackbars_alert message: 'max file size exceeded'
|
37
|
+
# end
|
38
|
+
|
39
|
+
# properties[:onFileTypeError] = ->(action) do
|
40
|
+
# action.snackbars_alert message: 'file type invalid'
|
41
|
+
# end
|
42
|
+
|
43
|
+
properties[:onFinishUpload] = ->(action) do
|
44
|
+
action.snackbars_alert message: 'Get the signed ids!'
|
45
|
+
end
|
46
|
+
|
47
|
+
page.form \
|
48
|
+
url: json_ui_garage_url(path: 'forms/generic_post'),
|
49
|
+
method: 'post',
|
50
|
+
padding: { top: 12, left: 20, right: 20, bottom: 12 },
|
51
|
+
childViews: ->(form) do
|
52
|
+
form.panels_flow styleClass: 'items-center justify-center gap-2 pb-4', childViews: ->(flow) do
|
53
|
+
flow.label text: "MODE: #{params[:mode] || 'directUpload'}"
|
54
|
+
change = params[:mode] == 'html' ? 'directUpload' : 'html'
|
55
|
+
flow.button text: 'Change', onClick: ->(action) { action.windows_open url: json_ui_garage_current_url({ mode: change }) }
|
56
|
+
end
|
57
|
+
|
58
|
+
form.h2 text: 'Field Upload', styleClass: 'pb-4'
|
59
|
+
form.label text: 'placeholder image', styleClass: 'pb-1'
|
60
|
+
form.panels_flow styleClass: 'align-center', xs: { gap: { all: 4 } }, childViews: ->(flow) do
|
61
|
+
form.fields_upload properties.merge(
|
62
|
+
name: 'user[file_placeholderView]',
|
63
|
+
id: 'pv1',
|
64
|
+
placeholderView: { type: 'image', url: image&.url, width: 144, height: 144 }
|
65
|
+
)
|
66
|
+
|
67
|
+
flow.button text: 'trigger', onClick: ->(action) do
|
68
|
+
action.components_invoke targetId: 'pv1', name: 'trigger'
|
69
|
+
end
|
70
|
+
flow.button text: 'reset', onClick: ->(action) do
|
71
|
+
action.components_invoke targetId: 'pv1', name: 'reset'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
form.label text: 'placeholder avatar', styleClass: 'pb-1'
|
76
|
+
form.panels_flow styleClass: 'align-center', xs: { gap: { all: 4 } }, childViews: ->(flow) do
|
77
|
+
flow.fields_upload \
|
78
|
+
properties.merge(
|
79
|
+
name: 'user[file_placeholderView2]',
|
80
|
+
id: 'pv2',
|
81
|
+
placeholderView: { type: 'avatar', url: image&.url, width: 64, height: 64 }
|
82
|
+
)
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
form.label text: 'file input', styleClass: 'pb-1'
|
87
|
+
form.fields_upload \
|
88
|
+
properties.merge(
|
89
|
+
name: 'user[file_input1]',
|
90
|
+
id: 'fi1',
|
91
|
+
label: 'Upload file',
|
92
|
+
width: 300,
|
93
|
+
label: 'Choose file',
|
94
|
+
inputView: { variant: 'outlined' },
|
95
|
+
multiple: false
|
96
|
+
)
|
97
|
+
|
98
|
+
|
99
|
+
form.label text: 'multiprogress', styleClass: 'pb-1'
|
100
|
+
form.fields_upload \
|
101
|
+
properties.merge(
|
102
|
+
name: 'user[file_multiprogress1][]',
|
103
|
+
id: 'mp1',
|
104
|
+
width: 300,
|
105
|
+
label: 'Upload file',
|
106
|
+
multiple: true,
|
107
|
+
multiProgressView: { files: [] }
|
108
|
+
)
|
109
|
+
|
110
|
+
|
111
|
+
form.label text: 'Button file upload', styleClass: 'pb-1'
|
112
|
+
form.button text: 'click me to select file', onClick: ->(action) do
|
113
|
+
action.components_invoke targetId: 'btn1', name: 'trigger'
|
114
|
+
end
|
115
|
+
form.fields_upload \
|
116
|
+
properties.merge(
|
117
|
+
name: 'user[file_btn1][]',
|
118
|
+
id: 'btn1',
|
119
|
+
width: 300,
|
120
|
+
label: 'Upload file',
|
121
|
+
multiple: true,
|
122
|
+
inputView: { files: [] },
|
123
|
+
styleClass: 'pb-4 d-none'
|
124
|
+
)
|
125
|
+
|
126
|
+
form.fields_submit text: 'submit'
|
127
|
+
|
128
|
+
end
|
@@ -72,6 +72,9 @@ page.list sections: [
|
|
72
72
|
template.thumbnail title: 'File Upload', onClick: ->(action) do
|
73
73
|
action.windows_open url: json_ui_garage_url(path: 'forms/file_upload')
|
74
74
|
end
|
75
|
+
template.thumbnail title: 'File Upload (NEW)', onClick: ->(action) do
|
76
|
+
action.windows_open url: json_ui_garage_url(path: 'forms/file_upload_new')
|
77
|
+
end
|
75
78
|
template.thumbnail title: 'Floating Submit', onClick: ->(action) do
|
76
79
|
action.windows_open url: json_ui_garage_url(path: 'forms/floating_submit')
|
77
80
|
end
|
@@ -65,6 +65,7 @@ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
65
65
|
key: 'menu2',
|
66
66
|
placement: 'right-start',
|
67
67
|
width: 200,
|
68
|
+
updateExisting: true,
|
68
69
|
content: ->(dialog) do
|
69
70
|
dialog.body styleClass: 'popover-menu', padding: glib_json_padding_body, childViews: ->(res) do
|
70
71
|
res.label text: 'Item 1', styleClass: 'popover-menu-item', onClick: ->(saction) do
|
@@ -95,7 +96,8 @@ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
95
96
|
action.popovers_open \
|
96
97
|
url: json_ui_garage_url(path: 'views/popovers_open', key: key),
|
97
98
|
styleClass: 'popover-container',
|
98
|
-
key: key
|
99
|
+
key: key,
|
100
|
+
updateExisting: true
|
99
101
|
end
|
100
102
|
|
101
103
|
scroll.spacer height: 10
|
@@ -1,7 +1,10 @@
|
|
1
|
+
sleep 1
|
2
|
+
|
1
3
|
page = json_ui_page json
|
2
4
|
|
3
5
|
page.body childViews: ->(body) do
|
4
|
-
body.
|
6
|
+
body.panels_form styleClass: 'popover-menu', childViews: ->(sres) do
|
7
|
+
sres.fields_select options: ['A', 'B'].map { |v| { text: v, value: v } }, name: 'user[select]', label: 'Select', width: 'matchParent'
|
5
8
|
sres.p text: "Current time: #{DateTime.current}", styleClass: 'pb-2'
|
6
9
|
sres.button text: 'Update', onClick: ->(action) do
|
7
10
|
action.popovers_open url: json_ui_garage_url(path: 'views/popovers_open', key: params[:key]), key: params[:key], updateExisting: true
|
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: 4.36.
|
4
|
+
version: 4.36.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ''
|
@@ -268,6 +268,7 @@ files:
|
|
268
268
|
- app/views/json_ui/garage/forms/dynamic_select.json.jbuilder
|
269
269
|
- app/views/json_ui/garage/forms/dynamic_select_data.json.jbuilder
|
270
270
|
- app/views/json_ui/garage/forms/file_upload.json.jbuilder
|
271
|
+
- app/views/json_ui/garage/forms/file_upload_new.json.jbuilder
|
271
272
|
- app/views/json_ui/garage/forms/floating_submit.json.jbuilder
|
272
273
|
- app/views/json_ui/garage/forms/full_page_form.json.jbuilder
|
273
274
|
- app/views/json_ui/garage/forms/full_page_form_dialog.json.jbuilder
|