Version19.246.1

This commit is contained in:
acanas 2020-05-25 00:18:09 +02:00
parent c2483d236f
commit d5f97b88e8
5 changed files with 157 additions and 74 deletions

View File

@ -550,7 +550,7 @@ function readConnUsrsData () {
/*****************************************************************************/
// This function is called when user changes an answer in an exam print
function updateExamPrint (idDiv,idInput,nameInput,Params,timeoutMsg) {
function updateExamPrint (idDiv,idInput,nameInput,Params,timeoutMsg,IHaveFinishedTxt,savingTxt) {
var objXMLHttp = false;
objXMLHttp = AJAXCreateObject ();
@ -559,7 +559,8 @@ function updateExamPrint (idDiv,idInput,nameInput,Params,timeoutMsg) {
objXMLHttp.onreadystatechange = function() { // onreadystatechange must be lowercase
if (objXMLHttp.readyState == 4) { // Check if data have been received
if (objXMLHttp.status == 200) {
clearTimeout (xmlHttpTimeout); // Response received ==> clear timeout
// Response received
clearTimeout (xmlHttpTimeout); // Clear timeout
if (idDiv) {
var div = document.getElementById(idDiv); // Access to DIV
if (div) {
@ -609,8 +610,11 @@ function updateExamPrint (idDiv,idInput,nameInput,Params,timeoutMsg) {
// Params += '&' + nameInput + '=' + encodeURIComponent(val); // UTF-8 escaped
// Params += '&' + nameInput + '=' + escape(val); // ISO-8859-1 escaped (deprecated)
Params += '&' + nameInput + '=' + getEscapedString(val); // ISO-8859-1 escaped, replacement for deprecated escape()
inputElem.value = '?'; // Reset while waiting response. If connection is broken ==> user will see ? input
}
}
disableFinished (savingTxt); // Disable finished button on sending. When answer is saved and response received ==> the button will be reloaded
objXMLHttp.open('POST',ActionAJAX,true);
objXMLHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
@ -624,6 +628,7 @@ function updateExamPrint (idDiv,idInput,nameInput,Params,timeoutMsg) {
function ajaxTimeout () {
objXMLHttp.abort ();
alert (timeoutMsg);
disableFinished (IHaveFinishedTxt); // Sending aborted ==> change "Saving..." to original "I have finished"
};
}
}
@ -685,6 +690,25 @@ for(var i=0;i<256;i++) {
console.table(arr);
//-----------------------------------------------------------------------------
*/
/*****************************************************************************/
/********* Disable button to finish exam when focus on a input text **********/
/*****************************************************************************/
function disableFinished (Txt) {
var f = document.getElementById('finished'); // Access to form
if (f)
for (var i = 0; i < f.elements.length; i++) {
var b = f.elements[i];
if (b.type == 'submit') {
b.disabled = true;
b.style.opacity = 0.5;
b.innerHTML = Txt;
}
}
}
/*****************************************************************************/
/********** Automatic refresh of current match question using AJAX ***********/
/*****************************************************************************/

View File

@ -557,10 +557,12 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - *
En OpenSWAD:
ps2pdf source.ps destination.pdf
*/
#define Log_PLATFORM_VERSION "SWAD 19.245 (2020-05-24)"
#define Log_PLATFORM_VERSION "SWAD 19.246.1 (2020-05-25)"
#define CSS_FILE "swad19.238.2.css"
#define JS_FILE "swad19.239.6.js"
#define JS_FILE "swad19.246.1.js"
/*
Version 19.246.1: May 25, 2020 Removed unused JavaScript code. (302515 lines)
Version 19.246: May 24, 2020 Fixed issue answering exam prints: when answer is been sent, button to send exam is disabled. (302527 lines)
Version 19.245: May 24, 2020 Session id is stored in a separated table. (302439 lines)
ALTER TABLE exa_log DROP COLUMN SessionId;
CREATE TABLE IF NOT EXISTS exa_log_session (LogCod INT NOT NULL,PrnCod INT NOT NULL,SessionId CHAR(43) NOT NULL,UNIQUE INDEX(LogCod),UNIQUE INDEX(PrnCod,LogCod));
@ -596,7 +598,7 @@ ALTER TABLE exa_log ENGINE=MyISAM;
Bug fixing and code refactoring in tests and exams. (301712 lines)
1 change necessary in database:
CREATE TABLE IF NOT EXISTS exa_log (LogCod INT NOT NULL,PrnCod INT NOT NULL,ActCod INT NOT NULL,ClickTime DATETIME NOT NULL,IP CHAR(15) NOT NULL,SessionId CHAR(43) NOT NULL,UNIQUE INDEX(LogCod),INDEX(PrnCod,ClickTime),INDEX(ClickTime));
--------------
Version 19.240: May 21, 2020 Code refactoring in tests and exams. (301428 lines)
Version 19.239.9: May 21, 2020 Fixed issue in exam sessions: exam prints in sessions of hidden exams are no accesible. (301441 lines)
Version 19.239.8: May 21, 2020 Fixed issue in exam sessions: a student can not see hidden sessions. (301433 lines)

View File

@ -27,6 +27,7 @@
#define _GNU_SOURCE // For asprintf
#include <stdio.h> // For asprintf
#include <stdlib.h> // For system, getenv, etc.
#include <string.h> // For string functions
#include "swad_action.h"
@ -278,6 +279,7 @@ static void ExaLog_LogUsrAgent (long LogCod,long PrnCod)
void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
{
extern const char *Txt_Hits;
extern const char *Txt_Click;
extern const char *Txt_Date_and_time;
extern const char *Txt_Action;
extern const char *Txt_Question;
@ -291,6 +293,7 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
unsigned NumClicks;
unsigned NumClick;
unsigned ActCod;
ExaLog_Action_t Action;
int QstInd;
bool UsrCouldAnswer;
time_t ClickTimeUTC;
@ -299,8 +302,9 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
size_t Length;
char Anonymized[14 + 1]; // ***&hellip;***
// 12345678901234
char LastSessionId[Cns_BYTES_SESSION_ID + 1];
char *LastUserAgent;
char SessionId[Cns_BYTES_SESSION_ID + 1];
char *UserAgent;
const char *Class;
/***** Check if I can view this print result *****/
switch (Gbl.Usrs.Me.Role.Logged)
@ -337,8 +341,8 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
if (NumClicks)
{
/***** Initialize last session id and last user agent ******/
LastSessionId[0] = '\0';
LastUserAgent = NULL;
SessionId[0] = '\0';
UserAgent = NULL;
/***** Begin box *****/
Box_BoxTableBegin (NULL,Txt_Hits,
@ -351,6 +355,7 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
/***** Write heading *****/
HTM_TR_Begin (NULL);
HTM_TH (1,1,"RB",Txt_Click);
HTM_TH (1,1,"LB",Txt_Date_and_time);
HTM_TH (1,1,"LB",Txt_Action);
HTM_TH (1,1,"RB",Txt_Question);
@ -373,8 +378,10 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
/* Get code of action (row[0]) */
ActCod = Str_ConvertStrToUnsigned (row[0]);
if (ActCod >= ExaLog_NUM_ACTIONS)
ActCod = ExaLog_UNKNOWN_ACTION;
if (ActCod < ExaLog_NUM_ACTIONS)
Action = (ExaLog_Action_t) ActCod;
else
Action = ExaLog_UNKNOWN_ACTION;
/* Get question index (row[1]) */
QstInd = (int) Str_ConvertStrCodToLongCod (row[1]);
@ -391,27 +398,50 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
/* Get session id (row[5]) */
if (row[5]) // This row has a user agent stored in database
Str_Copy (LastSessionId,row[5],
Str_Copy (SessionId,row[5],
Cns_BYTES_SESSION_ID);
else
Str_Copy (SessionId,"=",
Cns_BYTES_SESSION_ID);
/* Get session id (row[6]) */
if (row[6]) // This row has a user agent stored in database
{
if (LastUserAgent)
free (LastUserAgent);
if (asprintf (&LastUserAgent,"%s",row[6]) < 0)
Lay_NotEnoughMemoryExit ();
}
if (asprintf (&UserAgent,"%s",row[6] ? row[6] :
"=") < 0)
Lay_NotEnoughMemoryExit ();
/***** Set color of row depending on action *****/
if (UsrCouldAnswer)
switch (Action)
{
case ExaLog_START_EXAM:
case ExaLog_RESUME_EXAM:
case ExaLog_FINISH_EXAM:
Class = "DAT_SMALL_N";
break;
case ExaLog_ANSWER_QUESTION:
Class = "DAT_SMALL";
break;
default:
Class = "DAT_SMALL_LIGHT";
break;
}
else // Closed or not accesible exam print
Class = "DAT_SMALL_LIGHT";
/***** Write row *****/
HTM_TR_Begin (NULL);
/* Write number of click */
HTM_TD_Begin ("class=\"RT COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
HTM_Unsigned (NumClick + 1);
HTM_TD_End ();
/* Write click time */
if (asprintf (&Id,"click_date_%u",NumClick) < 0)
Lay_NotEnoughMemoryExit ();
HTM_TD_Begin ("id=\"%s\" class=\"LT COLOR%u %s\"",
Id,Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
HTM_TD_Begin ("id=\"%s\" class=\"LT COLOR%u %s\"",Id,Gbl.RowEvenOdd,Class);
Dat_WriteLocalDateHMSFromUTC (Id,ClickTimeUTC,
Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA,
true,true,true,0x7);
@ -419,16 +449,12 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
HTM_TD_End ();
/* Write action */
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
HTM_Txt (Txt_EXAM_LOG_ACTIONS[ActCod]);
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",Gbl.RowEvenOdd,Class);
HTM_Txt (Txt_EXAM_LOG_ACTIONS[Action]);
HTM_TD_End ();
/* Write number of question */
HTM_TD_Begin ("class=\"RT COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
HTM_TD_Begin ("class=\"RT COLOR%u %s\"",Gbl.RowEvenOdd,Class);
if (QstInd >= 0)
HTM_Unsigned ((unsigned) QstInd + 1);
HTM_TD_End ();
@ -442,9 +468,7 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
HTM_TD_End ();
/* Write IP */
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",Gbl.RowEvenOdd,Class);
Length = strlen (IP);
if (Length > 6)
{
@ -462,44 +486,40 @@ void ExaLog_ShowExamLog (const struct ExaPrn_Print *Print)
HTM_TD_End ();
/* Write session id */
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
Length = strlen (LastSessionId);
if (Length > 6)
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",Gbl.RowEvenOdd,Class);
if (SessionId[0])
{
sprintf (Anonymized,"%c%c%c&hellip;%c%c%c",
LastSessionId[0],
LastSessionId[1],
LastSessionId[2],
LastSessionId[Length - 3],
LastSessionId[Length - 2],
LastSessionId[Length - 1]);
HTM_Txt (Anonymized);
Length = strlen (SessionId);
if (Length > 6)
{
sprintf (Anonymized,"%c%c%c&hellip;%c%c%c",
SessionId[0],
SessionId[1],
SessionId[2],
SessionId[Length - 3],
SessionId[Length - 2],
SessionId[Length - 1]);
HTM_Txt (Anonymized);
}
else
HTM_Txt (SessionId);
}
else
HTM_Txt (LastSessionId);
HTM_TD_End ();
/* Write user agent (row[6]) */
HTM_TD_Begin ("class=\"LM COLOR%u %s\"",
Gbl.RowEvenOdd,UsrCouldAnswer ? "DAT_SMALL" :
"DAT_SMALL_LIGHT");
if (LastUserAgent)
HTM_Txt (LastUserAgent);
else
HTM_Txt ("?");
HTM_TD_Begin ("class=\"LT COLOR%u %s\"",Gbl.RowEvenOdd,Class);
if (UserAgent[0])
HTM_Txt (UserAgent);
HTM_TD_End ();
HTM_TR_End ();
/***** Free user agent *****/
free (UserAgent);
}
/***** End table and box *****/
Box_BoxTableEnd ();
/***** Free user agent *****/
if (LastUserAgent)
free (LastUserAgent);
}
/***** Free structure that stores the query result *****/

View File

@ -80,7 +80,8 @@ static void ExaPrn_ShowExamPrintToFillIt (struct Exa_Exams *Exams,
const struct Exa_Exam *Exam,
const struct ExaPrn_Print *Print);
static void ExaPrn_GetAndWriteDescription (long ExaCod);
static void ExaPrn_ShowTableWithQstsToFill (const struct ExaPrn_Print *Print);
static void ExaPrn_ShowTableWithQstsToFill (struct Exa_Exams *Exams,
const struct ExaPrn_Print *Print);
static void ExaPrn_WriteQstAndAnsToFill (const struct ExaPrn_Print *Print,
unsigned NumQst,
const struct Tst_Question *Question);
@ -607,7 +608,6 @@ static void ExaPrn_ShowExamPrintToFillIt (struct Exa_Exams *Exams,
const struct ExaPrn_Print *Print)
{
extern const char *Hlp_ASSESSMENT_Exams;
extern const char *Txt_I_have_finished;
/***** Begin box *****/
Box_BoxBegin (NULL,Exam->Title,
@ -625,14 +625,8 @@ static void ExaPrn_ShowExamPrintToFillIt (struct Exa_Exams *Exams,
{
/***** Show table with questions to answer *****/
HTM_DIV_Begin ("id=\"examprint\""); // Used for AJAX based refresh
ExaPrn_ShowTableWithQstsToFill (Print);
ExaPrn_ShowTableWithQstsToFill (Exams,Print);
HTM_DIV_End (); // Used for AJAX based refresh
/***** Form to end/close this exam print *****/
Frm_StartForm (ActEndExaPrn);
ExaSes_PutParamsEdit (Exams);
Btn_PutCreateButton (Txt_I_have_finished);
Frm_EndForm ();
}
/***** End box *****/
@ -663,8 +657,10 @@ static void ExaPrn_GetAndWriteDescription (long ExaCod)
/********* Show the main part (table) of an exam print to be answered ********/
/*****************************************************************************/
static void ExaPrn_ShowTableWithQstsToFill (const struct ExaPrn_Print *Print)
static void ExaPrn_ShowTableWithQstsToFill (struct Exa_Exams *Exams,
const struct ExaPrn_Print *Print)
{
extern const char *Txt_I_have_finished;
unsigned NumQst;
struct Tst_Question Question;
@ -692,6 +688,12 @@ static void ExaPrn_ShowTableWithQstsToFill (const struct ExaPrn_Print *Print)
/***** End table *****/
HTM_TABLE_End ();
/***** Form to end/close this exam print *****/
Frm_StartFormId (ActEndExaPrn,"finished");
ExaSes_PutParamsEdit (Exams);
Btn_PutCreateButton (Txt_I_have_finished);
Frm_EndForm ();
}
/*****************************************************************************/
@ -945,6 +947,7 @@ static void ExaPrn_WriteTxtAnsToFill (const struct ExaPrn_Print *Print,
Id,Tst_MAX_CHARS_ANSWERS_ONE_QST,
Print->PrintedQuestions[NumQst].StrAnswers);
ExaPrn_WriteJSToUpdateExamPrint (Print,NumQst,Id,-1);
HTM_Txt (" />");
}
@ -957,19 +960,21 @@ static void ExaPrn_WriteJSToUpdateExamPrint (const struct ExaPrn_Print *Print,
const char *Id,int NumOpt)
{
extern const char *Txt_Connection_issues_;
extern const char *Txt_I_have_finished;
extern const char *Txt_Saving_;
if (NumOpt < 0)
HTM_TxtF (" onchange=\"updateExamPrint('examprint','%s','Ans',"
"'act=%ld&ses=%s&SesCod=%ld&NumQst=%u','%s');",
"'act=%ld&ses=%s&SesCod=%ld&NumQst=%u','%s','%s','%s');",
Id,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->SesCod,NumQst,
Txt_Connection_issues_);
Txt_Connection_issues_,Txt_I_have_finished,Txt_Saving_);
else // NumOpt >= 0
HTM_TxtF (" onclick=\"updateExamPrint('examprint','%s_%d','Ans',"
"'act=%ld&ses=%s&SesCod=%ld&NumQst=%u','%s');",
"'act=%ld&ses=%s&SesCod=%ld&NumQst=%u','%s','%s','%s');",
Id,NumOpt,
Act_GetActCod (ActAnsExaPrn),Gbl.Session.Id,Print->SesCod,NumQst,
Txt_Connection_issues_);
Txt_Connection_issues_,Txt_I_have_finished,Txt_Saving_);
HTM_Txt (" return false;\""); // return false is necessary to not submit form
}
@ -980,12 +985,15 @@ static void ExaPrn_WriteJSToUpdateExamPrint (const struct ExaPrn_Print *Print,
void ExaPrn_ReceivePrintAnswer (void)
{
extern const char *Txt_You_dont_have_access_to_the_exam;
extern const char *Txt_Continue;
struct Exa_Exams Exams;
struct Exa_Exam Exam;
struct ExaSes_Session Session;
struct ExaPrn_Print Print;
unsigned QstInd;
/***** Reset exam, session and print *****/
/***** Reset exams context *****/
Exa_ResetExams (&Exams);
Exa_ResetExam (&Exam);
ExaSes_ResetSession (&Session);
ExaPrn_ResetPrint (&Print);
@ -1004,6 +1012,7 @@ void ExaPrn_ReceivePrintAnswer (void)
ExaSes_GetDataOfSessionByCod (&Session);
if (Session.SesCod <= 0)
Lay_WrongExamExit ();
Exams.SesCod = Session.SesCod;
/***** Get exam data *****/
Exam.ExaCod = Session.ExaCod;
@ -1012,6 +1021,7 @@ void ExaPrn_ReceivePrintAnswer (void)
Lay_WrongExamExit ();
if (Exam.CrsCod != Gbl.Hierarchy.Crs.CrsCod)
Lay_WrongExamExit ();
Exams.ExaCod = Exam.ExaCod;
/***** Get question index from form *****/
QstInd = ExaPrn_GetParamQstInd ();
@ -1043,7 +1053,7 @@ void ExaPrn_ReceivePrintAnswer (void)
ExaPrn_UpdatePrintInDB (&Print);
/***** Show table with questions to answer *****/
ExaPrn_ShowTableWithQstsToFill (&Print);
ExaPrn_ShowTableWithQstsToFill (&Exams,&Print);
}
else // Not accessible to answer
{
@ -1052,6 +1062,12 @@ void ExaPrn_ReceivePrintAnswer (void)
/***** Show warning *****/
Ale_ShowAlert (Ale_INFO,Txt_You_dont_have_access_to_the_exam);
/***** Form to end/close this exam print *****/
Frm_StartForm (ActEndExaPrn);
ExaSes_PutParamsEdit (&Exams);
Btn_PutCreateButton (Txt_Continue);
Frm_EndForm ();
}
}

View File

@ -40648,6 +40648,27 @@ const char *Txt_Save_file_properties =
"Salvar as propriedades do arquivo";
#endif
const char *Txt_Saving_ =
#if L==1 // ca
"Desant&hellip;";
#elif L==2 // de
"Speichern&hellip;";
#elif L==3 // en
"Saving&hellip;";
#elif L==4 // es
"Guardando&hellip;";
#elif L==5 // fr
"Enregistrement&hellip;";
#elif L==6 // gn
"Guardando&hellip;"; // Okoteve traducción
#elif L==7 // it
"Salvataggio&hellip;";
#elif L==8 // pl
"Zapisywanie&hellip;";
#elif L==9 // pt
"Salvando&hellip;";
#endif
const char *Txt_Scope =
#if L==1 // ca
"&Agrave;mbit";