glib-web 6.4.1 → 6.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0c733a1c0dbc779a2bd72cbcd304074238f10a2efde2d74ee4c75f50bf861d4
4
- data.tar.gz: 0ea1e58d18cea237c50fccaafb56a165abaa104caecd2011cbbeb7e5bdf7a97d
3
+ metadata.gz: 530b28412dbe8757ccb9cf80e746d3d9891f8d403ee013a2c505a4bc6681b8ac
4
+ data.tar.gz: 6754295e8de270915d25603a432197b7e50d372d6c4a227f6bd581b0ede0cb65
5
5
  SHA512:
6
- metadata.gz: ff566900716099396b7817beca6b934ad2d18f8338c2dfa6743c9b3ed851927becc596d75d5bd71c9fc90ff3e9bbba572f665228755cc4cac60d6389b50103ff
7
- data.tar.gz: 93e89c3f04019cf9517412416b4c8bb917b3171677f67a3214d8e12d705bddafb9f1744522452b93a1fa77d2278ed14499ee41d9097fc4a482db6b6ec40ac186
6
+ metadata.gz: 54a71bbd3cfb00f390dd5908e356db7bcb5f4576e66c3bef6be29e05841bd7a7c4e014344cab7784c9e0dec549ed4e83b46e77b214b5545d55b31e70ac26dd18
7
+ data.tar.gz: 47975dd0401a0b59cf404aa8bcaba12b9560bd0760fe4aa428c3516d10555749b21eea7ae71fdab38cb7516929cd0cde518099f9b4eeae35ab50eeccdcfb40d5
@@ -364,7 +364,7 @@ module Glib::Json::Libs
364
364
  # format.json do
365
365
  # render json: {
366
366
  # onResponse: {
367
- # action: 'windows/open-v1',
367
+ # action: 'windows/open',
368
368
  # url: url
369
369
  # }
370
370
  # }
@@ -83,7 +83,7 @@ module Glib::Json::Traversal
83
83
  if views.is_a? Array
84
84
  views.each do |view|
85
85
  case view['view']
86
- when 'panels/form-v1'
86
+ when 'panels/form'
87
87
  @forms << view
88
88
  traverse_single view, block
89
89
  @forms.pop
@@ -28,21 +28,6 @@ module Glib
28
28
  end
29
29
  end
30
30
 
31
- # TODO: Consider removing this in favour of non 'v1' suffix
32
- def add_singleton_element_v1(type, name, *args)
33
- name_components = name.to_s.split('_')
34
- json.set! type, "#{name_components.join('/')}-v1" if type
35
- args = [yield] if block_given?
36
- "#{self.class.name}::#{name_components.map { |str| capitalize_first_letter_and_leave_others_alone(str) }.join('::')}".constantize.new(json, @page).props(*args)
37
- end
38
-
39
- # TODO: Consider removing this in favour of non 'v1' suffix
40
- def add_element_to_array_v1(type, name, *args)
41
- json.child! do
42
- add_singleton_element_v1 type, name, *args
43
- end
44
- end
45
-
46
31
  end
47
32
 
48
33
  class JsonUiElement
@@ -37,6 +37,9 @@ class Glib::JsonUi::ActionBuilder
37
37
  end
38
38
  end
39
39
 
40
+ # Deprecated: use `logics_set` instead. `logics_set` is a superset of this
41
+ # action (same `targetId`/`data`/`onSet`/`skipOnChange`, plus
42
+ # `conditionalData`, `targetIds`, `variables` and `cacheData`).
40
43
  class Set < Action
41
44
  string :targetId
42
45
  hash :data
@@ -1,5 +1,8 @@
1
1
  class Glib::JsonUi::ActionBuilder
2
2
  module Logics
3
+ # The canonical setter action. Prefer this over the deprecated
4
+ # `components_set`: it supports plain static `data` as well as
5
+ # `conditionalData` (JsonLogic), `targetIds`, `variables` and `cacheData`.
3
6
  class Set < Action
4
7
  string :targetId
5
8
  array :targetIds
@@ -36,7 +36,7 @@ module Glib
36
36
 
37
37
  def method_missing(m, *args)
38
38
  if @multiple
39
- add_element_to_array_v1 'action', m, *args
39
+ add_element_to_array 'action', m, *args
40
40
  else
41
41
  if !Rails.env.production? && @singleton_action_set
42
42
  raise "Multiple actions called on a singleton ActionBuilder. " \
@@ -46,7 +46,7 @@ module Glib
46
46
  end
47
47
  @singleton_action_set = true
48
48
  @singleton_action_name = m
49
- add_singleton_element_v1 'action', m, *args
49
+ add_singleton_element 'action', m, *args
50
50
  end
51
51
  end
52
52
 
@@ -2,7 +2,7 @@ module Glib
2
2
  module JsonUi
3
3
  class MenuBuilder < AbstractBuilder
4
4
  def method_missing(m, *args)
5
- add_element_to_array_v1 nil, m, *args
5
+ add_element_to_array nil, m, *args
6
6
  end
7
7
 
8
8
  class MenuItem < JsonUiElement
@@ -496,6 +496,20 @@ class Glib::JsonUi::ViewBuilder
496
496
  class BulkEdit2 < View
497
497
  hash :import, required: [:submitUrl, :paramName]
498
498
 
499
+ # Override
500
+ def created
501
+ # bulkEdit2 is a form PEER, not a form child: it answers the same
502
+ # forms_submit action a form does (forms/directSubmit) and submits its
503
+ # rows itself to `import.submitUrl`. Inside a form, its repeated
504
+ # per-row input names would collide with the form's FormData scans
505
+ # (duplicate-name warnings, dirty-baseline pollution) while adding
506
+ # nothing to the form's submission -- so, like a nested form, reject
507
+ # the arrangement at render time.
508
+ if page.current_form
509
+ raise 'panels_bulkEdit2 is not allowed inside a form; place it as a sibling and target it with forms_submit targetId'
510
+ end
511
+ end
512
+
499
513
  # Maximum number of data rows an uploaded file may contain; files with
500
514
  # more rows are rejected with an error dialog. No limit when unset.
501
515
  int :maxRows
@@ -533,6 +547,65 @@ class Glib::JsonUi::ViewBuilder
533
547
 
534
548
  end
535
549
 
550
+ # The Surfguard members-import table: a fork of bulkEdit2's builder for
551
+ # glib-web-npm's bulkEditSg component (same skeleton — form-peer
552
+ # submission, per-row POSTs, viewCells/viewHeaders — plus the Surfguard
553
+ # parse inputs). Deliberately SG-specific; consolidate with BulkEdit2 when
554
+ # a second consumer proves which props generalize.
555
+ class BulkEditSg < View
556
+ hash :import, required: [:submitUrl, :paramName]
557
+
558
+ # Override
559
+ def created
560
+ # Same form-peer rule as bulkEdit2 (see its comment).
561
+ if page.current_form
562
+ raise 'panels_bulkEditSg is not allowed inside a form; place it as a sibling and target it with forms_submit targetId'
563
+ end
564
+ end
565
+
566
+ # Maximum number of data rows an uploaded file may contain; files with
567
+ # more rows are rejected with an error dialog. No limit when unset.
568
+ int :maxRows
569
+
570
+ array :viewHeaders
571
+
572
+ # string :paramNameForFormData
573
+ string :paramNameForRowId
574
+ action :onCellChange
575
+ action :onRowsLoad
576
+ action :onRowsSelect
577
+ action :onRowsSucceed
578
+ # Fires when non-importable rows drain out of the table on save (they
579
+ # never POST), so the page can keep its Loaded/Uploaded/Skipped
580
+ # arithmetic honest.
581
+ action :onRowsSkip
582
+ action :onSubmitStart
583
+ action :onSubmitEnd
584
+
585
+ # Surfguard file shape: CSV header => form field. The parser follows
586
+ # this map, so a header-spelling fix is a one-line server change.
587
+ hash :headerMap
588
+ array :requiredHeaders
589
+ string :statusFilter
590
+
591
+ def viewCells(values)
592
+ json.set! 'viewCells' do
593
+ values.each do |value|
594
+ value.call(page.view_builder)
595
+ end
596
+ end
597
+ end
598
+
599
+ def dataRows(value)
600
+ json.dataRows value
601
+ end
602
+
603
+ def viewRows(value)
604
+ json.viewRows value
605
+ end
606
+
607
+ end
608
+
536
609
  # deprecated
537
610
  class BulkEdit < View
538
611
  hash :nextPage
@@ -89,9 +89,9 @@ module Glib
89
89
 
90
90
  def add_view(name, *args)
91
91
  if @multiple
92
- add_element_to_array_v1 'view', name, *args
92
+ add_element_to_array 'view', name, *args
93
93
  else
94
- add_singleton_element_v1 'view', name, *args
94
+ add_singleton_element 'view', name, *args
95
95
  end
96
96
  end
97
97
 
@@ -115,7 +115,11 @@ module Glib
115
115
  include Builder::MouseEvents
116
116
 
117
117
  string :id
118
- string :key
118
+ string :key # Deprecated: use `reuseKey` instead.
119
+ # Controls whether the frontend reuses the underlying DOM/component when a
120
+ # view is re-rendered. Maps to Vue's `:key`: keep it stable to allow reuse,
121
+ # or change it to force a fresh render. Supersedes the deprecated `key`.
122
+ string :reuseKey
119
123
  length :width
120
124
  length :height
121
125
  color :backgroundColor
@@ -15,7 +15,7 @@ page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', pad
15
15
  # form.fields_richText name: 'user[bio]', width: 'matchParent', label: 'Content', images: images, value: '<p>Test {{image1}}</p>'
16
16
 
17
17
  json.child! do
18
- json.view 'fields/newRichText-v1'
18
+ json.view 'fields/newRichText'
19
19
  json.width 'matchParent'
20
20
  json.label 'Content'
21
21
  json.name 'user[bio]'
@@ -62,7 +62,7 @@ page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', pad
62
62
  end
63
63
 
64
64
  # json.child! do
65
- # json.view 'fields/richText-v1'
65
+ # json.view 'fields/richText'
66
66
  # json.width 'matchParent'
67
67
  # json.label 'Content'
68
68
  # json.name 'user[bio]'
@@ -0,0 +1,84 @@
1
+ json.title 'Test Page (Duplicate Names)'
2
+
3
+ page = json_ui_page json
4
+
5
+ render 'json_ui/garage/test_page/header', json: json, page: page
6
+
7
+ # Contract: inputs sharing a name are only a problem when an action logic
8
+ # READS the shared name -- getFormData then yields an ambiguous (array)
9
+ # value. Repeated names that nothing reads are a legitimate pattern (e.g. a
10
+ # multi-file upload renders one hidden input per signed file, all sharing the
11
+ # field name), so they must never warn -- not at mount, not on input events,
12
+ # and not when a logic reads OTHER fields.
13
+ page.body(
14
+ childViews: ->(body) do
15
+ body.panels_responsive(
16
+ padding: glib_json_padding_body,
17
+ childViews: ->(res) do
18
+ res.h2 text: 'Duplicate field names in a form'
19
+ res.spacer height: 8
20
+ res.panels_form(
21
+ url: json_ui_garage_url(path: 'forms/generic_post'),
22
+ method: 'post',
23
+ childViews: ->(form) do
24
+ # Never read by any logic -- mirrors the multi-file upload shape.
25
+ form.fields_text width: 'matchParent', name: 'attachment_meta', label: 'Attachment meta 1', value: 'a'
26
+ form.fields_text width: 'matchParent', name: 'attachment_meta', label: 'Attachment meta 2', value: 'b'
27
+ # Read by the button below -- the ambiguous read must warn.
28
+ form.fields_text width: 'matchParent', name: 'user[level]', label: 'Level 1', value: 'one'
29
+ form.fields_text width: 'matchParent', name: 'user[level]', label: 'Level 2', value: 'two'
30
+ # A multi-value select renders one hidden input per selected
31
+ # value, all sharing the (bare, explicit) field name -- an
32
+ # INTENTIONAL duplicate that stays silent even when read (setEq
33
+ # exists precisely to compare such array values).
34
+ form.fields_select(
35
+ width: 'matchParent',
36
+ name: 'tags',
37
+ label: 'Tags',
38
+ multiple: true,
39
+ options: [
40
+ { text: 'Tag A', value: 'a' },
41
+ { text: 'Tag B', value: 'b' }
42
+ ],
43
+ value: ['a', 'b']
44
+ )
45
+ end
46
+ )
47
+ res.spacer height: 8
48
+ res.button(
49
+ text: 'Check level',
50
+ onClick: ->(action) do
51
+ action.logics_run(
52
+ condition: { '==': [{ 'var': 'user[level]' }, 'one'] },
53
+ onTrue: ->(subaction) do
54
+ subaction.logics_set targetId: 'dup_status', data: { text: 'TRUE' }
55
+ end,
56
+ onFalse: ->(subaction) do
57
+ subaction.logics_set targetId: 'dup_status', data: { text: 'FALSE' }
58
+ end
59
+ )
60
+ end
61
+ )
62
+ res.spacer height: 8
63
+ res.label id: 'dup_status', text: 'PENDING'
64
+ res.spacer height: 8
65
+ res.button(
66
+ text: 'Check tags',
67
+ onClick: ->(action) do
68
+ action.logics_run(
69
+ condition: { 'setEq': [{ 'var': 'tags' }, %w[a b]] },
70
+ onTrue: ->(subaction) do
71
+ subaction.logics_set targetId: 'tags_status', data: { text: 'MATCH' }
72
+ end,
73
+ onFalse: ->(subaction) do
74
+ subaction.logics_set targetId: 'tags_status', data: { text: 'NO MATCH' }
75
+ end
76
+ )
77
+ end
78
+ )
79
+ res.spacer height: 8
80
+ res.label id: 'tags_status', text: 'PENDING'
81
+ end
82
+ )
83
+ end
84
+ )
@@ -0,0 +1,123 @@
1
+ json.title 'Test Page (Inputs Outside Form)'
2
+
3
+ page = json_ui_page json
4
+
5
+ render 'json_ui/garage/test_page/header', json: json, page: page
6
+
7
+ # Contract: inputs outside a glib form mount SILENTLY, named or not. Whether
8
+ # an outside-form input is a mistake depends on intent -- a named select that
9
+ # only navigates via onChange is legitimate; a field an action logic expects
10
+ # to read is a bug -- and intent is invisible at mount. So the warning fires
11
+ # at READ time instead: when an action logic (logics/run, logics/set
12
+ # conditions, fields/getValues) reads a name whose only input lives outside a
13
+ # glib form, i.e. exactly when the silent-read bug manifests.
14
+ page.body(
15
+ childViews: ->(body) do
16
+ body.panels_responsive(
17
+ padding: glib_json_padding_body,
18
+ childViews: ->(res) do
19
+ res.h2 text: 'Inputs outside a glib form'
20
+ res.label text: 'Every input below mounts silently. Warnings fire only when one of the ' \
21
+ 'buttons makes an action logic read a field that no glib form can provide.'
22
+ res.spacer height: 12
23
+ res.hr width: 'matchParent'
24
+ res.spacer height: 12
25
+
26
+ res.h2 text: 'Named input (silent at mount, warns when read)'
27
+ res.spacer height: 8
28
+ res.fields_text name: 'orphan_named', width: 'matchParent'
29
+
30
+ res.spacer height: 16
31
+ res.hr width: 'matchParent'
32
+ res.spacer height: 16
33
+
34
+ # A navigation-style control: named, outside any form, consumed only
35
+ # through its own onChange -- never through form data. Must stay
36
+ # silent forever.
37
+ res.h2 text: 'Nav select (onChange only, never warns)'
38
+ res.spacer height: 8
39
+ res.fields_select(
40
+ id: 'nav_year',
41
+ name: 'nav_year',
42
+ label: 'Year',
43
+ width: 300,
44
+ options: [
45
+ { text: '2025', value: '2025' },
46
+ { text: '2026', value: '2026' }
47
+ ],
48
+ value: '2026',
49
+ onChange: ->(action) do
50
+ action.logics_set targetId: 'nav_status', data: { text: 'NAVIGATED' }
51
+ end
52
+ )
53
+ res.spacer height: 8
54
+ res.label id: 'nav_status', text: 'IDLE'
55
+
56
+ res.spacer height: 16
57
+ res.hr width: 'matchParent'
58
+ res.spacer height: 16
59
+
60
+ res.h2 text: 'Nameless readOnly display (silent)'
61
+ res.spacer height: 8
62
+ res.fields_text value: 'https://example.com/copy-this-link', readOnly: true, width: 'matchParent'
63
+
64
+ res.spacer height: 16
65
+ res.hr width: 'matchParent'
66
+ res.spacer height: 16
67
+
68
+ res.h2 text: 'Action logics reading the orphan (warn at read time)'
69
+ res.spacer height: 8
70
+ res.panels_flow(
71
+ innerPadding: { bottom: 0 },
72
+ width: 'matchParent',
73
+ childViews: ->(flow) do
74
+ flow.button(
75
+ text: 'Read orphan (condition)',
76
+ onClick: ->(action) do
77
+ action.logics_run(
78
+ condition: { '==': [{ 'var': 'orphan_named' }, 'never'] },
79
+ onTrue: ->(subaction) do
80
+ subaction.logics_set targetId: 'orphan_condition_status', data: { text: 'TRUE' }
81
+ end,
82
+ onFalse: ->(subaction) do
83
+ subaction.logics_set targetId: 'orphan_condition_status', data: { text: 'FALSE' }
84
+ end
85
+ )
86
+ end
87
+ )
88
+ flow.spacer width: 8
89
+ flow.button(
90
+ text: 'Read orphan (set)',
91
+ onClick: ->(action) do
92
+ action.logics_set(
93
+ targetId: 'orphan_set_target',
94
+ conditionalData: {
95
+ 'text' => { '??' => [{ 'var' => 'orphan_named' }, 'SET MISSING'] }
96
+ }
97
+ )
98
+ end
99
+ )
100
+ flow.spacer width: 8
101
+ flow.button(
102
+ text: 'Read orphan (getValues)',
103
+ onClick: ->(action) do
104
+ action.fields_getValues(
105
+ fieldNames: { 'orphan_named' => nil },
106
+ onGet: ->(subaction) do
107
+ subaction.logics_set targetId: 'orphan_get_status', data: { text: 'VALUES READ' }
108
+ end
109
+ )
110
+ end
111
+ )
112
+ end
113
+ )
114
+ res.spacer height: 8
115
+ res.label id: 'orphan_condition_status', text: 'PENDING'
116
+ res.spacer height: 4
117
+ res.label id: 'orphan_set_target', text: 'SET PENDING'
118
+ res.spacer height: 4
119
+ res.label id: 'orphan_get_status', text: 'GET PENDING'
120
+ end
121
+ )
122
+ end
123
+ )
@@ -16,6 +16,8 @@ page.body childViews: ->(body) do
16
16
  method: 'post',
17
17
  childViews: ->(form) do
18
18
  form.fields_text width: 'matchParent', name: 'user[status]', label: 'First form status', value: 'first'
19
+ # Divergent collision that NO logic reads -- must stay silent.
20
+ form.fields_text width: 'matchParent', name: 'unread[shared]', label: 'First unread shared', value: 'a'
19
21
  end
20
22
  res.spacer height: 8
21
23
  res.panels_form \
@@ -23,6 +25,7 @@ page.body childViews: ->(body) do
23
25
  method: 'post',
24
26
  childViews: ->(form) do
25
27
  form.fields_text width: 'matchParent', name: 'user[status]', label: 'Second form status', value: 'second'
28
+ form.fields_text width: 'matchParent', name: 'unread[shared]', label: 'Second unread shared', value: 'b'
26
29
  end
27
30
 
28
31
  res.spacer height: 8
@@ -16,7 +16,7 @@ module Glib
16
16
  raise "Submit action needs to be inside a form: #{http.router.last_log}" unless form
17
17
 
18
18
  case form['view']
19
- when 'panels/bulkEdit2-v1'
19
+ when 'panels/bulkEdit2'
20
20
  method = 'post'
21
21
  action = "forms/#{method}"
22
22
  url = form['import']['submitUrl']
@@ -57,7 +57,7 @@ module Glib
57
57
  fields << child
58
58
 
59
59
  include_params = case name
60
- when 'fields/check', 'fields/check-v1'
60
+ when 'fields/check'
61
61
  child['checkValue'] == child['value']
62
62
  else
63
63
  true
@@ -67,14 +67,14 @@ module Glib
67
67
  def step(http, args)
68
68
  # TODO: Refactor
69
69
  case args['view']
70
- when 'fields/submit-v1', 'fields/submit'
70
+ when 'fields/submit'
71
71
  @depth += 1
72
72
  # forms = @visitor.forms
73
73
  # JsonCrawler::FormsSubmit.new(http, args, forms.last)
74
74
  JsonCrawler::FormsSubmit.new(http, args)
75
75
  @depth -= 1
76
76
  return
77
- when 'panels/web-v1', 'panels/web'
77
+ when 'panels/web'
78
78
  # A panels/web embeds content by URL in an inline viewer -- a file
79
79
  # preview (PDF/image), an inline HTML preview, etc. There's no onClick
80
80
  # action to catch here, so when the URL is one of our own (same-host)
@@ -83,7 +83,7 @@ module Glib
83
83
  # (it replays each per user and snapshots the response). We only record
84
84
  # (no fetch); external embeds are filtered out by internal_url?.
85
85
  url = args['url']
86
- http_actions.add(['panels/web-v1', url]) if url.present? && internal_url?(url)
86
+ http_actions.add(['panels/web', url]) if url.present? && internal_url?(url)
87
87
  end
88
88
 
89
89
  if args.is_a?(Hash) && args['rel'] != 'nofollow'
@@ -112,10 +112,9 @@ module Glib
112
112
  # @read_only_actions.add([action, params['url']])
113
113
  http_actions.add([action, params['url']])
114
114
  JsonCrawler::NavInitiate.new(http, params, action)
115
- when 'runMultiple-v1', 'runMultiple'
115
+ when 'runMultiple'
116
116
  JsonCrawler::RunMultiple.new(http, params, action)
117
- when 'windows/open-v1', 'dialogs/open-v1', 'windows/reload-v1', 'windows/open',
118
- 'dialogs/open', 'windows/reload', 'windows/openWeb', 'windows/openWeb-v1'
117
+ when 'windows/open', 'dialogs/open', 'windows/reload', 'windows/openWeb'
119
118
  if allowed?(params['url'])
120
119
  # @read_only_actions.add([action, params['url']])
121
120
  http_actions.add([action, params['url']])
@@ -141,24 +140,22 @@ module Glib
141
140
  http_actions.add([action, params['url']]) if internal_url?(params['url'])
142
141
  self.log action, params['url']
143
142
  end
144
- when 'dialogs/show-v1', 'dialogs/show', 'popovers/show-v1', 'popovers/show'
143
+ when 'dialogs/show', 'popovers/show'
145
144
  JsonCrawler::DialogsShow.new(http, params, action)
146
- when 'sheets/select-v1', 'sheets/select'
145
+ when 'sheets/select'
147
146
  JsonCrawler::Menu.new(http, params, action)
148
- when 'http/post-v1', 'http/post'
147
+ when 'http/post'
149
148
  JsonCrawler::ActionHttp.new(:post, http, params, action)
150
- when 'forms/submit-v1', 'forms/submit'
149
+ when 'forms/submit'
151
150
  # forms = @visitor.forms
152
151
  # JsonCrawler::FormsSubmit.new(http, params, forms.last)
153
152
  JsonCrawler::FormsSubmit.new(http, params)
154
- when 'dialogs/alert-v1', 'dialogs/alert'
153
+ when 'dialogs/alert'
155
154
  JsonCrawler::DialogsAlert.new(http, params, action)
156
- when 'dialogs/close-v1', 'dialogs/close', 'popovers/close', 'popovers/close-v1'
155
+ when 'dialogs/close', 'popovers/close'
157
156
  JsonCrawler::DialogsClose.new(http, params, action)
158
157
  else
159
158
  unless [
160
- 'http/delete-v1',
161
- 'dialogs/oauth-v1',
162
159
  'http/delete',
163
160
  'dialogs/oauth'
164
161
  ].include?(
@@ -271,13 +268,13 @@ module Glib
271
268
  params ||= {}
272
269
 
273
270
  case action.to_s.downcase
274
- when 'http/post-v1', 'forms/post'
271
+ when 'http/post', 'forms/post'
275
272
  http.post(url, action, params)
276
- when 'http/patch-v1', 'forms/patch'
273
+ when 'http/patch', 'forms/patch'
277
274
  http.patch(url, action, params)
278
- when 'http/put-v1', 'forms/put'
275
+ when 'http/put', 'forms/put'
279
276
  http.put(url, action, params)
280
- when 'http/delete-v1'
277
+ when 'http/delete'
281
278
  http.delete(url, action, params)
282
279
  else
283
280
  http.get(url, action, params)
@@ -232,7 +232,7 @@ module Glib
232
232
  view.is_a?(Hash) && (
233
233
  view['view']&.start_with?('panels/form') ||
234
234
  view['view']&.start_with?('panels/fullPageForm') ||
235
- view['view'] == 'panels/bulkEdit2-v1' ||
235
+ view['view'] == 'panels/bulkEdit2' ||
236
236
  view['view'] == 'panels/splitForm'
237
237
  )
238
238
  end
@@ -247,7 +247,7 @@ module Glib
247
247
  data_prefixes = data.keys.map { |k| "#{k}[" }
248
248
 
249
249
  __extract_form_fields(form).each do |field|
250
- next unless field[:view] == 'fields/hidden' || field[:view] == 'fields/hidden-v1'
250
+ next unless field[:view] == 'fields/hidden'
251
251
  next if data_prefixes.any? { |prefix| field[:name]&.start_with?(prefix) }
252
252
 
253
253
  params[field[:name]] = field[:value]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glib-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.1
4
+ version: 6.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-12 00:00:00.000000000 Z
11
+ date: 2026-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activestorage
@@ -432,6 +432,7 @@ files:
432
432
  - app/views/json_ui/garage/test_page/dialog.json.jbuilder
433
433
  - app/views/json_ui/garage/test_page/dialog_open.json.jbuilder
434
434
  - app/views/json_ui/garage/test_page/dirty_state.json.jbuilder
435
+ - app/views/json_ui/garage/test_page/duplicate_names.json.jbuilder
435
436
  - app/views/json_ui/garage/test_page/fields.json.jbuilder
436
437
  - app/views/json_ui/garage/test_page/fields_captcha.json.jbuilder
437
438
  - app/views/json_ui/garage/test_page/fields_creditCard.json.jbuilder
@@ -465,6 +466,7 @@ files:
465
466
  - app/views/json_ui/garage/test_page/horizontal.json.jbuilder
466
467
  - app/views/json_ui/garage/test_page/http.json.jbuilder
467
468
  - app/views/json_ui/garage/test_page/image.json.jbuilder
469
+ - app/views/json_ui/garage/test_page/inputs_outside_form.json.jbuilder
468
470
  - app/views/json_ui/garage/test_page/lifecycle.json.jbuilder
469
471
  - app/views/json_ui/garage/test_page/list.json.jbuilder
470
472
  - app/views/json_ui/garage/test_page/list_editable.json.jbuilder