Commit da470fc69ac16b213de6ed508ae84b6d243c70fc
1 parent
a81c2241
Exists in
master
and in
1 other branch
- show browser/screen area and focus state on admin page.
Showing
4 changed files
with
42 additions
and
14 deletions
Show diff stats
perguntations/__init__.py
perguntations/app.py
| ... | ... | @@ -86,6 +86,8 @@ class App(): |
| 86 | 86 | def __init__(self, conf): |
| 87 | 87 | self.online = dict() # {uid: {'student':{...}, 'test': {...}}, ...} |
| 88 | 88 | self.allowed = set() # '0' is hardcoded to allowed elsewhere |
| 89 | + self.unfocus = set() # set of students that have no browser focus | |
| 90 | + self.area = dict() # {uid: percent_area} | |
| 89 | 91 | |
| 90 | 92 | logger.info('Loading test configuration "%s".', conf["testfile"]) |
| 91 | 93 | try: |
| ... | ... | @@ -268,12 +270,12 @@ class App(): |
| 268 | 270 | def event_test(self, uid, cmd, value): |
| 269 | 271 | '''handles browser events the occur during the test''' |
| 270 | 272 | if cmd == 'focus': |
| 271 | - logger.info('"%s": focus %s', uid, value) | |
| 273 | + if value: | |
| 274 | + self.focus_student(uid) | |
| 275 | + else: | |
| 276 | + self.unfocus_student(uid) | |
| 272 | 277 | elif cmd == 'size': |
| 273 | - scr_y, scr_x, win_y, win_x = value | |
| 274 | - area = win_x * win_y / (scr_x * scr_y) * 100 | |
| 275 | - logger.info('"%s": area=%g%%, window=%dx%d, screen=%dx%d', | |
| 276 | - uid, area, win_x, win_y, scr_x, scr_y) | |
| 278 | + self.set_screen_area(uid, value) | |
| 277 | 279 | |
| 278 | 280 | # ------------------------------------------------------------------------ |
| 279 | 281 | # --- GETTERS |
| ... | ... | @@ -374,6 +376,8 @@ class App(): |
| 374 | 376 | 'start_time': self.online.get(uid, {}).get('test', {}) |
| 375 | 377 | .get('start_time', ''), |
| 376 | 378 | 'password_defined': pw != '', |
| 379 | + 'unfocus': uid in self.unfocus, | |
| 380 | + 'area': self.area.get(uid, None), | |
| 377 | 381 | 'grades': self.get_student_grades_from_test( |
| 378 | 382 | uid, self.testfactory['ref']) |
| 379 | 383 | } for uid, name, pw in self.get_all_students()] |
| ... | ... | @@ -406,12 +410,30 @@ class App(): |
| 406 | 410 | def allow_all_students(self): |
| 407 | 411 | '''allow all students to login''' |
| 408 | 412 | logger.info('Allowing all students...') |
| 409 | - self.allowed = set(s[0] for s in self.get_all_students()) | |
| 413 | + self.allowed.update(s[0] for s in self.get_all_students()) | |
| 410 | 414 | |
| 411 | 415 | def deny_all_students(self): |
| 412 | 416 | '''deny all students to login''' |
| 413 | 417 | logger.info('Denying all students...') |
| 414 | - self.allowed = set() | |
| 418 | + self.allowed.clear() | |
| 419 | + | |
| 420 | + def focus_student(self, uid): | |
| 421 | + '''set student in focus state''' | |
| 422 | + self.unfocus.discard(uid) | |
| 423 | + logger.info('"%s" focus', uid) | |
| 424 | + | |
| 425 | + def unfocus_student(self, uid): | |
| 426 | + '''set student in unfocus state''' | |
| 427 | + self.unfocus.add(uid) | |
| 428 | + logger.info('"%s" unfocus', uid) | |
| 429 | + | |
| 430 | + def set_screen_area(self, uid, sizes): | |
| 431 | + '''set current browser area as detected in resize event''' | |
| 432 | + scr_y, scr_x, win_y, win_x = sizes | |
| 433 | + area = win_x * win_y / (scr_x * scr_y) * 100 | |
| 434 | + self.area[uid] = area | |
| 435 | + logger.info('"%s": area=%g%%, window=%dx%d, screen=%dx%d', | |
| 436 | + uid, area, win_x, win_y, scr_x, scr_y) | |
| 415 | 437 | |
| 416 | 438 | async def update_student_password(self, uid, password=''): |
| 417 | 439 | '''change password on the database''' | ... | ... |
perguntations/static/js/admin.js
| ... | ... | @@ -16,11 +16,9 @@ $(document).ready(function() { |
| 16 | 16 | // button handlers (runs once) |
| 17 | 17 | $("#allow_all").click(function() { |
| 18 | 18 | $.postJSON("/admin", {"cmd": "allow_all"}); |
| 19 | - // $(":checkbox").prop("checked", true).trigger('change'); | |
| 20 | 19 | }); |
| 21 | 20 | $("#deny_all").click(function() { |
| 22 | 21 | $.postJSON("/admin", {"cmd": "deny_all"}); |
| 23 | - // $(":checkbox").prop("checked", false).trigger('change'); | |
| 24 | 22 | }); |
| 25 | 23 | $("#reset_password").click(function () { |
| 26 | 24 | $.postJSON("/admin", { |
| ... | ... | @@ -120,7 +118,15 @@ $(document).ready(function() { |
| 120 | 118 | var uid = d['uid']; |
| 121 | 119 | var checked = d['allowed'] ? 'checked' : ''; |
| 122 | 120 | var password_defined = d['password_defined'] ? ' <span class="badge badge-secondary"><i class="fa fa-key" aria-hidden="true"></i></span>' : ''; |
| 123 | - var hora_inicio = d['start_time'] ? ' <span class="badge badge-success">' + d['start_time'].slice(11,19) + '</span>': ''; | |
| 121 | + var hora_inicio = d['start_time'] ? ' <span class="badge badge-success"><i class="fas fa-hourglass-start"></i> ' + d['start_time'].slice(11,16) + '</span>': ''; | |
| 122 | + var unfocus = d['unfocus']? ' <span class="badge badge-danger">unfocus</span>' : ''; | |
| 123 | + var area = ''; | |
| 124 | + if (d['start_time'] ) { | |
| 125 | + if (d['area'] > 75) | |
| 126 | + area = ' <span class="badge badge-success"><i class="fas fa-desktop"></i> ' + Math.round(d['area']) + '%</span>'; | |
| 127 | + else | |
| 128 | + area = ' <span class="badge badge-danger"><i class="fas fa-desktop"></i> ' + Math.round(d['area']) + '%</span>'; | |
| 129 | + }; | |
| 124 | 130 | var g = d['grades']; |
| 125 | 131 | |
| 126 | 132 | t[i] = []; |
| ... | ... | @@ -128,7 +134,7 @@ $(document).ready(function() { |
| 128 | 134 | t[i][1] = '<input type="checkbox" name="' + uid + '" value="true"' + checked + '> '; |
| 129 | 135 | t[i][2] = uid; |
| 130 | 136 | t[i][3] = d['name']; |
| 131 | - t[i][4] = password_defined + hora_inicio; | |
| 137 | + t[i][4] = password_defined + hora_inicio + area + unfocus; | |
| 132 | 138 | |
| 133 | 139 | var gbar = ''; |
| 134 | 140 | for (var j=0; j < g.length; j++) | ... | ... |
perguntations/templates/review.html
| ... | ... | @@ -74,9 +74,9 @@ |
| 74 | 74 | <h1 class="display-5">{{ t['title'] }}</h1> |
| 75 | 75 | <h5> |
| 76 | 76 | <div class="row"> |
| 77 | - <label for="duracao" class="col-sm-2">Duração (minutos):</label> | |
| 77 | + <label for="duracao" class="col-sm-2">Duração:</label> | |
| 78 | 78 | <div class="col-sm-10" id="duracao"> |
| 79 | - {{ t.get('duration', 0) if t.get('duration', 0) > 0 else '+'+chr(8734) }} | |
| 79 | + {{ str(t.get('duration', 0)) + ' minutos' if t.get('duration', 0) > 0 else '+'+chr(8734) }} | |
| 80 | 80 | </div> |
| 81 | 81 | </div> |
| 82 | 82 | </h5> | ... | ... |