glib-web 3.12.0 → 3.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df6b1ad5defcb6d77fa2cff5f8daef5615ca3ce0965efeb7263a8d42e9e9ebe6
4
- data.tar.gz: 8bb3862f75b2d32c3284efc9de83afaa051c4e915a3ed5c1fe1b28b78e5fc0dd
3
+ metadata.gz: 33411954512fada9329818d4e011f5cb70f9c528a034fd87b8737318af18e07d
4
+ data.tar.gz: 492020f2693abdd8ffc38334c771cbe550952044f3030f9221fe163c5c49b103
5
5
  SHA512:
6
- metadata.gz: daa8778895e12cfb01ef928b27a61bc4b8cfbe20eb9c61a7e242a2ae63c8d8690cd45d348335832f79ff2cc3906b7f4c6c4bdfcc415f9db0ee297beb1ee29b6d
7
- data.tar.gz: c002c3203aedaff266113d6dc1ba50320010df33d53f82489cbe21fc207eb2069dc1fa82ed8934dfeccb2bc7c6c611788fbc3dadaa21769ff59039a984df90b4
6
+ metadata.gz: 97d3edb87b4e25bb71318dea8dd8243a2f98be27f74ac612e135100bfb5b12317c2b39e763f4e1301c2e3c08736fa7411f91a5a37eea96e1148b0d9d0e1e9841
7
+ data.tar.gz: 032b11ef90b8b22768459248da39de1a16f6342940cd902974bc96dc7d5a7c11acd7797d599e14bf21b11979b4ed237c053f9d82855856f29a7453b4f6ae98c4
@@ -0,0 +1,28 @@
1
+ module Glib
2
+ module Channel
3
+ class AppearanceChannel < ApplicationCable::Channel
4
+ def subscribed
5
+ stream_for "appearance_#{params[:room]}"
6
+ end
7
+
8
+ def status(data)
9
+ action = {
10
+ action: 'labels/set',
11
+ targetId: 'label-1',
12
+ text: data['text']
13
+ # onSet: {
14
+ # action: 'timeouts/set',
15
+ # interval: 1000,
16
+ # onTimeout: {
17
+ # action: 'labels/set',
18
+ # targetId: 'label-1',
19
+ # text: "Room ##{data['room'].upcase}"
20
+ # }
21
+ # }
22
+ }
23
+
24
+ broadcast_to("appearance_#{data['room']}", action)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module Glib
2
+ module Channel
3
+ class ChatChannel < ApplicationCable::Channel
4
+ rescue_from StandardError, with: :report_error
5
+
6
+ def subscribed
7
+ stream_for "chat_#{params[:room]}"
8
+ end
9
+
10
+ private
11
+ def report_error(e)
12
+ # Rollbar.error(e)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,6 +6,8 @@ module Glib::Json::Libs
6
6
 
7
7
  helper_method :json_ui_app_bundle_id, :json_ui_app_build_version, :json_ui_app_device_os
8
8
  helper_method :json_ui_app_is_android?, :json_ui_app_is_ios?, :json_ui_app_is_web?
9
+ helper_method :json_ui_redirect_back_or_to
10
+
9
11
  end
10
12
 
11
13
  def json_ui_app_bundle_id
@@ -58,7 +60,7 @@ module Glib::Json::Libs
58
60
  JSON.parse(render_to_string(template, locals: args))
59
61
  end
60
62
 
61
- def glib_ui_redirect_to(url)
63
+ def glib_redirect_to(url)
62
64
  respond_to do |format|
63
65
  format.html do
64
66
  redirect_to url
@@ -75,11 +77,30 @@ module Glib::Json::Libs
75
77
  end
76
78
  end
77
79
 
78
- def glib_json_handle_403
79
- render file: Rails.root.join('public', '404.html'), status: :forbidden
80
+ # The behaviour provided by this convenience method assumes that user is logged in.
81
+ # When accessing a forbidden page, redirects to `user_default_url` because we don't
82
+ # want the user to get confused in the scenario where after logging in,
83
+ # glib_redirect_back_or_to tries to open a page that the user doesn't have access of.
84
+ def glib_handle_403(user_default_url)
85
+ respond_to do |format|
86
+ format.html do
87
+ redirect_to user_default_url
88
+ end
89
+ format.json do
90
+ render json: if glib_json_dialog_mode?
91
+ { onLoad: __glib_error_dialog('Access denied', "Make sure you're logged in with the correct account.") }
92
+ else
93
+ {
94
+ onResponse: {
95
+ action: 'windows/open', url: user_default_url
96
+ }
97
+ }
98
+ end, status: Rails.env.test? ? :forbidden : :ok
99
+ end
100
+ end
80
101
  end
81
102
 
82
- def glib_json_handle_404
103
+ def glib_handle_404
83
104
  raise ActionController::RoutingError.new('Not Found')
84
105
 
85
106
  # if json_ui_activated?
@@ -89,6 +110,69 @@ module Glib::Json::Libs
89
110
  # end
90
111
  end
91
112
 
113
+ REDIRECT_BACK_KEY = :glib_return_to_url
114
+
115
+ def glib_handle_401(sign_in_url)
116
+ if !glib_json_dialog_mode? && request.get?
117
+ session[REDIRECT_BACK_KEY] = url_for(params.to_unsafe_h.merge(format: nil))
118
+ end
119
+
120
+ respond_to do |format|
121
+ format.html do
122
+ redirect_to sign_in_url
123
+ end
124
+ format.json do
125
+ render json: {
126
+ # Handle dialogs_open and windows_open
127
+ glib_json_dialog_mode? ? :onLoad : :onResponse => __glib_error_dialog(
128
+ 'Your session has ended', 'Please refresh the page and re-login.')
129
+ }, status: Rails.env.test? ? :unauthorized : :ok
130
+ end
131
+ end
132
+ end
133
+
134
+ def __delete_redirect_back_url(url)
135
+ redirect_url = session.delete(REDIRECT_BACK_KEY) || url
136
+ end
137
+
138
+ def glib_redirect_back_or_to(url)
139
+ redirect_url = __delete_redirect_back_url(url)
140
+ glib_redirect_to redirect_url
141
+ end
142
+
143
+ def json_ui_redirect_back_or_to(url, json_action)
144
+ redirect_url = __delete_redirect_back_url(url)
145
+ json_action.windows_closeAll onClose: ->(subaction) do
146
+ subaction.windows_open url: redirect_url
147
+ end
148
+ end
149
+
150
+ def glib_json_dialog_mode?
151
+ params[:_dialog].present? # E.g. _dialog=v1
152
+ end
153
+
154
+ def __glib_error_dialog(title, message)
155
+ {
156
+ action: 'dialogs/show',
157
+ # Don't show another dialog, just use the current one since it's a new dialog anyway, which means
158
+ # that it wouldn't contain existing user data.
159
+ updateExisting: glib_json_dialog_mode?,
160
+ title: title,
161
+ body: {
162
+ childViews: [
163
+ {
164
+ "view": "label",
165
+ "text": message
166
+ },
167
+ ],
168
+ "padding": {
169
+ "x": 20,
170
+ "y": 22,
171
+ },
172
+ }
173
+ }
174
+ end
175
+
92
176
  def glib_json_handle_500(exception)
93
177
  if json_ui_activated? && Rails.env.production?
94
178
  Rollbar.error(exception, :use_exception_level_filters => true) if defined?(Rollbar)
@@ -129,7 +213,7 @@ module Glib::Json::Libs
129
213
  after_action :__json_traversal_register_dynamic_text
130
214
  end
131
215
 
132
- def json_libs_skip_json_ui(options)
216
+ def json_libs_skip_json_ui(options = {})
133
217
  prepend_before_action options do
134
218
  params[:_skip_render] = 'true'
135
219
  end
@@ -152,13 +236,25 @@ module Glib::Json::Libs
152
236
  rescue_from ActionController::InvalidAuthenticityToken do |exception|
153
237
  sign_out(:user)
154
238
 
239
+ # respond_to do |format|
240
+ # format.json do
241
+ # render json: {
242
+ # onResponse: {
243
+ # action: 'windows/open-v1',
244
+ # url: url
245
+ # }
246
+ # }
247
+ # end
248
+ # end
249
+
155
250
  respond_to do |format|
251
+ format.html do
252
+ redirect_to sign_in_url
253
+ end
156
254
  format.json do
157
255
  render json: {
158
- onResponse: {
159
- action: 'windows/open-v1',
160
- url: root_url
161
- }
256
+ glib_json_dialog_mode? ? :onLoad : :onResponse => __glib_error_dialog(
257
+ 'Your session has expired', 'Please refresh the page and retry.')
162
258
  }
163
259
  end
164
260
  end
@@ -81,7 +81,7 @@ module Glib::Json::Ui
81
81
 
82
82
  private
83
83
  def __json_ui_vue(hash, options)
84
- renderer_path = options[:renderer_path]
84
+ renderer_path = params[:_skip_custom_render] == 'true' ? 'layouts/json_ui/no_custom' : options[:renderer_path]
85
85
  @__json_ui_orig_page = response.body
86
86
  response.body = render_to_string(
87
87
  template: renderer_path,
@@ -1,5 +1,9 @@
1
1
  module Glib
2
2
  class HomeController < ApplicationController
3
+ prepend_before_action do
4
+ params[:_skip_custom_render] = 'true' if params[:custom_render] != 'true'
5
+ end
6
+
3
7
  if try(:glib_auth_inited?)
4
8
  skip_before_action :glib_load_resource
5
9
  skip_before_action :glib_authorize_resource
@@ -35,6 +39,22 @@ module Glib
35
39
  render path
36
40
  end
37
41
 
42
+ def chat
43
+ chat_params = params[:chat]
44
+
45
+ payload = {
46
+ action: 'lists/append',
47
+ targetId: 'list-1',
48
+ row: {
49
+ template: 'thumbnail', title: chat_params[:user], subtitle: chat_params[:body]
50
+ }
51
+ }
52
+
53
+ Glib::Channel::ChatChannel.broadcast_to("chat_#{chat_params[:room]}", payload)
54
+
55
+ render template: 'json_ui/garage/empty'
56
+ end
57
+
38
58
  def init_orders
39
59
  @order_headings = {}
40
60
  @orders = params[:orders] || []
@@ -31,6 +31,7 @@ class Glib::JsonUi::ActionBuilder
31
31
  string :fullscreen # mobile, always
32
32
  length :width
33
33
  bool :closeOnBlur
34
+ bool :updateExisting
34
35
 
35
36
  # def initialize(json, page)
36
37
  # @json = json
@@ -0,0 +1,8 @@
1
+ class Glib::JsonUi::ActionBuilder
2
+ module Fields
3
+ class Reset < Action
4
+ string :targetId
5
+ action :onReset
6
+ end
7
+ end
8
+ end
@@ -124,6 +124,21 @@ module Glib
124
124
  end
125
125
  end
126
126
 
127
+ module Labels
128
+ class Set < Action
129
+ string :targetId
130
+ string :text
131
+ action :onSet
132
+ end
133
+ end
134
+
135
+ module Lists
136
+ class Append < Action
137
+ string :targetId
138
+ hash :row
139
+ end
140
+ end
141
+
127
142
  # FUTURE
128
143
  module Data
129
144
  class Save < Action
@@ -10,6 +10,15 @@ module Glib
10
10
  )
11
11
  end
12
12
 
13
+ def glib_chat_url(options = {})
14
+ Glib::Web::Engine.routes.url_helpers.chat_url(options.merge(
15
+ protocol: request.protocol,
16
+ host: request.host,
17
+ port: request.port,
18
+ _render: params[:_render], format: params[:format])
19
+ )
20
+ end
21
+
13
22
  def json_ui_garage_current_url(options = {})
14
23
  json_ui_garage_url(options.merge(path: params[:path]))
15
24
  end
@@ -89,6 +98,18 @@ module Glib
89
98
  # @generic_content_builder = GenericBuilders::Content.new(json, self, @view_builder)
90
99
  end
91
100
 
101
+ def actionCable(options = {})
102
+ json.actionCable do
103
+ if (on_error = options[:onError])
104
+ json.onError do
105
+ on_error.call(@action_builder)
106
+ end
107
+ end
108
+
109
+ json.channels options[:channels]
110
+ end
111
+ end
112
+
92
113
  def content_builder(panelNames)
93
114
  # NOTE: Can potentially be cached
94
115
  builder = GenericBuilders::Content.new(json, self, @view_builder)
@@ -263,6 +263,16 @@ class Glib::JsonUi::ViewBuilder
263
263
  hash :infoSpec
264
264
  end
265
265
 
266
+ class MultipleUpload < AbstractField
267
+ hash :accepts
268
+ array :files
269
+ string :directUploadUrl
270
+ string :title
271
+ string :subtitle
272
+ string :uploadTitle
273
+ string :uploadFailedText
274
+ end
275
+
266
276
  # TODO
267
277
  # class MultiImage < Text
268
278
  # # file_rules = { fileType: 'image/*', maxFileSize: 5000 }
@@ -66,6 +66,20 @@ section.rows builder: ->(template) do
66
66
  action.dialogs_open fullscreen: 'mobile', url: json_ui_garage_url(path: 'forms/basic', mode: 'dialog')
67
67
  end
68
68
 
69
+ if !Rails.env.test? # Prevent test failure
70
+ template.thumbnail title: 'dialogs/open (page with error)', onClick: ->(action) do
71
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/non_existent', mode: 'dialog')
72
+ end
73
+ end
74
+
75
+ template.thumbnail title: 'dialogs/open (page with dialogs/close)', onClick: ->(action) do
76
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_close', mode: 'dialog')
77
+ end
78
+
79
+ template.thumbnail title: 'dialogs/open (page with dialogs/show with updateExisting)', onClick: ->(action) do
80
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_update', mode: 'dialog')
81
+ end
82
+
69
83
  template.thumbnail title: 'dialogs/oauth', onClick: ->(action) do
70
84
  if respond_to?(:user_facebook_omniauth_authorize_url)
71
85
  provider = {
@@ -5,7 +5,10 @@ markdown = '## Emphasis' + "\n" +
5
5
  "\n" +
6
6
  '~~Strikethrough~~' + "\n"
7
7
 
8
- action.send "dialogs_#{dialog_mode}", showClose: true, content: ->(dialog) do
8
+ options = {
9
+ updateExisting: true
10
+ }
11
+ action.send "dialogs_#{dialog_mode}", **options, content: ->(dialog) do
9
12
  dialog.body padding: glib_json_padding_body, childViews: ->(body) do
10
13
  body.markdown text: markdown
11
14
 
@@ -0,0 +1,3 @@
1
+ json_ui_response json do |action|
2
+ # do nothing
3
+ end
@@ -0,0 +1,14 @@
1
+ json.title 'Forms'
2
+
3
+ page = json_ui_page json
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ page.scroll childViews: ->(scroll) do
7
+ scroll.label text: 'This content will be replaced'
8
+ end
9
+
10
+ page.on load: ->(action) do
11
+ action.dialogs_close onClose: ->(subaction) do
12
+ subaction.windows_open url: json_ui_garage_url(path: 'home/blank')
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ json.title 'Forms'
2
+
3
+ page = json_ui_page json
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ page.scroll childViews: ->(scroll) do
7
+ scroll.label text: 'This content will be replaced'
8
+ end
9
+
10
+ page.on load: ->(action) do
11
+ render 'json_ui/garage/actions/dialogs_show', json: json, action: action, dialog_mode: :show
12
+ end
@@ -1,5 +1,4 @@
1
1
  json.title 'Forms'
2
- # json.disableDirtyPrompt true
3
2
 
4
3
  data = params[:user] || {}
5
4
 
@@ -36,5 +36,17 @@ page.form options.merge(childViews: ->(form) do
36
36
  # form.fields_multiImage name: 'user[photos][]', width: 'matchParent', label: 'Avatar', accepts: rules, directUploadUrl: rails_direct_uploads_url,
37
37
  # placeholderView: { type: 'avatar', width: 100, height: 100, url: 'data:image/jpeg;base64,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' }
38
38
 
39
+ form.spacer height: 16
40
+ form.fields_multipleUpload \
41
+ name: 'user[multi][]',
42
+ directUploadUrl: rails_direct_uploads_url,
43
+ title: 'Select file or drag and drop here',
44
+ subtitle: 'JPG, PNG or PDF, file size no more than 10MB',
45
+ uploadTitle: 'File added:',
46
+ uploadFailedText: '(UPLOAD FAILED)',
47
+ files: [
48
+ { name: 'File (Example)', signed_id: ActiveStorage::Attachment.last&.signed_id }
49
+ ]
50
+ form.spacer height: 16
39
51
  form.fields_submit text: 'Submit'
40
52
  end)
@@ -1,114 +1,68 @@
1
- json.title 'ActionCable Real-time Update'
1
+ room = params[:room]
2
2
  page = json_ui_page json
3
3
 
4
- online_channel = 'OnlineChannel'
5
- typing_channel = 'IsTypingChannel'
6
- first_user = User.first
7
- second_user = User.offset(1).first
8
- # Implement a page that shows how ActionCable works in json_ui
4
+ random_key = SecureRandom.hex(3)
5
+ user = "randomuser##{random_key}"
9
6
 
10
- # 1. Example for list
11
- # column.panels_list actionCable: socket_config, width: 'matchParent', firstSection: ->(section) do
12
- # section.rows objects: @messages, builder: -> (row, message, index) do
13
- # render 'conversations/message', row: row, message: message, user: current_user
14
- # end
15
- # end
7
+ json.title "User: #{user}"
16
8
 
17
- # page.form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', padding: glib_json_padding_body, childViews: ->(form) do
18
- # form.fields_textarea \
19
- # width: 'matchParent',
20
- # label: 'Message',
21
- # onKeyUp: ->(action) do
22
- # action.cables_push channel: 'isTypingChannel', data: { conversationId: 1, userId: 1 }
23
- # end
24
- # end
25
-
26
-
27
- # 3. Example for online status
28
-
29
- # put on app/channels/online_channel.rb
30
- # class OnlineChannel < Glib::Channel::OnlineChannel
31
- # self.channel_name = 'OnlineChannel'
32
- # end
33
-
34
- page.on load: ->(action) do
35
- action.timeouts_set interval: 1000, repeat: true, onTimeout: ->(subaction) do
36
- subaction.cables_push channel: online_channel, event: 'online_status', payload: { status: true, user_id: first_user.id }
37
- end
9
+ if room.present?
10
+ page.actionCable \
11
+ channels: [
12
+ {
13
+ name: 'Glib::Channel::AppearanceChannel',
14
+ options: { targetId: 'label-1', room: room }
15
+ },
16
+ {
17
+ name: 'Glib::Channel::ChatChannel',
18
+ options: { targetId: 'list-1', room: room }
19
+ }
20
+ ],
21
+ onError: ->(action) do
22
+ action.labels_set targetId: 'label-1', text: "Room ##{room.upcase} (OFF)"
23
+ end
38
24
  end
39
25
 
40
- # 4. Example for typing status
41
-
42
- # put on app/channels/is_typing_channel.rb
43
- # class IsTypingChannel < Glib::Channel::IsTypingChannel
44
- # self.channel_name = 'IsTypingChannel'
45
- # end
46
-
47
26
  page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
48
27
 
49
- scroll.panels_split width: 'matchParent', content: ->(content) do
50
- content.left childViews: ->(left) do
51
- online_socket_config = {
52
- channel: online_channel,
53
- filterKey: second_user.id,
54
- params: {
55
- conversation: 2
56
- }
57
- }
58
- left.label actionCable: online_socket_config, text: ' '
59
-
60
- left.fields_textarea \
61
- width: 440,
62
- label: "Messages from #{first_user.full_name}",
63
- onTypeStart: lambda { |action|
64
- action.cables_push \
65
- channel: typing_channel, event: 'typing',
66
- payload: { status: true, user_id: first_user.id }
67
- },
68
- onTypeEnd: lambda { |action|
69
- action.cables_push \
70
- channel: typing_channel,
71
- event: 'typing',
72
- payload: { status: false, user_id: first_user.id }
73
- }
74
- left.spacer height: 10
28
+ if room.present?
29
+ scroll.panels_form url: glib_chat_url, width: 'matchParent', height: 'matchParent', method: 'POST', childViews: ->(form) do
30
+ form.fields_hidden name: 'chat[room]', value: room
31
+ form.fields_hidden name: 'chat[user]', value: user
75
32
 
76
- socket_config = {
77
- channel: typing_channel,
78
- filterKey: first_user.id,
79
- params: {
80
- conversation: 2
81
- }
82
- }
83
- left.label actionCable: socket_config, text: ' '
84
- end
33
+ form.p id: 'label-1', text: "Room ##{room.upcase}"
85
34
 
86
- content.right childViews: ->(right) do
87
- right.label text: ''
88
- right.fields_textarea \
89
- width: 440,
90
- label: "Messages from #{second_user.full_name}",
91
- onTypeStart: lambda { |action|
92
- action.cables_push \
93
- channel: typing_channel, event: 'typing',
94
- payload: { status: true, user_id: second_user.id }
95
- },
96
- onTypeEnd: lambda { |action|
97
- action.cables_push \
98
- channel: typing_channel,
99
- event: 'typing',
100
- payload: { status: false, user_id: second_user.id }
101
- }
102
- right.spacer height: 10
35
+ form.panels_list width: 'matchParent', height: 'matchParent', id: 'list-1', sections: [
36
+ ->(section) do
37
+ section.rows builder: ->(template) do
38
+ template.thumbnail title: 'System', subtitle: 'Feel free to discuss anything here.'
39
+ end
103
40
 
104
- socket_config = {
105
- channel: typing_channel,
106
- filterKey: second_user.id,
107
- params: {
108
- conversation: 2
109
- }
110
- }
111
- right.label actionCable: socket_config, text: ' '
41
+ section.footer childViews: ->(footer) do
42
+ form.fields_text \
43
+ name: 'chat[body]',
44
+ width: 'matchParent',
45
+ onTypeStart: ->(action) do
46
+ action.cables_push \
47
+ event: 'status',
48
+ channel: 'Glib::Channel::AppearanceChannel',
49
+ payload: { text: "#{user} is typing", room: room }
50
+ end,
51
+ onTypeEnd: ->(action) do
52
+ action.cables_push \
53
+ event: 'status',
54
+ channel: 'Glib::Channel::AppearanceChannel',
55
+ payload: { text: "Room ##{room.upcase}", room: room }
56
+ end
57
+ end
58
+ end
59
+ ]
112
60
  end
61
+
62
+ else
63
+ scroll.button text: 'Goto room', onClick: ->(action) { action.windows_open url: json_ui_garage_url(path: 'notifications/action_cable', room: random_key) }
64
+ scroll.spacer height: 8
65
+ scroll.label text: 'Or you can ask other dev for room (by copying the url)'
113
66
  end
67
+
114
68
  end
@@ -0,0 +1,5 @@
1
+ <% content_for :head do %>
2
+ <% end %>
3
+
4
+ <% content_for :header do %>
5
+ <% end %>
@@ -9,8 +9,6 @@
9
9
  <%= csrf_meta_tags %>
10
10
 
11
11
  <%= vite_javascript_tag 'vue_renderer', defer: true %>
12
- <%#= javascript_include_tag 'vue_renderer_extras', defer: true %>
13
-
14
12
  <%= vite_stylesheet_tag 'vue_renderer' %>
15
13
  <%# TODO: Remove this, for dev only %>
16
14
  <%# <script src="https://cdn.tailwindcss.com"></script> %>
data/config/routes.rb CHANGED
@@ -4,5 +4,6 @@ Glib::Web::Engine.routes.draw do
4
4
  post 'json_ui_garage', to: 'home#json_ui_garage'
5
5
  patch 'json_ui_garage', to: 'home#json_ui_garage'
6
6
  delete 'json_ui_garage', to: 'home#json_ui_garage'
7
+ post 'chat', to: 'home#chat'
7
8
  end
8
9
  end
@@ -11,9 +11,9 @@ module Glib
11
11
  crawl left_drawer['body']&.[]('childViews')
12
12
  end
13
13
 
14
- if (on_load = (args.fetch('onLoad', nil)))
15
- perform(on_load)
16
- end
14
+ # if (on_load = (args.fetch('onLoad', nil)))
15
+ # perform(on_load)
16
+ # end
17
17
  end
18
18
  end
19
19
  end
@@ -7,9 +7,8 @@ module Glib
7
7
 
8
8
  VALID_RESPONSE_CODES = [
9
9
  (200..299).to_a,
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
10
+ 401, ## UNAUTHORIZED Should be used for not-logged-in
11
+ 403, ## FORBIDDEN Should be used for logged-in but not allowed to access
13
12
  ].flatten
14
13
 
15
14
  def initialize(context, user, router)
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: 3.12.0
4
+ version: 3.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -72,6 +72,8 @@ executables: []
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
+ - app/channels/glib/channel/appearance_channel.rb
76
+ - app/channels/glib/channel/chat_channel.rb
75
77
  - app/channels/glib/channel/is_typing_channel.rb
76
78
  - app/channels/glib/channel/online_channel.rb
77
79
  - app/controllers/concerns/glib/analytics/funnel.rb
@@ -95,6 +97,7 @@ files:
95
97
  - app/helpers/glib/json_ui/action_builder/commands.rb
96
98
  - app/helpers/glib/json_ui/action_builder/components.rb
97
99
  - app/helpers/glib/json_ui/action_builder/dialogs.rb
100
+ - app/helpers/glib/json_ui/action_builder/fields.rb
98
101
  - app/helpers/glib/json_ui/action_builder/http.rb
99
102
  - app/helpers/glib/json_ui/action_builder/iap.rb
100
103
  - app/helpers/glib/json_ui/action_builder/panels.rb
@@ -148,6 +151,7 @@ files:
148
151
  - app/views/json_ui/garage/actions/dialogs_oauth_post.json.jbuilder
149
152
  - app/views/json_ui/garage/actions/index.json.jbuilder
150
153
  - app/views/json_ui/garage/actions/partial_update.json.jbuilder
154
+ - app/views/json_ui/garage/empty.json.jbuilder
151
155
  - app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder
152
156
  - app/views/json_ui/garage/forms/_conditional_banner.json.jbuilder
153
157
  - app/views/json_ui/garage/forms/_partial_update_execute.json.jbuilder
@@ -156,6 +160,8 @@ files:
156
160
  - app/views/json_ui/garage/forms/basic_post.json.jbuilder
157
161
  - app/views/json_ui/garage/forms/checkboxes.json.jbuilder
158
162
  - app/views/json_ui/garage/forms/conditional_value.json.jbuilder
163
+ - app/views/json_ui/garage/forms/dialogs_close.json.jbuilder
164
+ - app/views/json_ui/garage/forms/dialogs_update.json.jbuilder
159
165
  - app/views/json_ui/garage/forms/dirty_prompt.json.jbuilder
160
166
  - app/views/json_ui/garage/forms/dynamic_group.json.jbuilder
161
167
  - app/views/json_ui/garage/forms/dynamic_select.json.jbuilder
@@ -269,6 +275,7 @@ files:
269
275
  - app/views/json_ui/garage/views/shareButton.json.jbuilder
270
276
  - app/views/json_ui/garage/views/steppers.json.jbuilder
271
277
  - app/views/json_ui/garage/views/texts.json.jbuilder
278
+ - app/views/layouts/json_ui/no_custom.html.erb
272
279
  - app/views/layouts/json_ui/renderer.html.erb
273
280
  - config/routes.rb
274
281
  - lib/generators/glib/install_generator.rb