Commit 7c5719d820b4b0f526089afaac8a0dea6f524a8a

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

- login page looks good. (same as perguntations)

- maintopics in root page is ok.
- doing a topic is not working.
BUGS.md
1 1  
2 2 BUGS:
3 3  
  4 +- change password in maintopics.html, falta menu para lançar modal
  5 +
4 6 - reportar comentarios após submeter.
5 7 - cada topico tem uma pagina begin e uma end
6 8 - pertuntas tipo tristate: (sim, não, não sei)
... ...
serve.py
... ... @@ -31,8 +31,8 @@ class WebApplication(tornado.web.Application):
31 31 (r'/login', LoginHandler),
32 32 (r'/logout', LogoutHandler),
33 33 (r'/change_password', ChangePasswordHandler),
34   - (r'/question', QuestionHandler),
35   - (r'/', RootHandler),
  34 + (r'/question', QuestionHandler),
  35 + (r'/', RootHandler), # show list of topics
36 36 (r'/topic/(.+)', TopicHandler),
37 37 (r'/(.+)', FileHandler),
38 38 ]
... ... @@ -219,11 +219,28 @@ class QuestionHandler(BaseHandler):
219 219  
220 220 @tornado.web.authenticated
221 221 def get(self, topic=''):
222   - self.write(self.new_question(self.current_user))
  222 + logging.debug('QuestionHandler.get')
  223 + print("topic: " + topic)
  224 + uid = self.current_user
  225 + question = self.learn.get_student_question(self, uid)
  226 + print(question)
  227 +
  228 + question_html = self.render_string(self.templates[question['type']],question=question, md=md)
  229 + response = {
  230 + 'method': 'new_question',
  231 + 'params': {
  232 + 'question': tornado.escape.to_unicode(question_html),
  233 + 'state': tornado.escape.to_unicode(topics_html),
  234 + 'progress': progress,
  235 + }
  236 + }
  237 + self.write(response)
223 238  
224 239 # handles answer posted
225 240 @tornado.web.authenticated
226 241 def post(self):
  242 + logging.debug('QuestionHandler.post')
  243 +
227 244 user = self.current_user
228 245 answer = self.get_body_arguments('answer')
229 246 grade = self.learn.check_answer(user, answer)
... ...
static/css/learn.css
1 1 body {
2 2 margin: 0;
3   - padding-top: 0px;
  3 + padding-top: 100px;
4 4 }
5 5  
6 6 img {
... ...
static/popper 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../perguntations/static/popper
0 2 \ No newline at end of file
... ...
templates/login.html
1 1 <!DOCTYPE html>
2 2 <html lang="en">
3   - <head>
4   - <meta charset="utf-8" />
5   - <title>Teste</title>
6   - <link rel="icon" href="/static/favicon.ico" />
7   -
8   -<!-- Bootstrap -->
9   - <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
10   - <link rel="stylesheet" href="/static/css/bootstrap-theme.min.css"> <!-- optional -->
11   -
12   -<!-- Scripts -->
13   - <script src="/static/js/jquery.min.js"></script>
14   - <script src="/static/bootstrap/js/bootstrap.min.js"></script>
15   - </head>
16   -<!-- ===================================================================== -->
17   - <body>
18   - <div class="container-fluid">
19   - <div class="well drop-shadow">
20   - <div class="row voffset">
21   - <div class="col-xs-4">
22   - <img src="/static/logo_horizontal.png" class="img-responsive">
  3 +<head>
  4 + <title>GotIT</title>
  5 + <link rel="icon" href="/static/favicon.ico">
  6 +
  7 + <meta charset="utf-8">
  8 + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  9 +
  10 + <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
  11 +
  12 +</head>
  13 +<!-- =================================================================== -->
  14 +<body>
  15 + <div class="container-fluid">
  16 + <div class="card bg-light border-secondary mb-3">
  17 + <div class="card-body">
  18 + <div class="row">
  19 +
  20 + <div class="col-sm-4">
  21 + <img src="/static/logo_horizontal.png" class="img-responsive" width="60%">
23 22 </div>
24   - <div class="col-xs-8">
25   - <h4>Identificação:</h4>
  23 +
  24 + <div class="col-sm-8">
  25 + <h4>Identificação:</h4>
  26 +
26 27 <form method="post" action="/login" class="form-signin">
27 28 {% module xsrf_form_html() %}
28 29 <div class="form-group">
... ... @@ -37,6 +38,13 @@
37 38 </div>
38 39 </div>
39 40 </div>
40   - </div> <!-- container -->
41   - </body>
  41 + </div>
  42 + </div> <!-- container -->
  43 +
  44 + <!-- Scripts -->
  45 + <script src="/static/js/jquery.min.js"></script>
  46 + <script src="/static/popper/umd/popper.min.js"></script>
  47 + <script src="/static/bootstrap/js/bootstrap.min.js"></script>
  48 +
  49 +</body>
42 50 </html>
... ...
templates/maintopics.html
... ... @@ -3,7 +3,7 @@
3 3 <!DOCTYPE html>
4 4 <html lang="pt-PT">
5 5 <head>
6   - <title>GotIT</title>
  6 + <title>DoIT</title>
7 7 <link rel="icon" href="/static/favicon.ico">
8 8  
9 9 <meta charset="utf-8">
... ... @@ -22,7 +22,7 @@
22 22 <body>
23 23 <nav class="navbar navbar-expand-sm fixed-top navbar-dark bg-dark">
24 24 <a class="navbar-brand" href="#">
25   - <i class="fa fa-clock-o" aria-hidden="true"></i>
  25 + <img src="/static/logo_horizontal.png" height="30" alt="">
26 26 </a>
27 27 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
28 28 <span class="navbar-toggler-icon"></span>
... ... @@ -43,6 +43,8 @@
43 43 <!-- ===================================================================== -->
44 44 <div class="container">
45 45  
  46 + <div id="notifications"></div>
  47 +
46 48 <h3>Tópicos</h3>
47 49  
48 50 <div class="list-group">
... ... @@ -78,11 +80,66 @@
78 80 </div> <!-- list-group -->
79 81 </div>
80 82  
  83 +<!-- === Change Password Modal =========================================== -->
  84 +<div id="password_modal" class="modal fade" tabindex="-1" role="dialog">
  85 + <div class="modal-dialog modal-sm" role="document">
  86 + <div class="modal-content">
  87 +<!-- header -->
  88 + <div class="modal-header">
  89 + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  90 + <h4 class="modal-title">Alterar Password</h4>
  91 + </div>
  92 +<!-- body -->
  93 + <div class="modal-body">
  94 + <div class="control-group">
  95 + <label for="new_password" class="control-label">Nova Password</label>
  96 + <div class="controls">
  97 + <input type="password" id="new_password" name="new_password" autocomplete="new-password">
  98 + </div>
  99 + </div>
  100 + </div>
  101 +<!-- footer -->
  102 + <div class="modal-footer">
  103 + <button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
  104 + <button id="change_password" type="button" class="btn btn-danger" data-dismiss="modal">Alterar</button>
  105 + </div>
  106 +
  107 + </div><!-- /.modal-content -->
  108 + </div><!-- /.modal-dialog -->
  109 +</div><!-- /.modal -->
  110 +
81 111 <!-- Scripts -->
82   - <script src="/static/js/jquery.min.js"></script>
83   - <script src="/static/popper/umd/popper.min.js"></script>
84   - <script src="/static/bootstrap/js/bootstrap.min.js"></script>
  112 +<script src="/static/js/jquery.min.js"></script>
  113 +<script src="/static/popper/umd/popper.min.js"></script>
  114 +<script src="/static/bootstrap/js/bootstrap.min.js"></script>
  115 +
  116 +<script>
  117 + function notify(msg) {
  118 + $("#notifications").html(msg);
  119 + $("#notifications").fadeIn(250).delay(5000).fadeOut(500);
  120 + }
  121 +
  122 + function change_password() {
  123 + $.ajax({
  124 + type: "POST",
  125 + url: "/change_password",
  126 + data: {
  127 + "new_password": $("#new_password").val(),
  128 + },
  129 + dataType: "json",
  130 + success: function(r) {
  131 + notify(r['msg']);
  132 + },
  133 + error: function(r) {
  134 + notify(r['msg']);
  135 + },
  136 + });
  137 + }
85 138  
  139 + $(document).ready(function() {
  140 + $("#change_password").click(change_password);
  141 + });
  142 +</script>
86 143 </body>
87 144 </html>
88 145  
... ...
templates/topic.html
... ... @@ -25,7 +25,19 @@
25 25 <link rel="stylesheet" href="/static/css/github.css">
26 26  
27 27 <!-- Other -->
28   - <link rel="stylesheet" href="/static/css/learn.css">
  28 + <!-- <link rel="stylesheet" href="/static/css/learn.css"> -->
  29 +
  30 + <style>
  31 + /* progress bars have height of 4 pixels */
  32 + .progress {
  33 + height: 10px;
  34 + border-radius: 0px;
  35 + }
  36 + body {
  37 + margin: 0;
  38 + padding-top: 55px;
  39 + }
  40 + </style>
29 41  
30 42 </head>
31 43 <!-- ===================================================================== -->
... ... @@ -34,7 +46,7 @@
34 46 <!-- Navbar -->
35 47 <nav class="navbar navbar-expand-sm fixed-top navbar-dark bg-dark">
36 48 <a class="navbar-brand" href="#">
37   - <i class="fa fa-clock-o" aria-hidden="true"></i>
  49 + <img src="/static/logo_horizontal.png" height="30" alt="">
38 50 </a>
39 51 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
40 52 <span class="navbar-toggler-icon"></span>
... ... @@ -54,189 +66,60 @@
54 66 </nav>
55 67  
56 68 <!-- ===================================================================== -->
  69 +<div class="progress">
  70 + <div class="progress-bar progress-bar-success" id="topic_progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 1em;width: 0%"></div>
  71 +</div>
  72 +<!-- ===================================================================== -->
57 73 <!-- main panel with questions -->
58   -<div id="main">
59   - <div id="body">
60   - <div class="progress">
61   - <div class="progress-bar progress-bar-success" id="topic_progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 0em;width: 0%"></div>
62   - </div>
  74 +<div class="container">
63 75  
64   - <!-- <div class="col-md-12"> -->
65   -
66   - <div id="notifications">
67   - <!-- notifications go here -->
68   - </div>
69   -
70   - <!-- Question body -->
71   - <form action="/question" method="post" id="question_form" autocomplete="off">
72   - {% module xsrf_form_html() %}
73   -
74   - <div id="question_div">
75   - <!-- questions go here -->
76   - </div>
77   -
78   - </form>
79   - <button class="btn btn-primary" id="submit" data-toggle="tooltip" data-placement="right" title="Shift-Enter">Continuar</button>
80   - <!-- </div> -->
81   - </div> <!-- body -->
82   -</div> <!-- main -->
83   -
84   -<!-- === Change Password Modal =========================================== -->
85   -<div id="password_modal" class="modal fade" tabindex="-1" role="dialog">
86   - <div class="modal-dialog modal-sm" role="document">
87   - <div class="modal-content">
88   -<!-- header -->
89   - <div class="modal-header">
90   - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
91   - <h4 class="modal-title">Alterar Password</h4>
92   - </div>
93   -<!-- body -->
94   - <div class="modal-body">
95   - <div class="control-group">
96   - <label for="new_password" class="control-label">Nova Password</label>
97   - <div class="controls">
98   - <input type="password" id="new_password" name="new_password" autocomplete="new-password">
99   - </div>
100   - </div>
101   - </div>
102   -<!-- footer -->
103   - <div class="modal-footer">
104   - <button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
105   - <button id="change_password" type="button" class="btn btn-danger" data-dismiss="modal">Alterar</button>
106   - </div>
  76 + <div id="notifications"></div>
107 77  
108   - </div><!-- /.modal-content -->
109   - </div><!-- /.modal-dialog -->
110   -</div><!-- /.modal -->
  78 + <!-- Question body -->
  79 + <form action="/question" method="post" id="question_form" autocomplete="off">
  80 + {% module xsrf_form_html() %}
  81 +
  82 + <div id="question_div">
  83 + Question goes here!!!!
  84 + <!-- questions go here -->
  85 + </div>
111 86  
  87 + </form>
  88 + <button class="btn btn-primary" id="submit" data-toggle="tooltip" data-placement="right" title="Shift-Enter">Continuar</button>
  89 +</div>
112 90  
113 91 <!-- ===================================================================== -->
114 92 <!-- JAVASCRIPT -->
115 93 <!-- ===================================================================== -->
  94 +
  95 +<script src="/static/js/jquery.min.js"></script>
  96 +<script src="/static/popper/umd/popper.min.js"></script>
  97 +<script src="/static/bootstrap/js/bootstrap.min.js"></script>
  98 +
116 99 <script>
117   -$.fn.extend({
118   - animateCSS: function (animation) {
119   - var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
120   - this.addClass('animated ' + animation).one(animationEnd, function() {
121   - $(this).removeClass('animated ' + animation);
  100 + // Get current question
  101 + function getQuestion() {
  102 + $.ajax({
  103 + url: "/question",
  104 + // headers: {"X-XSRFToken": token},
  105 + dataType: "json", // expected from server
  106 + success: function(r) {alert(r); },//updateQuestion,
  107 + error: function() {alert("O servidor não responde.");}
122 108 });
123 109 }
124   -});
125   -
126   -// Process the response given by the server
127   -function updateQuestion(response){
128   - switch (response["method"]) {
129   - case "new_question":
130   - $("#question_div").html(response["params"]["question"]);
131   - $("#topics").html(response["params"]["state"]);
132   - $('#topic_progress').css('width', (100*response["params"]["progress"])+'%').attr('aria-valuenow', 100*response["params"]["progress"]);
133   -
134   - MathJax.Hub.Queue(["Typeset",MathJax.Hub,"question_div"]);
135   -
136   - // enable shift+enter to submit and tab to spaces conversion
137   - $("input:text, input:radio, input:checkbox").keydown(function (e) {
138   - if (e.keyCode == 13) {
139   - e.preventDefault();
140   - if (e.shiftKey) postQuestion();
141   - return false;
142   - }
143   - });
144   - $("textarea").keydown(function (e) {
145   - if (e.keyCode == 13 && e.shiftKey) { // shift enter
146   - e.preventDefault();
147   - postQuestion();
148   - }
149   - else if (e.keyCode === 9) { // tab
150   - e.preventDefault(); // prevent loosing focus
151   - // get caret position/selection
152   - var start = this.selectionStart;
153   - var end = this.selectionEnd;
154   - var value = $(this).val();
155   -
156   - // set textarea value to: text before caret + tab + text after caret
157   - $(this).val(value.substring(0, start) + " " + value.substring(end));
158   -
159   - // put caret at right position again (add one for the tab)
160   - this.selectionStart = this.selectionEnd = start + 4;
161   - }
162   - });
163 110  
164   - // var audio = new Audio('/static/sounds/correct.mp3');
165   - // audio.play();
166   - $('#question_div').animateCSS('zoomIn');
167   - break;
168   -
169   - case "shake":
170   - // var audio = new Audio('/static/sounds/wrong.mp3');
171   - // audio.play();
172   - $('#topic_progress').css('width', (100*response["params"]["progress"])+'%').attr('aria-valuenow', 100*response["params"]["progress"]);
173   - $('#question_div').animateCSS('shake');
174   - break;
175   -
176   - case "finished_topic":
177   - $('#topic_progress').css('width', '100%').attr('aria-valuenow', 100);
178   - $("#topics").html(response["params"]["state"]);
179   - $("#question_div").html('<img src="/static/trophy.png" alt="trophy" class="img-rounded img-responsive center-block">'); // FIXME size
180   - break;
181   - }
182   -}
183   -
184   -// Send answer and receive a response.
185   -// The response can be a new_question or a shake if the answer is wrong.
186   -function postQuestion() {
187   - $.ajax({
188   - type: "POST",
189   - url: "/question",
190   - // headers: {"X-XSRFToken": token},
191   - data: $("#question_form").serialize(), // {'a':10,'b':20},
192   - dataType: "json", // expected from server
193   - success: updateQuestion,
194   - error: function() {alert("O servidor não responde.");}
195   - });
196   -}
197   -
198   -// Get current question
199   -function getQuestion() {
200   - $.ajax({
201   - url: "/question",
202   - // headers: {"X-XSRFToken": token},
203   - dataType: "json", // expected from server
204   - success: updateQuestion,
205   - error: function() {alert("O servidor não responde.");}
206   - });
207   -}
208   -
209   -function change_password() {
210   - $.ajax({
211   - type: "POST",
212   - url: "/change_password",
213   - data: {
214   - "new_password": $("#new_password").val(),
215   - },
216   - dataType: "json",
217   - success: function(r) {
218   - $("#notifications").html(r["msg"]);
219   - $("#notification").fadeIn(250).delay(5000).fadeOut(500);
220   - },
221   - error: function(r) {
222   - $("#notifications").html(r["msg"]);
223   - $("#notification").fadeIn(250).delay(5000).fadeOut(500);
224   - },
225   - });
226   -}
227 111  
228   -$(document).ready(function() {
229   - getQuestion();
230   - $("#submit").click(postQuestion);
231   - $('[data-toggle=offcanvas]').click(function() {
232   - $('.row-offcanvas').toggleClass('active');
  112 +
  113 + $(document).ready(function() {
  114 + getQuestion();
  115 + // $("#submit").click(postQuestion);
  116 + // $('[data-toggle=offcanvas]').click(function() {
  117 + // $('.row-offcanvas').toggleClass('active');
  118 + // });
  119 + // $("#change_password").click(change_password);
233 120 });
234   - $("#change_password").click(change_password);
235   -});
236 121 </script>
237 122  
238   - <script src="/static/js/jquery.min.js"></script>
239   - <script src="/static/bootstrap/js/bootstrap.min.js"></script>
240 123  
241 124 </body>
242 125 </html>
... ...