rsence-pre 2.1.0.21 → 2.1.8.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.
Files changed (43) hide show
  1. data/INSTALL.rdoc +61 -46
  2. data/README.rdoc +17 -1
  3. data/VERSION +1 -1
  4. data/conf/rsence_command_strings.yaml +16 -16
  5. data/js/comm/sessionwatcher/sessionwatcher.js +5 -4
  6. data/js/comm/transporter/transporter.js +62 -4
  7. data/js/comm/values/values.js +62 -0
  8. data/js/controls/button/themes/default/button.css +7 -7
  9. data/js/controls/imageview/imageview.js +15 -6
  10. data/js/controls/stringview/stringview.js +16 -2
  11. data/js/controls/textcontrol/textcontrol.js +56 -3
  12. data/js/core/elem/elem.js +38 -12
  13. data/js/datetime/timesheet/timesheet.js +141 -32
  14. data/js/datetime/timesheet_item/timesheet_item.js +82 -22
  15. data/js/foundation/application/application.js +10 -4
  16. data/js/foundation/control/control.js +5 -3
  17. data/js/foundation/control/dyncontrol/dyncontrol.js +17 -3
  18. data/js/foundation/control/eventresponder/eventresponder.js +31 -2
  19. data/js/foundation/eventmanager/eventmanager.js +202 -74
  20. data/js/foundation/json_renderer/json_renderer.js +5 -2
  21. data/js/foundation/system/system.js +13 -11
  22. data/js/foundation/view/morphanimation/morphanimation.js +9 -5
  23. data/js/foundation/view/view.js +22 -10
  24. data/js/lists/propertylist/propertylist.js +5 -0
  25. data/js/menus/minimenu/minimenu.js +3 -8
  26. data/lib/conf/default.rb +0 -3
  27. data/lib/http/broker.rb +6 -5
  28. data/lib/http/rackup.rb +3 -3
  29. data/lib/http/response.rb +28 -2
  30. data/lib/session/msg.rb +30 -18
  31. data/lib/transporter/transporter.rb +4 -0
  32. data/lib/values/hvalue.rb +4 -134
  33. data/lib/values/valuemanager.rb +36 -22
  34. data/plugins/client_pkg/lib/client_pkg_serve.rb +195 -152
  35. data/plugins/main/main.rb +8 -10
  36. data/plugins/ticket/lib/common.rb +4 -4
  37. data/plugins/ticket/lib/favicon.rb +1 -1
  38. data/plugins/ticket/lib/rsrc.rb +1 -1
  39. data/plugins/ticket/lib/upload.rb +2 -2
  40. data/plugins/ticket/ticket.rb +3 -3
  41. data/setup/welcome/gui/welcome.yaml +1 -1
  42. metadata +10 -11
  43. data/lib/util/ruby19_fixes.rb +0 -18
data/lib/conf/default.rb CHANGED
@@ -13,9 +13,6 @@ require 'yaml'
13
13
 
14
14
 
15
15
 
16
- require 'util/ruby19_fixes' if RUBY_VERSION.to_f >= 1.9
17
-
18
-
19
16
  module RSence
20
17
 
21
18
 
data/lib/http/broker.rb CHANGED
@@ -24,7 +24,7 @@ class Broker
24
24
 
25
25
  # This method is called from Rack.
26
26
  # @param [Hash] env is the Rack environment.
27
- # @return [Array(Number, Hash, String)] Rack-style response status, header, body
27
+ # @return [Array(Number, Hash, Array)] Rack-style response status, header, body
28
28
  def call( env )
29
29
  sleep @@ping_sim if @@ping_sim
30
30
  unless @@transporter.online?
@@ -35,7 +35,7 @@ class Broker
35
35
  'Refresh' => "2; #{env['REQUEST_URI']}",
36
36
  'Content-Length' => '4'
37
37
  }
38
- return [ 503, headers, 'BUSY' ]
38
+ return [ 503, headers, ['BUSY'] ]
39
39
  end
40
40
  request = Request.new(env)
41
41
  response = Response.new
@@ -43,8 +43,9 @@ class Broker
43
43
  dispatcher = dispatcher_class.new( request, response )
44
44
  dispatcher.send( request_method )
45
45
  content_type = dispatcher.content_type
46
- response.header['Content-Length'] = response.body.length.to_s unless response.header.has_key?('Content-Length')
47
- return [response.status, response.header, response.body]
46
+ response_body = response.body
47
+ response.header['Content-Length'] = response.body_bytes unless response.header.has_key?('Content-Length')
48
+ return [response.status, response.header, response_body]
48
49
  end
49
50
 
50
51
  # Returns a dynamically created "REST Dispatcher" kind of class that has
@@ -121,7 +122,7 @@ class Broker
121
122
  @response.status = 404
122
123
  err404 = '<html><head><title>404 - Page Not Found</title></head><body>404 - Page Not Found</body></html>'
123
124
  @response['Content-Type'] = 'text/html; charset=UTF-8'
124
- @response['Content-Length'] = err404.length.to_s
125
+ @response['Content-Length'] = err404.bytesize.to_s
125
126
  @response.body = err404
126
127
  end
127
128
 
data/lib/http/rackup.rb CHANGED
@@ -74,7 +74,7 @@ module Broker
74
74
  else
75
75
  puts "unsupported method: #{request_method.inspect}"
76
76
  end
77
- response.header['Content-Length'] = response.body.length.to_s unless response.header.has_key?('Content-Length')
77
+ response.header['Content-Length'] = response.body.bytesize.to_s unless response.header.has_key?('Content-Length')
78
78
  return [response.status, response.header, response.body]
79
79
  end
80
80
 
@@ -82,8 +82,8 @@ module Broker
82
82
  puts "/404: #{request.fullpath.inspect}" if $DEBUG_MODE
83
83
  response.status = 404
84
84
  err404 = '<html><head><title>404 - Page Not Found</title></head><body>404 - Page Not Found</body></html>'
85
- response['content-type'] = 'text/html; charset=UTF-8'
86
- response['content-length'] = err404.length.to_s
85
+ response['Content-Type'] = 'text/html; charset=UTF-8'
86
+ response['Content-Length'] = err404.bytesize.to_s
87
87
  response.body = err404
88
88
  end
89
89
 
data/lib/http/response.rb CHANGED
@@ -17,6 +17,21 @@ module RSence
17
17
  # Adds the + method "operator" to an extended Array.
18
18
  # Used for pushing http body data.
19
19
  class ResponseBody < Array
20
+
21
+ def push( body_data )
22
+ super( sanitize_body_data( body_data ) )
23
+ end
24
+ def sanitize_body_data( body_data )
25
+ if body_data.class == String or body_data.class == GZString
26
+ return body_data
27
+ elsif body_data.respond_to?(:to_s)
28
+ warn "WARNING: RSence::Response::ResponseBody -> body_data is not a string. It's a #{body_data.class}, with the following contents: #{body_data.inspect}" if RSence.args[:verbose]
29
+ return body_data.to_s
30
+ else
31
+ warn "Invalid response data: #{body_data.inspect[0..100]}"
32
+ return ''
33
+ end
34
+ end
20
35
  def +(body_data)
21
36
  self.push(body_data)
22
37
  end
@@ -33,10 +48,21 @@ module RSence
33
48
  end
34
49
  def body=(body_data)
35
50
  @body = ResponseBody.new(1)
36
- @body[0] = body_data
51
+ @body[0] = @body.sanitize_body_data( body_data )
37
52
  end
38
53
  def body
39
- @body.join
54
+ @body
55
+ end
56
+ def body_bytes
57
+ bytes = 0
58
+ @body.each do |part|
59
+ if part.respond_to?(:to_s)
60
+ bytes += part.to_s.bytesize
61
+ else
62
+ warn "body data part does not respond to to_s: #{part.inspect[0..100]}"
63
+ end
64
+ end
65
+ return bytes.to_s
40
66
  end
41
67
  def content_type=(new_content_type)
42
68
  @header['Content-Type'] = new_content_type
data/lib/session/msg.rb CHANGED
@@ -111,7 +111,11 @@ module RSence
111
111
  @options = options
112
112
 
113
113
  # Value response output.
114
- @value_buffer = []
114
+ @value_buffer = {
115
+ :new => [],
116
+ :set => [],
117
+ :del => []
118
+ }
115
119
 
116
120
  # The session key placeholder.
117
121
  @ses_key = false
@@ -131,7 +135,7 @@ module RSence
131
135
  if options[:servlet]
132
136
  @do_gzip = false
133
137
  else
134
- @response.content_type = 'text/javascript; charset=utf-8'
138
+ @response['Content-Type'] = 'text/javascript; charset=utf-8'
135
139
  @response['Cache-Control'] = 'no-cache'
136
140
 
137
141
  # gnu-zipped responses:
@@ -238,21 +242,22 @@ module RSence
238
242
  if not @response_success
239
243
  @response.status = 200
240
244
  #@response.status = 503
241
-
245
+
242
246
  buffer = [
243
- "" # empty session key will stop the syncing
247
+ "", # empty session key will stop the syncing
248
+ {}, # no session values
244
249
  ] + @error_js
245
250
  else
246
251
  ## The response status should always be 200 (OK)
247
252
  @response.status = 200
248
-
249
- buffer = @value_buffer + @buffer
250
- if @ses_key
251
- buffer.unshift( @ses_key )
252
- end
253
-
253
+
254
+ buffer = [
255
+ @ses_key,
256
+ @value_buffer,
257
+ ] + @buffer
258
+
254
259
  end
255
-
260
+
256
261
  # flush the output
257
262
  if @do_gzip
258
263
  outp = GZString.new('')
@@ -262,13 +267,13 @@ module RSence
262
267
  else
263
268
  outp = buf_json(buffer)
264
269
  end
265
-
266
- @response['content-length'] = outp.size
270
+
271
+ @response['Content-Length'] = outp.bytesize.to_s
267
272
  @response.body = outp
268
-
273
+
269
274
  @response_sent = true
270
275
  end
271
-
276
+
272
277
  # Sends data to the client, usually javascript, but is valid for any data that responds to #to_json
273
278
  # @param [String<js>, #to_json] data Javascript source or object that responds to #to_json
274
279
  # @param [Boolean] dont_squeeze When true, doesn't `squeeze` the contents (jsmin + jscompress)
@@ -280,9 +285,16 @@ module RSence
280
285
  end
281
286
 
282
287
  # @private For value manager; insert changed values BEFORE other js.
283
- def reply_value(data)
284
- puts data if @config[:trace]
285
- @value_buffer.push( data )
288
+ def reply_value( operation_type, value_id, data=nil )
289
+ if operation_type == :set
290
+ @value_buffer[:set].push( [ value_id, data ] )
291
+ elsif operation_type == :new
292
+ @value_buffer[:new].push( [ value_id, data ] )
293
+ elsif operation_type == :del
294
+ @value_buffer[:del].push( value_id )
295
+ else
296
+ throw "Invalid reply_value operation: operation_type: #{operation_type.inspect}, value_id: #{value_id.inspect}, data: #{data.inspect}"
297
+ end
286
298
  end
287
299
 
288
300
  # Sends data to the client's javascript console.
@@ -229,6 +229,10 @@ module RSence
229
229
  end
230
230
 
231
231
  elsif msg.refresh_page?( @plugins.incr ) and @config[:client_autoreload]
232
+ while msg.refresh_page?( @plugins.incr )
233
+ msg.session[:plugin_incr] == @plugins.incr
234
+ sleep 0.5
235
+ end
232
236
  # Forces the client to reload, if plugins are incremented
233
237
  msg.reply("window.location.reload( true );")
234
238
  end
data/lib/values/hvalue.rb CHANGED
@@ -84,7 +84,7 @@ module RSence
84
84
  if RSence.args[:debug] and meta[:name] and not msg.valuemanager.id_exists?( msg, meta[:name] )
85
85
  @value_id = meta[:name]
86
86
  else
87
- @value_id = msg.valuemanager.randgen.gen
87
+ @value_id = msg.valuemanager.ses_unique_id( msg )
88
88
  end
89
89
 
90
90
  @meta = meta
@@ -245,12 +245,11 @@ module RSence
245
245
  def to_client( msg )
246
246
  if @is_new_to_client
247
247
  ## Initialize a new client value
248
- init_str = "COMM.Values.create(#{@value_id.to_json},#{@data.to_json});"
249
- msg.reply_value( init_str )
248
+ msg.reply_value( :new, @value_id, @data )
250
249
  @is_new_to_client = false
251
250
  else
252
251
  ## Sets the client value
253
- msg.reply_value "HVM.s(#{@value_id.to_json},#{@data.to_json});"
252
+ msg.reply_value( :set, @value_id, @data )
254
253
  end
255
254
  end
256
255
 
@@ -267,142 +266,13 @@ module RSence
267
266
  session_values.delete( @value_id )
268
267
 
269
268
  if msg and not @is_new_to_client
270
- msg.reply_value("HVM.del(#{@value_id.to_json});")
269
+ msg.reply_value( :del, @value_id )
271
270
  end
272
271
  end
273
272
  alias die die!
274
273
 
275
274
  end
276
275
 
277
-
278
- =begin
279
- class UploadValue < HValue
280
-
281
- @state_responders = {
282
- :ready => [], # id == 0
283
- :started => [], # id == 1
284
- :process => [], # id == 2 ; also uses bind
285
- 3 => [], # id == 3
286
- 4 => [], # id == 4
287
- :error => [] # id < 0
288
- }
289
-
290
- @upload_state = 0
291
- @upload_key = ''
292
- @uploads = []
293
-
294
- # the data should contain both state and key in the value
295
- def from_client( msg, data )
296
-
297
- ## change the valid state, because the value was set by the client!
298
- @is_valid = data.include?(':::')
299
-
300
- # the state and key are separated by the ':::' delimiter string
301
- if @is_valid
302
-
303
- # split state and key using the delimiter
304
- (upload_state, upload_key) = data.split(':::')
305
-
306
- # the state is a number
307
- upload_state = upload_state.to_i
308
-
309
- @upload_state = upload_state
310
- @upload_key = upload_key
311
-
312
- # negative states are errors
313
- if upload_state < 0
314
- # "upload error: #{upload_state}"
315
- # (parse the error)
316
- unless @state_responders[:error].empty?
317
- @state_responders[:error].each do |plugin_name,method_name|
318
- msg.run( plugin_name,method_name,msg,self,upload_state )
319
- end
320
- end
321
-
322
- # the default state, 0 means the UI is ready to send an
323
- # upload and ticketserve is ready to receive it
324
- elsif upload_state == 0
325
- # "upload state: ready to upload."
326
- # (do nothing)
327
-
328
- unless @state_responders[:ready].empty?
329
- @state_responders[:ready].each do |plugin_name,method_name|
330
- msg.run( plugin_name,method_name,msg,self,upload_state )
331
- end
332
- end
333
-
334
- # this state means the upload's transfer is started and progressing
335
- elsif upload_state == 1
336
- # "upload state: upload started."
337
- # (show progress bar)
338
-
339
- unless @state_responders[:started].empty?
340
- @state_responders[:started].each do |plugin_name,method_name|
341
- msg.run( plugin_name,method_name,msg,self,upload_state )
342
- end
343
- end
344
-
345
- # this state means the upload's transfer is complete,
346
- # but the uploaded data hasn't been handled yet.
347
- elsif upload_state == 2
348
- # "upload state: waiting to process."
349
-
350
- uploads = msg.plugins[:ticketservices].get_uploads(upload_key,true)
351
- if uploads.size == 1
352
- uploaded_data = uploads[0]
353
-
354
- # only process changes, if different from the one already stored.
355
- if uploaded_data != @data
356
-
357
- @data = uploaded_data
358
-
359
- ## add the id to the values to be checked
360
- check_ids = msg.session[:values][:check]
361
- unless check_ids.include?( @value_id )
362
- check_ids.push( @value_id )
363
- end
364
-
365
- end
366
- msg.plugins[:ticketservices].del_uploads(upload_key,msg.ses_id)
367
- else
368
- # "upload, amount of uploads: #{uploads.size}"
369
- end
370
-
371
- #
372
- hvalue.set(msg,"3:::#{upload_key}")
373
-
374
- msg.console( "upload state: set to ack" )
375
-
376
- elsif upload_state == 3
377
- # "upload state: waiting for user ack."
378
- # (do nothing)
379
-
380
- msg.console( "upload state: waiting user ack" )
381
-
382
-
383
- elsif upload_state == 4
384
- # "upload state: user wants to upload again."
385
- # (set a new upload key, )
386
-
387
- msg.console( "upload state: ack, getting new key" )
388
-
389
-
390
- setup_upload( msg, hvalue )
391
-
392
-
393
- else
394
- # "upload unknown state: #{upload_state.inspect}"
395
- end
396
- end
397
- return true
398
- end
399
- def setup_upload(msg,hvalue,size_bytes=500*1024,accept_mime=/image\/(.*?)/,allow_multi=false)
400
- upload_key = msg.plugins[:ticketservices].upload_key(msg,hvalue.val_id,size_bytes,accept_mime,allow_multi)
401
- hvalue.set( msg, upload_key )
402
- end
403
- end
404
- =end
405
-
406
276
  end
407
277
 
408
278
 
@@ -35,6 +35,40 @@ module RSence
35
35
 
36
36
  end
37
37
 
38
+
39
+ # @private Returns a session-unique random string
40
+ def ses_unique_id( msg )
41
+ new_id = randgen.gen while id_exists?( msg, new_id )
42
+ return new_id
43
+ end
44
+
45
+
46
+ # @private Regenerate a value id
47
+ def reshuffle_id( msg, ses_values, val_obj, old_id )
48
+
49
+ new_id = ses_unique_id( msg )
50
+
51
+ # replace the old id in the hvalue itself
52
+ val_obj.val_id = new_id
53
+
54
+ # re-associate the value with the new id
55
+ ses_values[:by_id][new_id] = val_obj
56
+ ses_values[:by_id].delete(old_id)
57
+
58
+ # replace the id in the unvalidated values (:check) array
59
+ if ses_values[:check].include?(old_id)
60
+ old_idx = ses_values[:check].index(old_id)
61
+ ses_values[:check][old_idx] = new_id
62
+ end
63
+
64
+ # replace the id in the unsynchronized values (:sync) array
65
+ if ses_values[:sync].include?(old_id)
66
+ old_idx = ses_values[:sync].index(old_id)
67
+ ses_values[:sync][old_idx] = new_id
68
+ end
69
+ end
70
+
71
+
38
72
  # @private Re-constructs all stored values and sends them to the client.
39
73
  # Used for restoring and cloning session values.
40
74
  def resend_session_values( msg )
@@ -56,28 +90,7 @@ module RSence
56
90
 
57
91
  # make a new id
58
92
  unless RSence.args[:debug] and val_obj.meta[:name]
59
- new_id = @randgen.gen
60
- new_id = @randgen.gen while id_exists?( msg, new_id )
61
-
62
- # replace the old id in the hvalue itself
63
- val_obj.val_id = new_id
64
-
65
- # re-associate the value with the new id
66
- ses_values[:by_id][new_id] = val_obj
67
- ses_values[:by_id].delete(old_id)
68
-
69
- # replace the id in the unvalidated values (:check) array
70
- if ses_values[:check].include?(old_id)
71
- old_idx = ses_values[:check].index(old_id)
72
- ses_values[:check][old_idx] = new_id
73
- end
74
-
75
- # replace the id in the unsynchronized values (:sync) array
76
- if ses_values[:sync].include?(old_id)
77
- old_idx = ses_values[:sync].index(old_id)
78
- ses_values[:sync][old_idx] = new_id
79
- end
80
-
93
+ reshuffle_id( msg, ses_values, val_obj, old_id )
81
94
  end
82
95
 
83
96
  # tell the hvalue to send its client-side initialization
@@ -96,6 +109,7 @@ module RSence
96
109
 
97
110
  # @private Verifies new_id is unique.
98
111
  def id_exists?( msg, new_id )
112
+ return true unless new_id.class == String
99
113
  return msg.session[:values][:by_id].has_key?(new_id)
100
114
  end
101
115