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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8defef028088f5b2924990e19bbc9e3f046bf7ca1adcb9ba2ea12b8b91821b0
4
- data.tar.gz: e8b48a98fea6164325bde300b81523f18343647c3e67293bbf6a7dc99f1a7d18
3
+ metadata.gz: a129200d9f396b24db166b36cb58d42ed7b4b82fef85effb1e4782b85b619a31
4
+ data.tar.gz: 8ff5a30a9cdd8bb2fd89372a239da566a35b4617effd71a35fe73f3bccb436cf
5
5
  SHA512:
6
- metadata.gz: 197045903a729f2a05cab3e0466d6ea0f30513a1cb8fc555e2a3233537463dd6b9261afe05a8e8b9ce91eab943aa8f9fd801c2492e6413e9350ea86432c400e3
7
- data.tar.gz: d64dd6940a50e85149fe84de93f37c4409fc8db35a25d3f7ca94516e1f92924143c75dc866c0e1b49306aa522b437af9aac21be25d862ee1be9a7bae2938a4d3
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
@@ -20,7 +20,7 @@ module Glib
20
20
  icon :icon
21
21
  action :onClick
22
22
  bool :disabled
23
- # hash :tooltip
23
+ bool :expanded
24
24
  singleton_array :styleClass, :styleClasses
25
25
 
26
26
  def childButtons(block)
@@ -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
@@ -48,7 +48,7 @@ page.form options.merge(childViews: ->(form) do
48
48
  width: 360,
49
49
  accepts: {
50
50
  fileType: 'image',
51
- maxFileSize: 10,
51
+ maxFileSize: 100,
52
52
  maxFileLength: 2,
53
53
  maxFileLengthErrorText: {
54
54
  body: 'try with a smaller number of files',
@@ -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.panels_responsive styleClass: 'popover-menu', childViews: ->(sres) do
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.7
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