glib-web 6.4.1 → 6.5.0
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/concerns/glib/json/libs.rb +1 -1
- data/app/controllers/concerns/glib/json/traversal.rb +1 -1
- data/app/helpers/glib/json_ui/abstract_builder.rb +0 -15
- data/app/helpers/glib/json_ui/action_builder/components.rb +3 -0
- data/app/helpers/glib/json_ui/action_builder/logics.rb +3 -0
- data/app/helpers/glib/json_ui/action_builder.rb +2 -2
- data/app/helpers/glib/json_ui/menu_builder.rb +1 -1
- data/app/helpers/glib/json_ui/view_builder/panels.rb +14 -0
- data/app/helpers/glib/json_ui/view_builder.rb +7 -3
- data/app/views/json_ui/garage/forms/new_rich_text.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/rich_text.json.jbuilder +1 -1
- data/app/views/json_ui/garage/test_page/duplicate_names.json.jbuilder +84 -0
- data/app/views/json_ui/garage/test_page/inputs_outside_form.json.jbuilder +123 -0
- data/app/views/json_ui/garage/test_page/logics_run_multi_form.json.jbuilder +3 -0
- data/lib/glib/json_crawler/action_crawlers/forms_submit.rb +2 -2
- data/lib/glib/json_crawler/router.rb +15 -18
- data/lib/glib/test_helpers.rb +2 -2
- metadata +4 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2d8ea05929baccf426c3ef7f44c3b0c755ae8d27e67ce5ab4c654c3711eb0eb
|
|
4
|
+
data.tar.gz: 4427906583b5ae24631feba633e286d1b702a51d9012b8a19e0c6409a2e31715
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a734238edcb561b5a49479ee7cb01dc4ad147cac8beda29f2105719c1a2158dbbc5f886538a4adc68e6a1337d8c454efcba69d8e32ed2e9fe470b227c2ae780
|
|
7
|
+
data.tar.gz: b819efbb6637bb5e622b79cc904c207e68686845f4f918cb5d840a0f465a66738d954a18661743b6dee2c5fa535047e9621bc7c82188fdbdd4d2a2765166ca3f
|
|
@@ -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
|
-
|
|
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
|
-
|
|
49
|
+
add_singleton_element 'action', m, *args
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -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
|
|
@@ -89,9 +89,9 @@ module Glib
|
|
|
89
89
|
|
|
90
90
|
def add_view(name, *args)
|
|
91
91
|
if @multiple
|
|
92
|
-
|
|
92
|
+
add_element_to_array 'view', name, *args
|
|
93
93
|
else
|
|
94
|
-
|
|
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
|
|
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
|
|
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
|
|
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'
|
|
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
|
|
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
|
|
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
|
|
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
|
|
115
|
+
when 'runMultiple'
|
|
116
116
|
JsonCrawler::RunMultiple.new(http, params, action)
|
|
117
|
-
when '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
|
|
143
|
+
when 'dialogs/show', 'popovers/show'
|
|
145
144
|
JsonCrawler::DialogsShow.new(http, params, action)
|
|
146
|
-
when 'sheets/select
|
|
145
|
+
when 'sheets/select'
|
|
147
146
|
JsonCrawler::Menu.new(http, params, action)
|
|
148
|
-
when 'http/post
|
|
147
|
+
when 'http/post'
|
|
149
148
|
JsonCrawler::ActionHttp.new(:post, http, params, action)
|
|
150
|
-
when '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
|
|
153
|
+
when 'dialogs/alert'
|
|
155
154
|
JsonCrawler::DialogsAlert.new(http, params, action)
|
|
156
|
-
when 'dialogs/close
|
|
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
|
|
271
|
+
when 'http/post', 'forms/post'
|
|
275
272
|
http.post(url, action, params)
|
|
276
|
-
when 'http/patch
|
|
273
|
+
when 'http/patch', 'forms/patch'
|
|
277
274
|
http.patch(url, action, params)
|
|
278
|
-
when 'http/put
|
|
275
|
+
when 'http/put', 'forms/put'
|
|
279
276
|
http.put(url, action, params)
|
|
280
|
-
when 'http/delete
|
|
277
|
+
when 'http/delete'
|
|
281
278
|
http.delete(url, action, params)
|
|
282
279
|
else
|
|
283
280
|
http.get(url, action, params)
|
data/lib/glib/test_helpers.rb
CHANGED
|
@@ -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
|
|
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'
|
|
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,11 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: glib-web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ''
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
10
|
date: 2026-08-12 00:00:00.000000000 Z
|
|
@@ -178,7 +177,6 @@ dependencies:
|
|
|
178
177
|
- - ">="
|
|
179
178
|
- !ruby/object:Gem::Version
|
|
180
179
|
version: '0'
|
|
181
|
-
description:
|
|
182
180
|
email: ''
|
|
183
181
|
executables: []
|
|
184
182
|
extensions: []
|
|
@@ -432,6 +430,7 @@ files:
|
|
|
432
430
|
- app/views/json_ui/garage/test_page/dialog.json.jbuilder
|
|
433
431
|
- app/views/json_ui/garage/test_page/dialog_open.json.jbuilder
|
|
434
432
|
- app/views/json_ui/garage/test_page/dirty_state.json.jbuilder
|
|
433
|
+
- app/views/json_ui/garage/test_page/duplicate_names.json.jbuilder
|
|
435
434
|
- app/views/json_ui/garage/test_page/fields.json.jbuilder
|
|
436
435
|
- app/views/json_ui/garage/test_page/fields_captcha.json.jbuilder
|
|
437
436
|
- app/views/json_ui/garage/test_page/fields_creditCard.json.jbuilder
|
|
@@ -465,6 +464,7 @@ files:
|
|
|
465
464
|
- app/views/json_ui/garage/test_page/horizontal.json.jbuilder
|
|
466
465
|
- app/views/json_ui/garage/test_page/http.json.jbuilder
|
|
467
466
|
- app/views/json_ui/garage/test_page/image.json.jbuilder
|
|
467
|
+
- app/views/json_ui/garage/test_page/inputs_outside_form.json.jbuilder
|
|
468
468
|
- app/views/json_ui/garage/test_page/lifecycle.json.jbuilder
|
|
469
469
|
- app/views/json_ui/garage/test_page/list.json.jbuilder
|
|
470
470
|
- app/views/json_ui/garage/test_page/list_editable.json.jbuilder
|
|
@@ -574,10 +574,8 @@ files:
|
|
|
574
574
|
- lib/glib/time_returning_mailer.rb
|
|
575
575
|
- lib/glib/value.rb
|
|
576
576
|
- lib/tasks/db.rake
|
|
577
|
-
homepage:
|
|
578
577
|
licenses: []
|
|
579
578
|
metadata: {}
|
|
580
|
-
post_install_message:
|
|
581
579
|
rdoc_options: []
|
|
582
580
|
require_paths:
|
|
583
581
|
- lib
|
|
@@ -592,8 +590,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
592
590
|
- !ruby/object:Gem::Version
|
|
593
591
|
version: '0'
|
|
594
592
|
requirements: []
|
|
595
|
-
rubygems_version:
|
|
596
|
-
signing_key:
|
|
593
|
+
rubygems_version: 4.0.6
|
|
597
594
|
specification_version: 4
|
|
598
595
|
summary: ''
|
|
599
596
|
test_files: []
|