Commit 8c25db5a0e1e21c40032405400edb10ccf8fe9e1

Authored by Miguel Barão
1 parent 90115648
Exists in master and in 1 other branch dev

- handle focus/unfocus events

- handle resize event
- report initial screen and window size
- simplified run_script() function in tools.py
perguntations/__init__.py
... ... @@ -32,7 +32,7 @@ proof of submission and for review.
32 32 '''
33 33  
34 34 APP_NAME = 'perguntations'
35   -APP_VERSION = '2020.04.dev2'
  35 +APP_VERSION = '2020.04.dev3'
36 36 APP_DESCRIPTION = __doc__
37 37  
38 38 __author__ = 'Miguel Barão'
... ...
perguntations/app.py
... ... @@ -257,6 +257,17 @@ class App():
257 257 return test
258 258  
259 259 # ------------------------------------------------------------------------
  260 + def event_test(self, uid, cmd, value):
  261 + '''handle browser events the occur during the test'''
  262 + if cmd == 'focus':
  263 + logger.info('Student %s: focus %s', uid, value)
  264 + elif cmd == 'size':
  265 + scr_y, scr_x, win_y, win_x = value
  266 + area = win_x * win_y / (scr_x * scr_y) * 100
  267 + logger.info('Student %s: area=%g%%, window=%dx%d, screen=%dx%d',
  268 + uid, area, win_x, win_y, scr_x, scr_y)
  269 +
  270 + # ------------------------------------------------------------------------
260 271  
261 272 # --- helpers (getters)
262 273 # def get_student_name(self, uid):
... ...
perguntations/serve.py
... ... @@ -42,6 +42,7 @@ class WebApplication(tornado.web.Application):
42 42 (r'/file', FileHandler),
43 43 # (r'/root', MainHandler), # FIXME
44 44 # (r'/ws', AdminSocketHandler),
  45 + (r'/studentwebservice', StudentWebservice),
45 46 (r'/', RootHandler),
46 47 ]
47 48  
... ... @@ -152,13 +153,24 @@ class BaseHandler(tornado.web.RequestHandler):
152 153 # AdminSocketHandler.update_cache(chat) # store msgs
153 154 # AdminSocketHandler.send_updates(chat) # send to clients
154 155  
  156 +class StudentWebservice(BaseHandler):
  157 + '''
  158 + Receive ajax from students in the test:
  159 + focus, unfocus
  160 + '''
  161 +
  162 + @tornado.web.authenticated
  163 + def post(self):
  164 + '''handle ajax post'''
  165 + uid = self.current_user
  166 + cmd = self.get_body_argument('cmd', None)
  167 + value = json.loads(self.get_body_argument('value', None))
  168 + self.testapp.event_test(uid, cmd, value)
155 169  
156 170 # ----------------------------------------------------------------------------
157 171 class AdminHandler(BaseHandler):
158 172 '''Handle /admin'''
159 173  
160   - # SUPPORTED_METHODS = ['GET', 'POST']
161   -
162 174 @tornado.web.authenticated
163 175 @admin_only
164 176 async def get(self):
... ... @@ -405,7 +417,9 @@ class TestHandler(BaseHandler):
405 417  
406 418 # --- REVIEW -----------------------------------------------------------------
407 419 class ReviewHandler(BaseHandler):
408   - # SUPPORTED_METHODS = ['GET']
  420 + '''
  421 + Show test for review
  422 + '''
409 423  
410 424 _templates = {
411 425 'radio': 'review-question-radio.html',
... ... @@ -445,7 +459,6 @@ class ReviewHandler(BaseHandler):
445 459 templ=self._templates)
446 460  
447 461  
448   -
449 462 # ----------------------------------------------------------------------------
450 463 def signal_handler(sig, frame):
451 464 '''
... ...
perguntations/static/js/detect_unfocus.js
  1 +// from: https://www.tornadoweb.org/en/stable/guide/security.html
  2 +// with changes: removed datatype and callback from original postJSON
  3 +function getCookie(name) {
  4 + var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
  5 + return r ? r[1] : undefined;
  6 +}
  7 +
  8 +jQuery.postJSON = function(url, args) {
  9 + args._xsrf = getCookie("_xsrf");
  10 + $.ajax({url: url, data: $.param(args), type: "POST"});
  11 +};
  12 +
  13 +
1 14 $(document).ready(function() {
  15 + $.postJSON("/studentwebservice", {
  16 + "cmd": "size",
  17 + "value": JSON.stringify([screen.height, screen.width, $(window).height(), $(window).width()]),
  18 + });
  19 +
2 20 $(window).focus(function(){
3   - $.ajax({
4   - type: "POST",
5   - url: "/studentwebservice",
6   - data: {
7   - "cmd": "focus",
8   - "number": $("#number").text(),
9   - "value": true
10   - }
  21 + $.postJSON("/studentwebservice", {
  22 + "cmd": "focus",
  23 + "value": true,
11 24 });
12 25 });
13 26  
14   - $(window).blur(function(e){
15   - $.ajax({
16   - type: "POST",
17   - url: "/studentwebservice",
18   - data: {
19   - "cmd": "focus",
20   - "number": $("#number").text(),
21   - "value": false
22   - }
  27 + $(window).blur(function(){
  28 + $.postJSON("/studentwebservice", {
  29 + "cmd": "focus",
  30 + "value": false,
23 31 });
24 32 });
25 33  
26 34 $(window).resize(function(){
27   - var n = $(window).scrollTop();
28   - $.ajax({
29   - type: "POST",
30   - url: "/adminwebservice",
31   - data: {
32   - "cmd": "resize",
33   - "name": $("#number").text(),
34   - "scroll": n
35   - }
  35 + $.postJSON("/studentwebservice", {
  36 + "cmd": "size",
  37 + "value": JSON.stringify([screen.height, screen.width, $(window).height(), $(window).width()]),
36 38 });
  39 +
  40 +
  41 + // // var n = $(window).scrollTop();
  42 + // $.postJSON({"/studentwebservice", {
  43 + // "cmd": "size",
  44 + // "value": JSON.stringify([screen.height, screen.width, $(window).height(), $(window).width()]),
  45 + // }});
  46 + // // data: {
  47 + // // "cmd": "resize",
  48 + // // "name": $("#number").text(),
  49 + // // "scroll": n
  50 + // // }
  51 + // // });
37 52 });
38   -});
39 53 \ No newline at end of file
  54 +
  55 +});
... ...
perguntations/templates/test.html
... ... @@ -38,6 +38,7 @@
38 38 <!-- My scripts -->
39 39 <script defer src="/static/js/question_disabler.js"></script>
40 40 <script defer src="/static/js/prevent_enter_submit.js"></script>
  41 + <script defer src="/static/js/detect_unfocus.js"></script>
41 42 </head>
42 43 <!-- ===================================================================== -->
43 44 <body>
... ...
perguntations/tools.py
... ... @@ -67,21 +67,16 @@ def run_script(script: str,
67 67 stderr=subprocess.STDOUT,
68 68 universal_newlines=True,
69 69 timeout=timeout,
70   - check=False,
  70 + check=True,
71 71 )
72   - except OSError:
73   - logger.error('Can not execute script "%s".', script)
74   - return output
75 72 except subprocess.TimeoutExpired:
76 73 logger.error('Timeout %ds exceeded running "%s".', timeout, script)
77 74 return output
78   - except Exception:
79   - logger.error('An Exception ocurred running "%s".', script)
  75 + except subprocess.CalledProcessError as exc:
  76 + logger.error('Return code %d running "%s".', exc.returncode, script)
80 77 return output
81   -
82   - # --- check return code
83   - if proc.returncode != 0:
84   - logger.error('Return code %d running "%s".', proc.returncode, script)
  78 + except OSError:
  79 + logger.error('Can not execute script "%s".', script)
85 80 return output
86 81  
87 82 # --- parse yaml
... ...