glib-web 0.5.0 → 0.5.5

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/glib/home_controller.rb +1 -1
  3. data/app/helpers/glib/app_feature_support_helper.rb +16 -0
  4. data/app/helpers/glib/json_ui/list_builders.rb +5 -0
  5. data/app/helpers/glib/json_ui/page_helper.rb +21 -16
  6. data/app/helpers/glib/json_ui/view_builder/fields.rb +3 -0
  7. data/app/helpers/glib/json_ui/view_builder/panels.rb +2 -0
  8. data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +21 -12
  9. data/app/views/json_ui/garage/actions/dialogs_oauth_post.json.jbuilder +6 -0
  10. data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +9 -18
  11. data/app/views/json_ui/garage/forms/dynamic_select_data.json.jbuilder +25 -10
  12. data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +5 -5
  13. data/app/views/json_ui/garage/forms/pickers.json.jbuilder +6 -3
  14. data/app/views/json_ui/garage/lists/_infinite_scroll_section.json.jbuilder +15 -5
  15. data/app/views/json_ui/garage/notifications/index.json.jbuilder +0 -43
  16. data/app/views/json_ui/garage/notifications/web_socket.json.jbuilder +19 -21
  17. data/app/views/json_ui/garage/tables/autoload_as_needed.json.jbuilder +39 -0
  18. data/app/views/json_ui/garage/tables/index.json.jbuilder +3 -0
  19. data/app/views/json_ui/garage/views/_chart_data.json.jbuilder +1 -1
  20. data/app/views/json_ui/garage/views/calendar_data.json.jbuilder +23 -27
  21. data/lib/glib-web.rb +1 -0
  22. data/lib/glib/json_crawler.rb +1 -0
  23. data/lib/glib/json_crawler/action_crawlers/menu.rb +12 -0
  24. data/lib/glib/json_crawler/action_crawlers/nav_initiate.rb +1 -1
  25. data/lib/glib/json_crawler/action_crawlers/windows_open.rb +8 -3
  26. data/lib/glib/json_crawler/http.rb +14 -14
  27. data/lib/glib/json_crawler/router.rb +3 -6
  28. data/lib/glib/test_helpers.rb +40 -0
  29. metadata +6 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 832af08d8701c658362e9974f4a9ed5a52c5bb5f
4
- data.tar.gz: 81b729e8cc79ee02437eb96b715ad8e4ccd86283
3
+ metadata.gz: 3a631905663a326cc5d4da2aa0be179812d12aae
4
+ data.tar.gz: a167fd02e4db101e5067832225762ba410bc401b
5
5
  SHA512:
6
- metadata.gz: 2ee4d1c3b862f97349c17d9d638766006ad47832b26b7abc46d8976139012f1ab2fbe23bf931c0fc36623f06c7a7ae8802e8d766044c9c11a4194a8684214875
7
- data.tar.gz: 1d76aa4197f3d12d3131b3224e83d76fe7d8c3aa54a8a258945ca2f76f8b690ef4f281d3d961d3a9b785c8660bb6d66a9ccb45ebc1494a57e2b53162df512ce2
6
+ metadata.gz: 0a5094637dbe44532c384bd7e30a49bb3dd5377ef87cee6ea13da3528620aae8f2a43eba21f3077df4530a3356087851dcbd8be150d72a3ff1af70b4b3493afb
7
+ data.tar.gz: 03b85596d99b043700a6818feef54b6e45017e905800358502052a68bdf0d6cb472c64bc9bb352849a9628b587479bfbab41314da1543cb1f92317371639ac07
@@ -1,6 +1,6 @@
1
1
  module Glib
2
2
  class HomeController < ApplicationController
3
- if glib_auth_inited?
3
+ if try(:glib_auth_inited?)
4
4
  skip_before_action :glib_load_resource
5
5
  skip_before_action :glib_authorize_resource
6
6
  end
@@ -0,0 +1,16 @@
1
+ module Glib
2
+ module AppFeatureSupportHelper
3
+ def glib_app_feature_supported?(name, app_version, dictionary)
4
+ device = (app_device_os || :default).to_sym
5
+
6
+ version = dictionary[name.to_sym].try(:[], device)
7
+ except = dictionary[name.to_sym].try(:[], :except).try(:[], device)
8
+
9
+ !version.nil? && (version == :all || glib_app_version_gte(version, app_version)) && (except.nil? || except.to_s != app_version)
10
+ end
11
+
12
+ def glib_app_version_gte(feature_version, app_version)
13
+ app_version.blank? || Gem::Version.new(app_version) >= Gem::Version.new(feature_version)
14
+ end
15
+ end
16
+ end
@@ -41,6 +41,11 @@ module Glib
41
41
 
42
42
  class Custom < Thumbnail
43
43
  string :template
44
+
45
+ # TODO: Experimental
46
+ hash :extra
47
+
48
+ # TODO: Deprecate
44
49
  hash :data
45
50
  end
46
51
  end
@@ -17,22 +17,27 @@ module Glib
17
17
  @__json_ui_page
18
18
  end
19
19
 
20
- # Use this only if you need to generate json independently from the current `json_ui_page`
21
- def json_ui_menu(&block)
22
- @__json_ui_menu_page ||= Page.new(Jbuilder.new, self)
23
- json = @__json_ui_menu_page.json
24
- json.nil!
25
- block&.call @__json_ui_menu_page.menu_builder
26
- json.attributes!
27
- end
28
-
29
- # Use this only if you need to generate json independently from the current `json_ui_page`
30
- def json_ui_panel(&block)
31
- @__json_ui_panel_page ||= Page.new(Jbuilder.new, self)
32
- json = @__json_ui_panel_page.json
33
- json.nil!
34
- block&.call @__json_ui_panel_page.view_builder
35
- json.attributes!
20
+ # # Use this only if you need to generate json independently from the current `json_ui_page`
21
+ # def json_ui_menu(&block)
22
+ # @__json_ui_menu_page ||= Page.new(Jbuilder.new, self)
23
+ # json = @__json_ui_menu_page.json
24
+ # json.nil!
25
+ # block&.call @__json_ui_menu_page.menu_builder
26
+ # json.attributes!
27
+ # end
28
+
29
+ # # Use this only if you need to generate json independently from the current `json_ui_page`
30
+ # def json_ui_panel(&block)
31
+ # @__json_ui_panel_page ||= Page.new(Jbuilder.new, self)
32
+ # json = @__json_ui_panel_page.json
33
+ # json.nil!
34
+ # block&.call @__json_ui_panel_page.view_builder
35
+ # json.attributes!
36
+ # end
37
+
38
+ def json_ui_section(json, &block)
39
+ @__json_ui_section ||= Page.new(json, self)
40
+ @__json_ui_section.list_section_builder
36
41
  end
37
42
 
38
43
  class Page
@@ -104,6 +104,9 @@ class Glib::JsonUi::ViewBuilder
104
104
 
105
105
  class Check < Text
106
106
  string :uncheckValue
107
+ string :checkValue
108
+
109
+ # Where possible, use value instead of this
107
110
  bool :checked
108
111
  end
109
112
 
@@ -123,6 +123,8 @@ class Glib::JsonUi::ViewBuilder
123
123
  hash :nextPage
124
124
  hash :export
125
125
  hash :import
126
+ action :onScrollToTop
127
+ action :onScrollToBottom
126
128
 
127
129
  def firstSection(block)
128
130
  json.sections [1] do
@@ -79,17 +79,26 @@ section.rows builder: ->(template) do
79
79
  end
80
80
 
81
81
  template.thumbnail title: 'dialogs/oauth', onClick: ->(action) do
82
- provider = {
83
- name: "facebook",
84
- webRequestUrl: "https://www.facebook.com/v3.1/dialog/oauth?auth_type=rerequest&client_id=CLIENT_ID&redirect_uri=http%3A%2F%2Fwww.lvh.me%3A3000%2Foauth_callback%2Ffacebook&response_type=code&scope=email",
85
- requestUrl: "https://www.facebook.com/v3.1/dialog/oauth",
86
- clientId: "CLIENT_ID",
87
- redirectUrl: "http://www.lvh.me:3000/oauth_callback/facebook.json"
88
- }
89
-
90
- action.dialogs_oauth provider: provider, providerParamName: "session[oauth_provider]", callbackUrlParamName: "session[[oauth_callback_url]", onSuccess: ->(action) do
91
- action.http_post url: 'TODO: post params to server'
82
+ if respond_to?(:user_facebook_omniauth_authorize_url)
83
+ provider = {
84
+ name: 'facebook',
85
+ webRequestUrl: user_facebook_omniauth_authorize_url(format: nil, _render: nil),
86
+ requestUrl: user_facebook_omniauth_authorize_url(format: nil),
87
+ clientId: Devise.omniauth_configs[:facebook].strategy[:client_id],
88
+ permissions: Devise.omniauth_configs[:facebook].strategy[:scope],
89
+ redirectUrl: user_facebook_omniauth_callback_url(format: nil)
90
+ }
91
+ action.dialogs_oauth provider: provider, providerParamName: 'session[oauth_provider]', callbackUrlParamName: 'session[[oauth_callback_url]', onSuccess: ->(subaction) do
92
+ subaction.http_post url: json_ui_garage_url(path: 'actions/dialogs_oauth_post'), formData: {
93
+ authenticity_token: form_authenticity_token
94
+ }
95
+ end
96
+ else
97
+ action.dialogs_alert message: 'To enable this, set up omniauth using devise'
98
+ # E.g.
99
+ # Add `devise :omniauthable, omniauth_providers: %i[facebook]` to user.rb
100
+ # Add `gem 'omniauth-facebook'` to Gemfile
101
+ # Add `config.omniauth :facebook` to devise.rb
92
102
  end
93
103
  end
94
-
95
- end
104
+ end
@@ -0,0 +1,6 @@
1
+ facebook_graph = Koala::Facebook::API.new(params[:credentials][:token])
2
+ profile = facebook_graph.get_object('me')
3
+
4
+ json_ui_response json do |action|
5
+ action.dialogs_alert message: profile
6
+ end
@@ -10,7 +10,8 @@ json_ui_page json do |page|
10
10
  value = [
11
11
  {
12
12
  'question': 'Punctuality',
13
- 'type': 'rating'
13
+ 'type': 'rating',
14
+ 'enabled': '1'
14
15
  },
15
16
  {
16
17
  'question': 'Quality of work',
@@ -21,30 +22,20 @@ json_ui_page json do |page|
21
22
  'type': 'yes_no'
22
23
  }
23
24
  ]
24
- # form.fields_dynamicGroup width: 'matchParent', name: 'user[evaluation]', value: value, groupTitlePrefix: 'Entry', groupTemplateViews: ->(group) do
25
- # group.spacer height: 10
26
- # group.fields_text width: 'matchParent', name: 'question', label: 'Question'
27
- # group.fields_text width: 'matchParent', name: 'type', label: 'Answer type'
28
- # end
29
-
30
- # form.fields_dynamicGroup width: 'matchParent', name: 'user[evaluation]', value: value, group: ->(group) do
31
- # group.titlePrefix 'Entry'
32
- # group.template childViews: ->(template) do
33
- # template.spacer height: 10
34
- # template.fields_text width: 'matchParent', name: 'question', label: 'Question'
35
- # template.fields_text width: 'matchParent', name: 'type', label: 'Answer type'
36
- # end
37
- # end
38
25
 
39
26
  form.fields_dynamicGroup width: 'matchParent', name: 'user[evaluation]', value: value, titlePrefix: 'Entry', content: ->(group) do
40
27
  group.template padding: { left: 32 }, childViews: ->(template) do
41
28
  template.spacer height: 10
42
- template.fields_text width: 'matchParent', name: 'question', label: 'Question'
43
- template.fields_text width: 'matchParent', name: 'type', label: 'Answer type'
29
+ template.fields_text width: 'matchParent', name: 'question', label: 'Question', placeholder: 'Question'
30
+ options = [ :rating, :yes_no ]
31
+ template.fields_select width: 'matchParent', name: 'type', label: 'Answer Type', placeholder: 'Answer Type', options: options.map { |o| { text: o.to_s.humanize, value: o } }
32
+ template.fields_check width: 'matchParent', name: 'enabled', label: 'Enable', checkValue: '1'
33
+
34
+ template.spacer height: 14
44
35
  end
45
36
  end
46
37
 
47
38
  form.spacer height: 20
48
- form.button text: 'Submit', onClick: ->(action) { action.forms_submit }
39
+ form.fields_submit text: 'Submit'
49
40
  end
50
41
  end
@@ -6,18 +6,33 @@ if page < 2
6
6
  json.nextPageUrl json_ui_garage_url(path: 'forms/dynamic_select_data', page: page + 1)
7
7
  end
8
8
 
9
- json.rows do
9
+ # json.rows do
10
10
 
11
+ # count_per_page = 20
12
+ # count_per_page.times do |i|
13
+ # json.child! do
14
+ # index = page * count_per_page + i
15
+ # json.template 'thumbnail'
16
+ # json.title "City #{index} (#{params[:q]})"
17
+ # json.subtitle "State #{index}"
18
+ # json.subsubtitle "Country #{index}"
19
+ # json.value "id#{index}"
20
+ # json.text "Item #{index}"
21
+ # end
22
+ # end
23
+ # end
24
+
25
+ section = json_ui_section json
26
+ section.rows builder: ->(row) do
11
27
  count_per_page = 20
12
28
  count_per_page.times do |i|
13
- json.child! do
14
- index = page * count_per_page + i
15
- json.template 'thumbnail'
16
- json.title "City #{index} (#{params[:q]})"
17
- json.subtitle "State #{index}"
18
- json.subsubtitle "Country #{index}"
19
- json.value "id#{index}"
20
- json.text "Item #{index}"
21
- end
29
+ index = page * count_per_page + i
30
+ row.custom title: "City #{index} (#{params[:q]})",
31
+ subtitle: "State #{index}",
32
+ subsubtitle: "Country #{index}",
33
+ extra: {
34
+ value: "id#{index}",
35
+ text: "Item #{index}"
36
+ }
22
37
  end
23
38
  end
@@ -8,18 +8,18 @@ options = {
8
8
 
9
9
  json_ui_page json do |page|
10
10
  render "#{@path_prefix}/nav_menu", json: json, page: page
11
-
11
+
12
12
  page.form options.merge(childViews: ->(form) do
13
13
  rules1 = { fileType: "image/*", maxFileSize: 5000 }
14
14
  rules2 = { fileType: "image/*", maxFileSize: 1, fileTypeErrorText: 'Invalid!', maxFileSizeErrorText: 'Too big!' }
15
- form.fields_file name: 'user[photo][]', width: 'matchParent', label: 'Photo', accepts: rules1, directUploadUrl: rails_direct_uploads_url,
15
+ form.fields_file name: 'user[photo][]', width: 'matchParent', label: 'Landscape Photo', accepts: rules1, directUploadUrl: rails_direct_uploads_url,
16
16
  value: 'eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBFQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--193dc0d939b9558fc4973fafbba91d989cbb04d4',
17
17
  fileUrl: 'https://imageserver-demo.herokuapp.com/image/itinerarybuilder-demo/o6CKzNt67PWnkPdUEnWMt7pr?h=100&w=100',
18
18
  fileTitle: '1 month ago',
19
- placeholderView: { type: 'image', width: 100, height: 100 }
19
+ placeholderView: { type: 'image', width: 100, height: 75, url: 'https://www.atms.com.au/wp-content/uploads/2019/10/placeholder-1-1024x683.png?x93630' }
20
20
 
21
- form.fields_file name: 'user[photo][]', width: 'matchParent', label: 'Photo', accepts: rules2, directUploadUrl: rails_direct_uploads_url,
22
- placeholderView: { type: 'avatar', width: 100, height: 100 }
21
+ form.fields_file name: 'user[photo][]', width: 'matchParent', label: 'Avatar', accepts: rules2, directUploadUrl: rails_direct_uploads_url,
22
+ placeholderView: { type: 'avatar', width: 100, height: 100, url: 'data:image/jpeg;base64,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' }
23
23
 
24
24
  form.fields_submit text: 'Submit'
25
25
  # form.button text: 'Submit', onClick: ->(action) { action.forms_submit }
@@ -8,14 +8,16 @@ json_ui_page json do |page|
8
8
  form.spacer height: 6
9
9
  form.h4 text: 'Gender'
10
10
  form.fields_radioGroup name: 'user[gender]', value: 'F', childViews: ->(group) do
11
+ group.fields_radio value: '', label: 'Unknown'
11
12
  group.fields_radio value: 'M', label: 'Male'
12
13
  group.fields_radio value: 'F', label: 'Female'
13
14
  end
14
15
 
15
16
  form.spacer height: 20
16
17
  form.h2 text: 'Single Checkbox'
17
- form.fields_check name: 'user[age_range]', value: '16+', uncheckValue: '0-16', label: 'I am over 16 (has default value)'
18
- form.fields_check name: 'user[employer]', value: 1, label: 'I am an employer (no default value)'
18
+ form.fields_check name: 'user[age_range]', value: '16+', checkValue: '16+', uncheckValue: '0-16', label: 'I am over 16 (has default value)'
19
+ form.fields_check name: 'user[employer]', checkValue: 1, label: 'I am an employer (no default value)'
20
+ form.fields_check name: 'user[enabled]', checkValue: true, label: 'Enable', styleClass: 'switch', value: 'true'
19
21
 
20
22
  form.spacer height: 20
21
23
  form.h2 text: 'Date/Time'
@@ -36,7 +38,8 @@ json_ui_page json do |page|
36
38
  latitudeField: { name: 'user[latitude]', label: 'Lat', value: -33.8523063, readOnly: true },
37
39
  longitudeField: { name: 'user[longitude]', label: 'Long', value: 151.21078710000006, readOnly: true }
38
40
 
39
- form.button text: 'Submit', onClick: ->(action) { action.forms_submit }
41
+ form.spacer height: 20
42
+ form.fields_submit text: 'Submit'
40
43
 
41
44
  end
42
45
 
@@ -1,10 +1,20 @@
1
- json.rows do
1
+
2
+ # json.rows do
3
+ # batch_count = 30
4
+ # batch_count.times do |i|
5
+ # index = page * batch_count + i
6
+ # json.child! do
7
+ # json.template 'thumbnail'
8
+ # json.title "Item #{index}"
9
+ # end
10
+ # end
11
+ # end
12
+
13
+ section = json_ui_section json
14
+ section.rows builder: ->(row) do
2
15
  batch_count = 30
3
16
  batch_count.times do |i|
4
17
  index = page * batch_count + i
5
- json.child! do
6
- json.template 'thumbnail'
7
- json.title "Item #{index}"
8
- end
18
+ row.thumbnail title: "Item #{index}"
9
19
  end
10
20
  end
@@ -1,23 +1,5 @@
1
1
  json.title 'Notifications'
2
2
 
3
- # json.ws({
4
- # "socket" => {
5
- # "endpoint" => "/socket/websocket",
6
- # "params" => {
7
- # "vsn": "2.0.0"
8
- # }
9
- # },
10
- # # "topic" => "room:30",
11
- # # "event" => "comments_updated",
12
- # "topic" => "links",
13
- # "event" => "new_link_added",
14
- # "header" => {
15
- # "user_id" => 2,
16
- # "prev_item_id" => nil,
17
- # "last_item_id" => nil
18
- # }
19
- # })
20
-
21
3
  page = json_ui_page json
22
4
  render "#{@path_prefix}/nav_menu", json: json, page: page, top_nav: true
23
5
 
@@ -31,31 +13,6 @@ page.list firstSection: ->(section) do
31
13
 
32
14
  template.thumbnail title: 'WebSocket Real-time Update', onClick: ->(action) do
33
15
  action.windows_open url: json_ui_garage_url(path: 'notifications/web_socket')
34
- # dialogs_notification title: 'Hello World', message: 'This is a notification', onClick: ->(subaction) do
35
- # subaction.dialogs_alert message: 'Perform action'
36
- # end
37
16
  end
38
-
39
- # template.thumbnail title: 'Send WebSocket Notification', onClick: ->(action) do
40
- # json.action "ws/push"
41
- # json.topic "links"
42
- # json.event "new_link"
43
- # json.payload({
44
- # "club_id": "2",
45
- # "room_id": "30",
46
- # "user_id": "2"
47
- # # title: "TITLE",
48
- # # url: "URL"
49
- # })
50
-
51
- # # "topic": "room:30",
52
- # # "event": "create_comment",
53
- # # "payload": {
54
- # # "club_id": "2",
55
- # # "room_id": "30",
56
- # # "user_id": "2"
57
- # # }
58
-
59
- # end
60
17
  end
61
18
  end
@@ -14,7 +14,7 @@ json.ws({
14
14
  # "topic" => "room:30",
15
15
  # "event" => "comments_updated",
16
16
  "topic" => "links",
17
- "event" => "new_link_added",
17
+ "events" => ["new_link_added"],
18
18
  "header" => {
19
19
  "user_id" => 2,
20
20
  "prev_item_id" => nil,
@@ -23,31 +23,29 @@ json.ws({
23
23
  })
24
24
 
25
25
  page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', padding: glib_json_padding_body, paramNameForFormData: 'formData', onSubmit: ->(action) do
26
- # action.dialogs_alert
27
-
28
- json.action "ws/push"
29
- json.topic "links"
30
- json.event "new_link"
31
- json.payload({
32
- "club_id": "2",
33
- "room_id": "30",
34
- "user_id": "2"
35
- # title: "TITLE",
36
- # url: "URL"
37
- })
38
-
39
- # "topic": "room:30",
40
- # "event": "create_comment",
41
- # "payload": {
42
- # "club_id": "2",
43
- # "room_id": "30",
44
- # "user_id": "2"
45
- # }
26
+ json.action "ws/push"
27
+ json.topic "links"
28
+ json.event "new_link"
29
+ json.payload({
30
+ "club_id": "2",
31
+ "room_id": "30",
32
+ "user_id": "2"
33
+ # title: "TITLE",
34
+ # url: "URL"
35
+ })
46
36
 
47
37
  end, childViews: ->(form) do
38
+ form.spacer height: 14
39
+ form.label text: "Message: #{params[:message]}"
40
+ form.spacer height: 14
41
+
48
42
  form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name'
43
+
44
+ # TODO: Change this to radio for selecting alert vs reload response
49
45
  form.fields_password name: 'user[password]', width: 'matchParent', label: 'Password'
50
46
 
47
+ form.fields_hidden name: 'baseUrl', width: 'matchParent', value: json_ui_garage_url(path: 'notifications/web_socket')
48
+
51
49
  form.panels_split width: 'matchParent', content: ->(split) do
52
50
  # split.left childViews: ->(left) do
53
51
  # if params[:mode] == 'dialog'
@@ -0,0 +1,39 @@
1
+
2
+ page_index = params[:page].to_i
3
+ next_page = {
4
+ url: json_ui_garage_url(path: 'tables/autoload_all', page: page_index + 1, section_only: 'v1'),
5
+ autoload: 'asNeeded'
6
+ }
7
+
8
+ column_indexes = (1..3)
9
+ if params[:section_only].present?
10
+ json.nextPage next_page if page_index < 3
11
+ json_ui_page json do |page|
12
+ json.sections do
13
+ json.child! do
14
+ render 'json_ui/garage/tables/autoload_section', page: page, page_index: page_index, column_indexes: column_indexes
15
+ end
16
+ end
17
+ end
18
+ else
19
+ json.title 'Tables'
20
+
21
+ json_ui_page json do |page|
22
+ render "#{@path_prefix}/nav_menu", json: json, page: page
23
+
24
+ page.table nextPage: next_page, firstSection: ->(section) do
25
+ section.header cellViews: ->(header) do
26
+ column_indexes.each do |i|
27
+ header.label text: "Heading#{i}"
28
+ end
29
+ end
30
+
31
+ render "#{@path_prefix}/tables/autoload_section", page: page, page_index: page_index, column_indexes: column_indexes
32
+ end, onScrollToBottom: ->(action) do
33
+ action.snackbars_alert message: 'Scrolled to Bottom'
34
+ end, onScrollToTop: ->(action) do
35
+ action.snackbars_alert message: 'Scrolled to Top'
36
+ end
37
+ end
38
+
39
+ end
@@ -17,6 +17,9 @@ json_ui_page json do |page|
17
17
  template.thumbnail title: 'Autoload All', onClick: ->(action) do
18
18
  action.windows_open url: json_ui_garage_url(path: 'tables/autoload_all')
19
19
  end
20
+ template.thumbnail title: 'Autoload as Needed', onClick: ->(action) do
21
+ action.windows_open url: json_ui_garage_url(path: 'tables/autoload_as_needed')
22
+ end
20
23
  end
21
24
 
22
25
  end
@@ -14,4 +14,4 @@ if page_index < 3
14
14
  json.points (from.month.ago.to_date..to.month.ago.to_date).map { |d| { x: d, y: 100 + rand(40) } }
15
15
  end
16
16
  ]
17
- end
17
+ end
@@ -1,34 +1,30 @@
1
-
2
- json.events do
3
-
4
- json.child! do
5
- json.start '2018-12-14'
6
- json.end '2018-12-17'
7
- json.text 'Hackathon'
8
- json.onClick do
9
- json.action 'dialogs/alert-v1'
10
- json.message 'At Town Hall'
1
+ section = json_ui_section json
2
+ section.rows builder: ->(row) do
3
+ row.custom title: 'Hackathon',
4
+ extra: {
5
+ start: '2018-12-14',
6
+ end: '2018-12-17'
7
+ },
8
+ onClick: ->(action) do
9
+ action.dialogs_alert message: 'At Town Hall'
11
10
  end
12
- end
13
11
 
14
- json.child! do
15
- json.start '2018-12-30'
16
- json.end '2018-12-30'
17
- json.text 'Birthday'
18
- json.onClick do
19
- json.action 'dialogs/alert-v1'
20
- json.message 'At home'
12
+ row.custom title: 'Birthday',
13
+ extra: {
14
+ start: '2018-12-30',
15
+ end: '2018-12-30'
16
+ },
17
+ onClick: ->(action) do
18
+ action.dialogs_alert message: 'At home'
21
19
  end
22
- end
23
20
 
24
- json.child! do
25
- json.start '2018-12-31'
26
- json.end '2018-12-31'
27
- json.text 'Conference'
28
- json.onClick do
29
- json.action 'dialogs/alert-v1'
30
- json.message 'In Perth'
21
+ row.custom title: 'Conference',
22
+ extra: {
23
+ start: '2018-12-31',
24
+ end: '2019-01-02'
25
+ },
26
+ onClick: ->(action) do
27
+ action.dialogs_alert message: 'In Perth'
31
28
  end
32
- end
33
29
 
34
30
  end
@@ -5,3 +5,4 @@ require "glib/json_crawler"
5
5
 
6
6
  require 'glib/dynamic_text'
7
7
  require 'glib/crypt'
8
+ require 'glib/test_helpers'
@@ -7,3 +7,4 @@ require_relative './json_crawler/action_crawlers/nav_initiate'
7
7
  require_relative './json_crawler/action_crawlers/windows_open'
8
8
  require_relative './json_crawler/action_crawlers/action_http'
9
9
  require_relative './json_crawler/action_crawlers/forms_submit'
10
+ require_relative './json_crawler/action_crawlers/menu'
@@ -0,0 +1,12 @@
1
+ module Glib
2
+ module JsonCrawler
3
+ class Menu < ActionCrawler
4
+ def initialize(http, args, action)
5
+ super(http)
6
+
7
+ @http.router.log action, nil
8
+ crawl args['buttons']
9
+ end
10
+ end
11
+ end
12
+ end
@@ -5,7 +5,7 @@ module Glib
5
5
  super(http)
6
6
 
7
7
  @http = http
8
- if (json = @http.get args['url'], action) && (left_drawer = json['leftDrawer'])
8
+ if (json = (@http.get args['url'], action, args.except('url'))) && (left_drawer = json['leftDrawer'])
9
9
  crawl left_drawer['header']&.[]('childViews')
10
10
  crawl left_drawer['rows']
11
11
  end
@@ -4,7 +4,7 @@ module Glib
4
4
  def initialize(http, args, action)
5
5
  @http = http
6
6
  if (url = args['url'])
7
- json = @http.get url, action
7
+ json = @http.get(url, action, args.except('url'))
8
8
 
9
9
  unless json.nil?
10
10
  crawl json['header']&.[]('childViews')
@@ -12,11 +12,16 @@ module Glib
12
12
  crawl json['footer']&.[]('childViews')
13
13
 
14
14
  json['rightNavButtons']&.each do |button|
15
- click button
15
+ if button['buttons'].present?
16
+ button['buttons'].each do |inner_button|
17
+ click inner_button
18
+ end
19
+ else
20
+ click button
21
+ end
16
22
  end
17
23
  end
18
24
  end
19
-
20
25
  end
21
26
  end
22
27
  end
@@ -8,8 +8,8 @@ module Glib
8
8
  VALID_RESPONSE_CODES = [
9
9
  (200..299).to_a,
10
10
  ## Note, the JSON API does not allow redirects
11
- 401, ## UNAUTHORIZED Should be used for not-logged-in
12
- 403, ## FORBIDDEN Should be used for logged-in but not allowed to access
11
+ # 401, ## UNAUTHORIZED Should be used for not-logged-in
12
+ # 403, ## FORBIDDEN Should be used for logged-in but not allowed to access
13
13
  ].flatten
14
14
 
15
15
  def initialize(context, user, router)
@@ -20,8 +20,8 @@ module Glib
20
20
  @router = router
21
21
  end
22
22
 
23
- def get(url, action, inspect_result = true)
24
- fetch(:get, url, action, {}, inspect_result)
23
+ def get(url, action, params = {}, inspect_result = true)
24
+ fetch(:get, url, action, params, inspect_result)
25
25
  end
26
26
 
27
27
  def post(url, action, params)
@@ -40,14 +40,6 @@ module Glib
40
40
  fetch(:delete, url, action, {})
41
41
  end
42
42
 
43
- def controller
44
- @context.integration_session.controller
45
- end
46
-
47
- def action_name
48
- controller.action_name.to_sym
49
- end
50
-
51
43
  private
52
44
  Response = Struct.new :code, :headers, :media_type, :body do
53
45
  def initialize(*)
@@ -66,13 +58,16 @@ module Glib
66
58
  history << url
67
59
  end
68
60
 
69
- @context.assert_match(URI_REGEXP, url)
61
+ if !URI_REGEXP.match(url)
62
+ raise "Invalid URL: `#{url}`. Make sure to use the absolute URL."
63
+ end
70
64
 
71
65
  http_header = {
72
66
  'Client-DeviceOS' => user[:device],
73
67
  'Client-Version' => user[:version],
74
68
  'X-CSRF-Token' => user[:token]
75
69
  }
70
+ http_header.merge!(params[:headers]) if params[:headers].present?
76
71
 
77
72
  params.each do |name, value|
78
73
  params[name] = '' if value.is_a?(Array) && value.size == 0
@@ -83,6 +78,10 @@ module Glib
83
78
  @context.send(method, url, params: params, headers: http_header)
84
79
  raw_response = @context.response
85
80
  response = Response.new(raw_response.code.to_i, raw_response.headers, raw_response.media_type, raw_response.body)
81
+
82
+ if (controller = @context.controller)
83
+ Glib::JsonCrawler::Coverage.coverage_files.add(controller.class.instance_method(controller.action_name).source_location.first)
84
+ end
86
85
  rescue => ex
87
86
  if !inspect_result
88
87
  case ex
@@ -103,9 +102,10 @@ module Glib
103
102
  if (code = response.code) == 302
104
103
  redirect_uri = URI(response.headers['Location'])
105
104
  redirect_uri.query = [redirect_uri.query, 'format=json'].compact.join('&')
106
- get redirect_uri.to_s, action
105
+ get redirect_uri.to_s, action, params
107
106
  else
108
107
  response_times << response.headers['X-Runtime'].to_f
108
+
109
109
  @context.assert_includes VALID_RESPONSE_CODES, code, "Expected a valid response but was [#{response.code}] #{Rack::Utils::HTTP_STATUS_CODES[response.code.to_i]}:\n#{url}"
110
110
  if response.media_type == 'application/json'
111
111
  JSON.parse(response.body)
@@ -19,10 +19,6 @@ module Glib
19
19
  end
20
20
 
21
21
  def step(http, args)
22
- if (controller = http.controller)
23
- Glib::JsonCrawler::Coverage.coverage_files.add(controller.class.instance_method(http.action_name).source_location.first)
24
- end
25
-
26
22
  case args['view']
27
23
  when 'fields/submit-v1', 'fields/submit'
28
24
  @depth += 1
@@ -40,7 +36,6 @@ module Glib
40
36
 
41
37
  if action.present?
42
38
  @depth += 1
43
- # child =
44
39
  case action
45
40
  when 'initiate_navigation'
46
41
  @read_only_actions.add([action, params['url']])
@@ -48,6 +43,8 @@ module Glib
48
43
  when 'windows/open-v1', 'dialogs/open-v1', 'windows/reload-v1', 'windows/open', 'dialogs/open', 'windows/reload'
49
44
  @read_only_actions.add([action, params['url']])
50
45
  JsonCrawler::WindowsOpen.new(http, params, action)
46
+ when 'sheets/select-v1', 'sheets/select'
47
+ JsonCrawler::Menu.new(http, params, action)
51
48
  when 'http/post-v1', 'http/post'
52
49
  JsonCrawler::ActionHttp.new(:post, http, params, action)
53
50
  when 'forms/submit-v1', 'forms/submit'
@@ -73,7 +70,7 @@ module Glib
73
70
  @depth += 1
74
71
  target_router.read_only_actions.each do |crawler_action|
75
72
  action, url = crawler_action
76
- http.get url, action, false
73
+ http.get(url, action, {}, false)
77
74
  end
78
75
  end
79
76
 
@@ -0,0 +1,40 @@
1
+ module Glib
2
+ module TestHelpers
3
+ def response_assert_equal
4
+ expected = __get_previous_result_from_git
5
+ result = __log(response.body)
6
+ assert_equal JSON.parse(expected), JSON.parse(result), "Result mismatch! #{__git_is_available? ? `git diff #{__log_dir}/#{__log_file}` : ''}"
7
+ end
8
+
9
+ private
10
+ def __git_is_available?
11
+ @__git_is_available ||= (`git status 2>&1` =~ /fatal/).nil?
12
+ end
13
+
14
+ def __log_dir
15
+ if @__log_dir.nil?
16
+ @__log_dir = File.expand_path("#{Rails.root}/test/controllers/#{self.class.to_s.underscore}_results", File.dirname(__FILE__))
17
+ unless File.directory?(@__log_dir)
18
+ FileUtils.mkdir_p(@__log_dir)
19
+ end
20
+ end
21
+ @__log_dir
22
+ end
23
+
24
+ def __log_file
25
+ @__log_file ||= "#{self.method_name}.json"
26
+ end
27
+
28
+ def __log json
29
+ File.open("#{File.join(__log_dir, __log_file)}", "w") do |f|
30
+ f << JSON.pretty_generate( JSON.parse(json) )
31
+ end
32
+ json
33
+ end
34
+
35
+ def __get_previous_result_from_git
36
+ `git checkout -- "#{File.join(__log_dir, __log_file)}" > /dev/null 2>&1` if __git_is_available?
37
+ File.exists?(File.join(__log_dir, __log_file)) ? File.open(File.join(__log_dir, __log_file)).read : "\{\}"
38
+ end
39
+ end
40
+ end
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: 0.5.0
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -73,6 +73,7 @@ files:
73
73
  - app/controllers/concerns/glib/json/ui.rb
74
74
  - app/controllers/concerns/glib/json/validation.rb
75
75
  - app/controllers/glib/home_controller.rb
76
+ - app/helpers/glib/app_feature_support_helper.rb
76
77
  - app/helpers/glib/dynamic_images_helper.rb
77
78
  - app/helpers/glib/dynamic_texts_helper.rb
78
79
  - app/helpers/glib/forms_helper.rb
@@ -114,6 +115,7 @@ files:
114
115
  - app/views/json_ui/garage/actions/_snackbars.json.jbuilder
115
116
  - app/views/json_ui/garage/actions/_timeouts.json.jbuilder
116
117
  - app/views/json_ui/garage/actions/_windows.json.jbuilder
118
+ - app/views/json_ui/garage/actions/dialogs_oauth_post.json.jbuilder
117
119
  - app/views/json_ui/garage/actions/index.json.jbuilder
118
120
  - app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder
119
121
  - app/views/json_ui/garage/forms/basic.json.jbuilder
@@ -172,6 +174,7 @@ files:
172
174
  - app/views/json_ui/garage/services/index.json.jbuilder
173
175
  - app/views/json_ui/garage/tables/_autoload_section.json.jbuilder
174
176
  - app/views/json_ui/garage/tables/autoload_all.json.jbuilder
177
+ - app/views/json_ui/garage/tables/autoload_as_needed.json.jbuilder
175
178
  - app/views/json_ui/garage/tables/export_import.json.jbuilder
176
179
  - app/views/json_ui/garage/tables/horizontal_scroll.json.jbuilder
177
180
  - app/views/json_ui/garage/tables/index.json.jbuilder
@@ -207,11 +210,13 @@ files:
207
210
  - lib/glib/json_crawler/action_crawler.rb
208
211
  - lib/glib/json_crawler/action_crawlers/action_http.rb
209
212
  - lib/glib/json_crawler/action_crawlers/forms_submit.rb
213
+ - lib/glib/json_crawler/action_crawlers/menu.rb
210
214
  - lib/glib/json_crawler/action_crawlers/nav_initiate.rb
211
215
  - lib/glib/json_crawler/action_crawlers/windows_open.rb
212
216
  - lib/glib/json_crawler/coverage.rb
213
217
  - lib/glib/json_crawler/http.rb
214
218
  - lib/glib/json_crawler/router.rb
219
+ - lib/glib/test_helpers.rb
215
220
  - lib/glib/value.rb
216
221
  - lib/glib/version.rb
217
222
  - lib/tasks/db.rake