Commit 8b4ac80ad8069fb0bb8d73b59baf6680b802547f

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

- fixed menus

- mathjax3 seems to be working fine
- fixed finish_topics redirect
working... with bugs...
1 1
2 # BUGS 2 # BUGS
3 3
  4 +- nao esta a seguir o max_tries definido no ficheiro de dependencias.
  5 +- no curso de linear algebra, as perguntas estao shuffled, mas nao deviam estar... nao esta a obedecer a keyword shuffle.
  6 +- obter rankings por curso GET course=course_id
  7 +- impedir que quando students.db não é encontrado, crie um ficheiro vazio.
4 - classificacoes so devia mostrar os que ja fizeram alguma coisa 8 - classificacoes so devia mostrar os que ja fizeram alguma coisa
5 -- menu nao mostra as opcoes correctamente  
6 -- mathjax nao esta a correr sobre o titulo e sobre as solucoes.  
7 - QFactory.generate() devia fazer run da gen_async, ou remover. 9 - QFactory.generate() devia fazer run da gen_async, ou remover.
8 -- finish topic vai para a lista de cursos. devia ficar no mesmo curso.  
9 - marking all options right in a radio question breaks! 10 - marking all options right in a radio question breaks!
10 -- impedir que quando students.db não é encontrado, crie um ficheiro vazio.  
11 - opcao --prefix devia afectar a base de dados? 11 - opcao --prefix devia afectar a base de dados?
12 - duplo clicks no botao "responder" dessincroniza as questões, ver debounce em https://stackoverflow.com/questions/20281546/how-to-prevent-calling-of-en-event-handler-twice-on-fast-clicks 12 - duplo clicks no botao "responder" dessincroniza as questões, ver debounce em https://stackoverflow.com/questions/20281546/how-to-prevent-calling-of-en-event-handler-twice-on-fast-clicks
13 - quando termina topico devia apagar as perguntas todas (se falhar a gerar novo topico, aparecem perguntas do antigo) 13 - quando termina topico devia apagar as perguntas todas (se falhar a gerar novo topico, aparecem perguntas do antigo)
@@ -16,8 +16,6 @@ @@ -16,8 +16,6 @@
16 - permitir configuracao para escolher entre static files locais ou remotos 16 - permitir configuracao para escolher entre static files locais ou remotos
17 - sqlalchemy.pool.impl.NullPool: Exception during reset or similar 17 - sqlalchemy.pool.impl.NullPool: Exception during reset or similar
18 sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread. 18 sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread.
19 -  
20 -- porque é que md() é usado nos templates e não directamente no codigo python?  
21 - templates question-*.html tem input hidden question_ref que não é usado. remover? 19 - templates question-*.html tem input hidden question_ref que não é usado. remover?
22 - guardar o estado a meio de um nível. 20 - guardar o estado a meio de um nível.
23 - safari as vezes envia dois gets no inicio do topico. nesses casos, a segunda pergunta não é actualizada no browser... o topico tem de ser gerado qd se escolhe o topico em main_topics. O get nao deve alterar o estado. 21 - safari as vezes envia dois gets no inicio do topico. nesses casos, a segunda pergunta não é actualizada no browser... o topico tem de ser gerado qd se escolhe o topico em main_topics. O get nao deve alterar o estado.
@@ -50,6 +48,9 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in @@ -50,6 +48,9 @@ sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in
50 48
51 # FIXED 49 # FIXED
52 50
  51 +- menu nao mostra as opcoes correctamente
  52 +- finish topic vai para a lista de cursos. devia ficar no mesmo curso.
  53 +- mathjax nao esta a correr sobre o titulo.
53 - forgetting factor is hardcoded in student.py 54 - forgetting factor is hardcoded in student.py
54 - add aprendizatons --version 55 - add aprendizatons --version
55 - se aluno abre dois tabs no browser, conseque navegar em simultaneo para perguntas diferentes. quando submete uma delas dá asneira. Tem de haver um campo hidden que tenha um céodigo único que indique qual a pergunta. do lado do servidor apnas há o codigo da pergunta corrente, se forem diferentes faz redirect para /. 56 - se aluno abre dois tabs no browser, conseque navegar em simultaneo para perguntas diferentes. quando submete uma delas dá asneira. Tem de haver um campo hidden que tenha um céodigo único que indique qual a pergunta. do lado do servidor apnas há o codigo da pergunta corrente, se forem diferentes faz redirect para /.
aprendizations/learnapp.py
@@ -268,6 +268,7 @@ class LearnApp(object): @@ -268,6 +268,7 @@ class LearnApp(object):
268 student.start_course(course) 268 student.start_course(course)
269 except Exception as e: 269 except Exception as e:
270 logger.warning(f'"{uid}" could not start course "{course}": {e}') 270 logger.warning(f'"{uid}" could not start course "{course}": {e}')
  271 + raise
271 else: 272 else:
272 logger.info(f'"{uid}" started course "{course}"') 273 logger.info(f'"{uid}" started course "{course}"')
273 274
@@ -452,6 +453,10 @@ class LearnApp(object): @@ -452,6 +453,10 @@ class LearnApp(object):
452 return self.online[uid]['state'].get_current_course_title() 453 return self.online[uid]['state'].get_current_course_title()
453 454
454 # ------------------------------------------------------------------------ 455 # ------------------------------------------------------------------------
  456 + def get_student_course_id(self, uid: str) -> str:
  457 + return self.online[uid]['state'].get_current_course_id()
  458 +
  459 + # ------------------------------------------------------------------------
455 # def get_title(self) -> str: 460 # def get_title(self) -> str:
456 # # return self.deps.graph.get('title', '') 461 # # return self.deps.graph.get('title', '')
457 # return self. 462 # return self.
@@ -471,15 +476,15 @@ class LearnApp(object): @@ -471,15 +476,15 @@ class LearnApp(object):
471 return self.courses 476 return self.courses
472 477
473 # ------------------------------------------------------------------------ 478 # ------------------------------------------------------------------------
474 - def get_rankings(self, uid: str) -> Iterable[Tuple[str, str, float, float]]: 479 + def get_rankings(self, uid: str, course_id: str) -> Iterable[Tuple[str, str, float, float]]:
475 480
476 - logger.info(f'User "{uid}" get rankings') 481 + logger.info(f'User "{uid}" get rankings for {course_id}')
477 with self.db_session() as s: 482 with self.db_session() as s:
478 students = s.query(Student.id, Student.name).all() 483 students = s.query(Student.id, Student.name).all()
479 484
480 # topic progress 485 # topic progress
481 student_topics = s.query(StudentTopic.student_id, 486 student_topics = s.query(StudentTopic.student_id,
482 - StudentTopic.topic_id, 487 + StudentTopic.topic_id, # FIXME Filter topics of the course
483 StudentTopic.level, 488 StudentTopic.level,
484 StudentTopic.date).all() 489 StudentTopic.date).all()
485 total_topics = s.query(Topic).count() 490 total_topics = s.query(Topic).count()
aprendizations/serve.py
@@ -48,11 +48,10 @@ class WebApplication(tornado.web.Application): @@ -48,11 +48,10 @@ class WebApplication(tornado.web.Application):
48 (r'/change_password', ChangePasswordHandler), 48 (r'/change_password', ChangePasswordHandler),
49 (r'/question', QuestionHandler), # render question 49 (r'/question', QuestionHandler), # render question
50 (r'/rankings', RankingsHandler), # rankings table 50 (r'/rankings', RankingsHandler), # rankings table
51 - # (r'/topics', TopicsHandler), # show list of topics  
52 (r'/topic/(.+)', TopicHandler), # start topic 51 (r'/topic/(.+)', TopicHandler), # start topic
53 (r'/file/(.+)', FileHandler), # serve file 52 (r'/file/(.+)', FileHandler), # serve file
54 (r'/courses', CoursesHandler), # show list of courses 53 (r'/courses', CoursesHandler), # show list of courses
55 - (r'/course/(.+)', CourseHandler), # show course topics 54 + (r'/course/(.*)', CourseHandler), # show course topics
56 (r'/', RootHandler), # redirects 55 (r'/', RootHandler), # redirects
57 ] 56 ]
58 settings = { 57 settings = {
@@ -96,12 +95,17 @@ class RankingsHandler(BaseHandler): @@ -96,12 +95,17 @@ class RankingsHandler(BaseHandler):
96 @tornado.web.authenticated 95 @tornado.web.authenticated
97 def get(self): 96 def get(self):
98 uid = self.current_user 97 uid = self.current_user
99 - rankings = self.learn.get_rankings(uid) 98 + current_course = self.learn.get_student_course_id(uid)
  99 + course_id = self.get_query_argument('course', default=current_course)
  100 + rankings = self.learn.get_rankings(uid, course_id)
100 self.render('rankings.html', 101 self.render('rankings.html',
101 appname=APP_NAME, 102 appname=APP_NAME,
102 uid=uid, 103 uid=uid,
103 name=self.learn.get_student_name(uid), 104 name=self.learn.get_student_name(uid),
104 - rankings=rankings) 105 + rankings=rankings,
  106 + course_id=course_id,
  107 + course_title=self.learn.get_student_course_title(uid), # FIXME get from course var
  108 + )
105 109
106 110
107 # ---------------------------------------------------------------------------- 111 # ----------------------------------------------------------------------------
@@ -202,40 +206,25 @@ class CourseHandler(BaseHandler): @@ -202,40 +206,25 @@ class CourseHandler(BaseHandler):
202 @tornado.web.authenticated 206 @tornado.web.authenticated
203 def get(self, course): 207 def get(self, course):
204 uid = self.current_user 208 uid = self.current_user
  209 + if course == '':
  210 + course = self.learn.get_student_course_id(uid)
205 211
206 try: 212 try:
207 self.learn.start_course(uid, course) 213 self.learn.start_course(uid, course)
208 except KeyError: 214 except KeyError:
209 self.redirect('/courses') 215 self.redirect('/courses')
210 216
211 - # print('TITULO: ---------------->', self.learn.get_title())  
212 self.render('maintopics-table.html', 217 self.render('maintopics-table.html',
213 appname=APP_NAME, 218 appname=APP_NAME,
214 uid=uid, 219 uid=uid,
215 name=self.learn.get_student_name(uid), 220 name=self.learn.get_student_name(uid),
216 state=self.learn.get_student_state(uid), 221 state=self.learn.get_student_state(uid),
217 - title=self.learn.get_student_course_title(uid), 222 + course_title=self.learn.get_student_course_title(uid),
  223 + course_id=self.learn.get_student_course_id(uid),
218 ) 224 )
219 225
220 226
221 # ---------------------------------------------------------------------------- 227 # ----------------------------------------------------------------------------
222 -# /topics  
223 -# Shows a list of topics and proficiency (stars, locked).  
224 -# ----------------------------------------------------------------------------  
225 -# class TopicsHandler(BaseHandler):  
226 -# @tornado.web.authenticated  
227 -# def get(self):  
228 -# uid = self.current_user  
229 -# self.render('maintopics-table.html',  
230 -# appname=APP_NAME,  
231 -# uid=uid,  
232 -# name=self.learn.get_student_name(uid),  
233 -# state=self.learn.get_student_state(uid),  
234 -# title=self.learn.get_title(),  
235 -# )  
236 -  
237 -  
238 -# ----------------------------------------------------------------------------  
239 # /topic/... 228 # /topic/...
240 # Start a given topic 229 # Start a given topic
241 # ---------------------------------------------------------------------------- 230 # ----------------------------------------------------------------------------
@@ -253,6 +242,8 @@ class TopicHandler(BaseHandler): @@ -253,6 +242,8 @@ class TopicHandler(BaseHandler):
253 appname=APP_NAME, 242 appname=APP_NAME,
254 uid=uid, 243 uid=uid,
255 name=self.learn.get_student_name(uid), 244 name=self.learn.get_student_name(uid),
  245 + # course_title=self.learn.get_student_course_title(uid),
  246 + course_id=self.learn.get_student_course_id(uid),
256 ) 247 )
257 248
258 249
aprendizations/static/js/topic.js
@@ -55,7 +55,7 @@ function updateQuestion(response) { @@ -55,7 +55,7 @@ function updateQuestion(response) {
55 $('#submit, #comments, #solution').remove(); 55 $('#submit, #comments, #solution').remove();
56 $("#content").html(response["params"]["question"]).animateCSS('tada'); 56 $("#content").html(response["params"]["question"]).animateCSS('tada');
57 $('#topic_progress').css('width', '100%').attr('aria-valuenow', 100); 57 $('#topic_progress').css('width', '100%').attr('aria-valuenow', 100);
58 - setTimeout(function(){window.location.replace('/');}, 2000); 58 + setTimeout(function(){window.location.replace('/course/');}, 2000);
59 break; 59 break;
60 } 60 }
61 } 61 }
@@ -137,7 +137,7 @@ function getFeedback(response) { @@ -137,7 +137,7 @@ function getFeedback(response) {
137 $("#right").hide(); 137 $("#right").hide();
138 $('#solution').html(params['solution']).animateCSS('flipInX'); 138 $('#solution').html(params['solution']).animateCSS('flipInX');
139 // MathJax.Hub.Queue(["Typeset", MathJax.Hub, "#solution"]); 139 // MathJax.Hub.Queue(["Typeset", MathJax.Hub, "#solution"]);
140 - MathJax.typeset(); 140 + MathJax.typeset();
141 141
142 }); 142 });
143 break; 143 break;
aprendizations/student.py
@@ -232,6 +232,10 @@ class StudentState(object): @@ -232,6 +232,10 @@ class StudentState(object):
232 return self.courses[self.current_course]['title'] 232 return self.courses[self.current_course]['title']
233 233
234 # ------------------------------------------------------------------------ 234 # ------------------------------------------------------------------------
  235 + def get_current_course_id(self) -> Optional[str]:
  236 + return self.current_course
  237 +
  238 + # ------------------------------------------------------------------------
235 def is_locked(self, topic: str) -> bool: 239 def is_locked(self, topic: str) -> bool:
236 return topic not in self.state 240 return topic not in self.state
237 241
aprendizations/templates/courses.html
@@ -33,16 +33,16 @@ @@ -33,16 +33,16 @@
33 </button> 33 </button>
34 34
35 <div class="collapse navbar-collapse" id="navbarText"> 35 <div class="collapse navbar-collapse" id="navbarText">
36 - <ul class="navbar-nav mr-auto">  
37 - <li class="nav-item active">  
38 - <a class="nav-link" href="#">Cursos<span class="sr-only">(actual)</span></a>  
39 - </li>  
40 - </ul> 36 + <div class="navbar-nav mr-auto">
  37 + <a class="nav-item nav-link active" href="#">Cursos <span class="sr-only">(actual)</span></a>
  38 + <a class="nav-item nav-link disabled" href="#">Tópicos</a>
  39 + <a class="nav-item nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Classificação</a>
  40 + </div>
41 41
42 <ul class="navbar-nav"> 42 <ul class="navbar-nav">
43 <li class="nav-item dropdown"> 43 <li class="nav-item dropdown">
44 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 44 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
45 - <i class="fas fa-user" aria-hidden="true"></i> 45 + <i class="fas fa-user-graduate" aria-hidden="true"></i>
46 <span id="name">{{ escape(name) }}</span> 46 <span id="name">{{ escape(name) }}</span>
47 <span class="caret"></span> 47 <span class="caret"></span>
48 </a> 48 </a>
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 62
63 {% for k,v in courses.items() %} 63 {% for k,v in courses.items() %}
64 64
65 - <a href="/course/{{k}}" class="card text-dark mb-3"> 65 + <a href="/course/{{k}}" class="card text-dark mb-3" style="width: 18rem;">
66 <div class="card-body"> 66 <div class="card-body">
67 <h6 class="card-title">{{ v['title'] }}</h6> 67 <h6 class="card-title">{{ v['title'] }}</h6>
68 </div> 68 </div>
aprendizations/templates/maintopics-table.html
@@ -33,22 +33,16 @@ @@ -33,22 +33,16 @@
33 </button> 33 </button>
34 34
35 <div class="collapse navbar-collapse" id="navbarText"> 35 <div class="collapse navbar-collapse" id="navbarText">
36 - <ul class="navbar-nav mr-auto">  
37 - <li class="nav-item">  
38 - <a class="nav-link" href="/courses">Cursos</a>  
39 - </li>  
40 - <li class="nav-item active">  
41 - <a class="nav-link" href="#">Tópicos<span class="sr-only">(actual)</span></a>  
42 - </li>  
43 - <li class="nav-item">  
44 - <a class="nav-link" href="/rankings">Classificação</a>  
45 - </li>  
46 - </ul> 36 + <div class="navbar-nav mr-auto">
  37 + <a class="nav-item nav-link" href="/courses">Cursos</a>
  38 + <a class="nav-item nav-link active" href="#">Tópicos <span class="sr-only">(actual)</span></a>
  39 + <a class="nav-item nav-link" href="/rankings?course={{course_id}}">Classificação</a>
  40 + </div>
47 41
48 <ul class="navbar-nav"> 42 <ul class="navbar-nav">
49 <li class="nav-item dropdown"> 43 <li class="nav-item dropdown">
50 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 44 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
51 - <i class="fas fa-user" aria-hidden="true"></i> 45 + <i class="fas fa-user-graduate" aria-hidden="true"></i>
52 <span id="name">{{ escape(name) }}</span> 46 <span id="name">{{ escape(name) }}</span>
53 <span class="caret"></span> 47 <span class="caret"></span>
54 </a> 48 </a>
@@ -66,7 +60,7 @@ @@ -66,7 +60,7 @@
66 60
67 <div id="notifications"></div> 61 <div id="notifications"></div>
68 62
69 - <h4>{{ title }}</h4> 63 + <h4>{{ course_title }}</h4>
70 64
71 <table class="table table-hover"> 65 <table class="table table-hover">
72 <thead> 66 <thead>
aprendizations/templates/question.html
1 {% autoescape %} 1 {% autoescape %}
2 2
3 -<h2 class="page-header">{{ question['title'] }}</h4> 3 +<h2 class="page-header">{{ md(question['title']) }}</h4>
4 4
5 <div id="text"> 5 <div id="text">
6 {{ md(question['text']) }} 6 {{ md(question['text']) }}
aprendizations/templates/rankings.html
@@ -33,19 +33,16 @@ @@ -33,19 +33,16 @@
33 </button> 33 </button>
34 34
35 <div class="collapse navbar-collapse" id="navbarText"> 35 <div class="collapse navbar-collapse" id="navbarText">
36 - <ul class="navbar-nav mr-auto">  
37 - <li class="nav-item">  
38 - <a class="nav-link" href="/">Tópicos</a>  
39 - </li>  
40 - <li class="nav-item active">  
41 - <a class="nav-link" href="/rankings">Classificação<span class="sr-only">(current)</span></a>  
42 - </li>  
43 - </ul> 36 + <div class="navbar-nav mr-auto">
  37 + <a class="nav-item nav-link" href="/courses">Cursos <span class="sr-only">(actual)</span></a>
  38 + <a class="nav-item nav-link" href="/course/{{course_id}}">Tópicos</a>
  39 + <a class="nav-item nav-link active" href="#">Classificação</a>
  40 + </div>
44 41
45 <ul class="navbar-nav"> 42 <ul class="navbar-nav">
46 <li class="nav-item dropdown"> 43 <li class="nav-item dropdown">
47 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 44 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
48 - <i class="fas fa-user" aria-hidden="true"></i> 45 + <i class="fas fa-user-graduate" aria-hidden="true"></i>
49 <span id="name">{{ escape(name) }}</span> 46 <span id="name">{{ escape(name) }}</span>
50 <span class="caret"></span> 47 <span class="caret"></span>
51 </a> 48 </a>
@@ -60,7 +57,7 @@ @@ -60,7 +57,7 @@
60 </nav> 57 </nav>
61 <!-- ===================================================================== --> 58 <!-- ===================================================================== -->
62 <div class="container"> 59 <div class="container">
63 -<h4>Classificação geral</h4> 60 +<h4>{{course_title}}</h4>
64 <table class="table table-hover"> 61 <table class="table table-hover">
65 <col width="100"> 62 <col width="100">
66 <thead> 63 <thead>
@@ -87,8 +84,8 @@ @@ -87,8 +84,8 @@
87 <td> <!-- student name --> 84 <td> <!-- student name -->
88 {{ ' '.join(r[1].split()[n] for n in (0,-1)) }} 85 {{ ' '.join(r[1].split()[n] for n in (0,-1)) }}
89 &nbsp; 86 &nbsp;
90 - {{ '<i class="fas fa-brain fa-2x text-success" title="Mais de 75% de respostas correctas"></i>' if r[3] > 0.75 else '' }}  
91 - {{ '<i class="fas fa-frown text-secondary" title="Menos de 50% de respostas correctas" ></i>' if 0.0 < r[3] < 0.5 else '' }} 87 + {{ '<i class="far fa-thumbs-up text-success" title="Mais de 75% de respostas correctas"></i>' if r[3] > 0.75 else '' }}
  88 + {{ '<i class="fas fa-bug" title="Menos de 50% de respostas correctas" ></i>' if 0.0 < r[3] < 0.5 else '' }}
92 </td> 89 </td>
93 <td> <!-- progress --> 90 <td> <!-- progress -->
94 <div class="progress"> 91 <div class="progress">
aprendizations/templates/topic.html
@@ -49,16 +49,16 @@ @@ -49,16 +49,16 @@
49 </button> 49 </button>
50 50
51 <div class="collapse navbar-collapse" id="navbarText"> 51 <div class="collapse navbar-collapse" id="navbarText">
52 - <ul class="navbar-nav mr-auto">  
53 - <li class="nav-item">  
54 - <a class="nav-link" href="/">Tópicos</a>  
55 - </li>  
56 - </ul> 52 + <div class="navbar-nav mr-auto">
  53 + <a class="nav-item nav-link" href="/courses">Cursos</a>
  54 + <a class="nav-item nav-link active" href="/course/{{course_id}}">Tópicos <span class="sr-only">(actual)</span></a>
  55 + <a class="nav-item nav-link" href="/rankings?course={{course_id}}">Classificação</a>
  56 + </div>
57 57
58 <ul class="navbar-nav"> 58 <ul class="navbar-nav">
59 <li class="nav-item dropdown"> 59 <li class="nav-item dropdown">
60 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 60 <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
61 - <i class="fas fa-user" aria-hidden="true"></i> 61 + <i class="fas fa-user-graduate" aria-hidden="true"></i>
62 <span id="name">{{ escape(name) }}</span> 62 <span id="name">{{ escape(name) }}</span>
63 <span class="caret"></span> 63 <span class="caret"></span>
64 </a> 64 </a>
package-lock.json
@@ -131,9 +131,9 @@ @@ -131,9 +131,9 @@
131 } 131 }
132 }, 132 },
133 "@fortawesome/fontawesome-free": { 133 "@fortawesome/fontawesome-free": {
134 - "version": "5.10.2",  
135 - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.10.2.tgz",  
136 - "integrity": "sha512-9pw+Nsnunl9unstGEHQ+u41wBEQue6XPBsILXtJF/4fNN1L3avJcMF/gGF86rIjeTAgfLjTY9ndm68/X4f4idQ==" 134 + "version": "5.11.2",
  135 + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.11.2.tgz",
  136 + "integrity": "sha512-XiUPoS79r1G7PcpnNtq85TJ7inJWe0v+b5oZJZKb0pGHNIV6+UiNeQWiFGmuQ0aj7GEhnD/v9iqxIsjuRKtEnQ=="
137 }, 137 },
138 "ansi-styles": { 138 "ansi-styles": {
139 "version": "3.2.1", 139 "version": "3.2.1",
@@ -154,9 +154,9 @@ @@ -154,9 +154,9 @@
154 } 154 }
155 }, 155 },
156 "codemirror": { 156 "codemirror": {
157 - "version": "5.48.4",  
158 - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.48.4.tgz",  
159 - "integrity": "sha512-pUhZXDQ6qXSpWdwlgAwHEkd4imA0kf83hINmUEzJpmG80T/XLtDDEzZo8f6PQLuRCcUQhmzqqIo3ZPTRaWByRA==" 157 + "version": "5.49.0",
  158 + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.0.tgz",
  159 + "integrity": "sha512-Hyzr0HToBdZpLBN9dYFO/KlJAsKH37/cXVHPAqa+imml0R92tb9AkmsvjnXL+SluEvjjdfkDgRjc65NG5jnMYA=="
160 }, 160 },
161 "color-convert": { 161 "color-convert": {
162 "version": "1.9.3", 162 "version": "1.9.3",
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 "description": "Javascript libraries required to run the server", 2 "description": "Javascript libraries required to run the server",
3 "email": "mjsb@uevora.pt", 3 "email": "mjsb@uevora.pt",
4 "dependencies": { 4 "dependencies": {
5 - "@fortawesome/fontawesome-free": "^5",  
6 - "codemirror": "^5.48", 5 + "@fortawesome/fontawesome-free": "^5.11.2",
  6 + "codemirror": "^5.49.0",
7 "mathjax": "^3", 7 "mathjax": "^3",
8 "mdbootstrap": "^4.8.10" 8 "mdbootstrap": "^4.8.10"
9 }, 9 },