Version 22.117: May 22, 2023 Teachers can allow comments in a survey question.

This commit is contained in:
acanas 2023-05-22 14:34:35 +02:00
parent 710a82e846
commit 1a1d0196b5
8 changed files with 315 additions and 206 deletions

View File

@ -1428,6 +1428,7 @@ CREATE TABLE IF NOT EXISTS svy_questions (
SvyCod INT NOT NULL,
QstInd INT NOT NULL DEFAULT 0,
AnsType ENUM('unique_choice','multiple_choice') NOT NULL,
CommentsAllowed ENUM('N','Y') NOT NULL DEFAULT 'N',
Stem TEXT NOT NULL,
UNIQUE INDEX(QstCod),
INDEX(SvyCod));

View File

@ -629,10 +629,14 @@ TODO: Emilce Barrera Mesa: Podr
TODO: Emilce Barrera Mesa: Mis estudiantes presentan muchas dificultades a la hora de poner la foto porque la plataforma es muy exigente respecto al fondo de la imagen.
*/
#define Log_PLATFORM_VERSION "SWAD 22.116.1 (2023-05-21)"
#define Log_PLATFORM_VERSION "SWAD 22.117 (2023-05-22)"
#define CSS_FILE "swad22.107.36.css"
#define JS_FILE "swad22.49.js"
/*
Version 22.117: May 22, 2023 Teachers can allow comments in a survey question. (337196 lines)
1 change necessary in database:
ALTER TABLE svy_questions ADD COLUMN CommentsAllowed ENUM('N','Y') NOT NULL DEFAULT 'N' AFTER AnsType;
Version 22.116.1: May 21, 2023 Rubrics only availables for superusers. (337098 lines)
Version 22.116: May 20, 2023 Changes in rubric scores. (337093 lines)
Version 22.115: May 19, 2023 Generalization of rubric scores. (337010 lines)

View File

@ -3058,22 +3058,24 @@ mysql> DESCRIBE svy_groups;
/***** Table svy_questions *****/
/*
mysql> DESCRIBE svy_questions;
+---------+-----------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-----------------------------------------+------+-----+---------+----------------+
| QstCod | int(11) | NO | PRI | NULL | auto_increment |
| SvyCod | int(11) | NO | MUL | NULL | |
| QstInd | int(11) | NO | | 0 | |
| AnsType | enum('unique_choice','multiple_choice') | NO | | NULL | |
| Stem | text | NO | | NULL | |
+---------+-----------------------------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
+-----------------+-----------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-----------------------------------------+------+-----+---------+----------------+
| QstCod | int | NO | PRI | NULL | auto_increment |
| SvyCod | int | NO | MUL | NULL | |
| QstInd | int | NO | | 0 | |
| AnsType | enum('unique_choice','multiple_choice') | NO | | NULL | |
| CommentsAllowed | enum('N','Y') | NO | | N | |
| Stem | text | NO | | NULL | |
+-----------------+-----------------------------------------+------+-----+---------+----------------+
6 rows in set (0,00 sec)
*/
DB_CreateTable ("CREATE TABLE IF NOT EXISTS svy_questions ("
"QstCod INT NOT NULL AUTO_INCREMENT,"
"SvyCod INT NOT NULL,"
"QstInd INT NOT NULL DEFAULT 0,"
"AnsType ENUM ('unique_choice','multiple_choice') NOT NULL,"
"CommentsAllowed ENUM('N','Y') NOT NULL DEFAULT 'N'"
"Stem TEXT NOT NULL," // Cns_MAX_BYTES_TEXT
"UNIQUE INDEX(QstCod),"
"INDEX(SvyCod))");

View File

@ -70,21 +70,6 @@ extern struct Globals Gbl;
#define Svy_MAX_BYTES_LIST_ANSWER_TYPES (Svy_NUM_ANS_TYPES * (Cns_MAX_DECIMAL_DIGITS_UINT + 1))
#define Svy_MAX_ANSWERS_PER_QUESTION 10
struct Svy_Question // Must be initialized to 0 before using it
{
long QstCod;
unsigned QstInd;
Svy_AnswerType_t AnswerType;
struct
{
char *Text;
} AnsChoice[Svy_MAX_ANSWERS_PER_QUESTION];
bool AllAnsTypes;
char ListAnsTypes[Svy_MAX_BYTES_LIST_ANSWER_TYPES + 1];
};
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
@ -136,6 +121,9 @@ static void Svy_WriteQstStem (const char *Stem);
static void Svy_WriteAnswersOfAQst (struct Svy_Survey *Svy,
struct Svy_Question *SvyQst,
bool PutFormAnswerSurvey);
static void Svy_WriteCommentsOfAQst (struct Svy_Survey *Svy,
struct Svy_Question *SvyQst,
bool PutFormAnswerSurvey);
static void Svy_DrawBarNumUsrs (unsigned NumUsrs,unsigned MaxUsrs);
static void Svy_PutIconToRemoveOneQst (void *Surveys);
@ -1229,33 +1217,36 @@ void Svy_GetSurveyDataByCod (struct Svy_Survey *Svy)
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_STD:
Svy->Status.ICanViewResults = ( Svy->Scope == HieLvl_CRS ||
Svy->Status.ICanViewResults = ( Svy->Scope == HieLvl_CRS ||
Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
( Svy->NumQsts != 0) &&
!Svy->Status.Hidden &&
Svy->Status.Open &&
Svy->Status.IAmLoggedWithAValidRoleToAnswer &&
Svy->Status.IBelongToScope &&
Svy->Status.IHaveAnswered;
Svy->Status.ICanViewComments = false;
Svy->Status.ICanEdit = false;
break;
case Rol_NET:
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->Scope == HieLvl_CRS ||
Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
( Svy->NumQsts != 0) &&
!Svy->Status.Hidden &&
Svy->Status.Open &&
Svy->Status.IAmLoggedWithAValidRoleToAnswer &&
Svy->Status.IBelongToScope &&
Svy->Status.IHaveAnswered;
Svy->Status.ICanEdit = false;
break;
case Rol_NET:
Svy->Status.ICanViewResults = (Svy->Scope == HieLvl_CRS ||
Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
Svy->NumQsts != 0 &&
!Svy->Status.ICanAnswer;
Svy->NumQsts != 0 &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = false;
break;
case Rol_TCH:
Svy->Status.ICanViewResults = (Svy->Scope == HieLvl_CRS ||
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->Scope == HieLvl_CRS ||
Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
@ -1266,42 +1257,47 @@ void Svy_GetSurveyDataByCod (struct Svy_Survey *Svy)
Svy->Status.ICanEdit = Svy->Scope == HieLvl_CRS; // && Svy->Status.IBelongToScope
break;
case Rol_DEG_ADM:
Svy->Status.ICanViewResults = (Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_DEG &&
Svy->Status.IBelongToScope;
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->Scope == HieLvl_DEG ||
Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_DEG &&
Svy->Status.IBelongToScope;
break;
case Rol_CTR_ADM:
Svy->Status.ICanViewResults = (Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_CTR &&
Svy->Status.IBelongToScope;
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->Scope == HieLvl_CTR ||
Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_CTR &&
Svy->Status.IBelongToScope;
break;
case Rol_INS_ADM:
Svy->Status.ICanViewResults = (Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_INS &&
Svy->Status.IBelongToScope;
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->Scope == HieLvl_INS ||
Svy->Scope == HieLvl_CTY ||
Svy->Scope == HieLvl_SYS) &&
(Svy->NumQsts != 0) &&
!Svy->Status.ICanAnswer;
Svy->Status.ICanEdit = Svy->Scope == HieLvl_INS &&
Svy->Status.IBelongToScope;
break;
case Rol_SYS_ADM:
Svy->Status.ICanViewResults = (Svy->NumQsts != 0);
Svy->Status.ICanEdit = true;
Svy->Status.ICanViewResults =
Svy->Status.ICanViewComments = (Svy->NumQsts != 0);
Svy->Status.ICanEdit = true;
break;
default:
Svy->Status.ICanViewResults = false;
Svy->Status.ICanEdit = false;
Svy->Status.ICanViewResults = false;
Svy->Status.ICanViewComments = false;
Svy->Status.ICanEdit = false;
break;
}
}
@ -1324,6 +1320,7 @@ void Svy_GetSurveyDataByCod (struct Svy_Survey *Svy)
Svy->Status.IHaveAnswered = false;
Svy->Status.ICanAnswer = false;
Svy->Status.ICanViewResults = false;
Svy->Status.ICanViewComments = false;
Svy->Status.ICanEdit = false;
}
@ -1666,6 +1663,7 @@ void Svy_ReqCreatOrEditSvy (void)
Surveys.Svy.Status.IHaveAnswered = false;
Surveys.Svy.Status.ICanAnswer = false;
Surveys.Svy.Status.ICanViewResults = false;
Surveys.Svy.Status.ICanViewComments = false;
}
else
{
@ -2265,6 +2263,9 @@ static void Svy_ShowFormEditOneQst (struct Svy_Surveys *Surveys,
extern const char *Txt_Wording;
extern const char *Txt_Type;
extern const char *Txt_SURVEY_STR_ANSWER_TYPES[Svy_NUM_ANS_TYPES];
extern const char *Txt_Options;
extern const char *Txt_Comments;
extern const char *Txt_Comments_allowed;
extern const char *Txt_Save_changes;
extern const char *Txt_Create;
MYSQL_RES *mysql_res;
@ -2380,10 +2381,13 @@ static void Svy_ShowFormEditOneQst (struct Svy_Surveys *Surveys,
/***** Answers *****/
HTM_TR_Begin (NULL);
HTM_TD_Empty (1);
HTM_TD_Begin ("class=\"RT FORM_IN_%s\"",The_GetSuffix ());
HTM_TxtColon (Txt_Options);
HTM_TD_End ();
/* Unique or multiple choice answers */
HTM_TD_Begin ("class=\"LT\"");
/* Unique or multiple choice answers */
HTM_TABLE_BeginPadding (2);
for (NumAns = 0;
NumAns < Svy_MAX_ANSWERS_PER_QUESTION;
@ -2411,6 +2415,26 @@ static void Svy_ShowFormEditOneQst (struct Svy_Surveys *Surveys,
HTM_TR_End ();
}
HTM_TABLE_End ();
HTM_TD_End ();
HTM_TR_End ();
/***** Comments allowed? *****/
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"RT FORM_IN_%s\"",The_GetSuffix ());
HTM_TxtColon (Txt_Comments);
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT FORM_IN_%s\"",The_GetSuffix ());
HTM_LABEL_Begin (NULL);
HTM_INPUT_CHECKBOX ("Comment",HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s",
SvyQst->CommentsAllowed ? " checked=\"checked\"" :
"");
HTM_Txt (Txt_Comments_allowed);
HTM_LABEL_End ();
HTM_TD_End ();
HTM_TR_End ();
@ -2449,6 +2473,7 @@ static void Svy_InitQst (struct Svy_Question *SvyQst)
NumAns < Svy_MAX_ANSWERS_PER_QUESTION;
NumAns++)
SvyQst->AnsChoice[NumAns].Text = NULL;
SvyQst->CommentsAllowed = false;
}
/*****************************************************************************/
@ -2504,14 +2529,12 @@ void Svy_ReceiveQst (void)
{
extern const char *Txt_You_must_type_the_question_stem;
extern const char *Txt_You_can_not_leave_empty_intermediate_answers;
extern const char *Txt_You_must_type_at_least_the_first_two_answers;
extern const char *Txt_The_survey_has_been_modified;
struct Svy_Surveys Surveys;
struct Svy_Question SvyQst;
char Stem[Cns_MAX_BYTES_TEXT + 1];
unsigned NumAns;
char AnsStr[8 + 10 + 1];
unsigned NumLastAns;
bool ThereIsEndOfAnswers;
bool Error = false;
@ -2550,40 +2573,25 @@ void Svy_ReceiveQst (void)
Par_GetParHTML (AnsStr,SvyQst.AnsChoice[NumAns].Text,Svy_MAX_BYTES_ANSWER);
}
/***** Make sure that stem and answer are not empty *****/
/* Get if comments are allowed */
SvyQst.CommentsAllowed = Par_GetParBool ("Comment");
/***** Make sure that stem is not empty *****/
if (Stem[0])
{
if (SvyQst.AnsChoice[0].Text[0]) // If the first answer has been filled
{
for (NumAns = 0, NumLastAns = 0, ThereIsEndOfAnswers = false;
!Error && NumAns < Svy_MAX_ANSWERS_PER_QUESTION;
NumAns++)
if (SvyQst.AnsChoice[NumAns].Text[0])
{
if (ThereIsEndOfAnswers)
{
Ale_ShowAlert (Ale_WARNING,Txt_You_can_not_leave_empty_intermediate_answers);
Error = true;
}
else
NumLastAns = NumAns;
}
else
ThereIsEndOfAnswers = true;
if (!Error)
{
if (NumLastAns < 1)
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
Error = true;
}
}
}
else // If first answer is empty
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
Error = true;
}
for (NumAns = 0, ThereIsEndOfAnswers = false;
!Error && NumAns < Svy_MAX_ANSWERS_PER_QUESTION;
NumAns++)
if (SvyQst.AnsChoice[NumAns].Text[0])
{
if (ThereIsEndOfAnswers)
{
Ale_ShowAlert (Ale_WARNING,Txt_You_can_not_leave_empty_intermediate_answers);
Error = true;
}
}
else
ThereIsEndOfAnswers = true;
}
else
{
@ -2599,12 +2607,11 @@ void Svy_ReceiveQst (void)
if (SvyQst.QstCod < 0) // It's a new question
{
SvyQst.QstInd = Svy_GetNextQuestionIndexInSvy (Surveys.Svy.SvyCod);
SvyQst.QstCod = Svy_DB_CreateQuestion (Surveys.Svy.SvyCod,SvyQst.QstInd,
SvyQst.AnswerType,Stem);
SvyQst.QstCod = Svy_DB_CreateQuestion (Surveys.Svy.SvyCod,&SvyQst,Stem);
}
else // It's an existing question
/* Update question */
Svy_DB_UpdateQuestion (Surveys.Svy.SvyCod,SvyQst.QstCod,SvyQst.AnswerType,Stem);
Svy_DB_UpdateQuestion (Surveys.Svy.SvyCod,&SvyQst,Stem);
/* Insert, update or delete answers in the answers table */
for (NumAns = 0;
@ -2774,6 +2781,9 @@ static void Svy_ListSvyQuestions (struct Svy_Surveys *Surveys)
The_GetColorRows ());
Svy_WriteQstStem (Stem);
Svy_WriteAnswersOfAQst (&Surveys->Svy,&SvyQst,PutFormAnswerSurvey);
if (SvyQst.CommentsAllowed)
Svy_WriteCommentsOfAQst (&Surveys->Svy,&SvyQst,PutFormAnswerSurvey);
HTM_TD_End ();
HTM_TR_End ();
@ -2823,8 +2833,11 @@ static void Svy_GetQstDataFromRow (MYSQL_RES *mysql_res,
/***** Get the answer type (row[2]) *****/
SvyQst->AnswerType = Svy_DB_ConvertFromStrAnsTypDBToAnsTyp (row[2]);
/***** Get the stem of the question from the database (row[3]) *****/
Str_Copy (Stem,row[3],Cns_MAX_BYTES_TEXT);
/***** Get whether the comments are allowed (row[3]) *****/
SvyQst->CommentsAllowed = (row[3][0] == 'Y');
/***** Get the stem of the question from the database (row[4]) *****/
Str_Copy (Stem,row[4],Cns_MAX_BYTES_TEXT);
}
/*****************************************************************************/
@ -2901,84 +2914,113 @@ static void Svy_WriteAnswersOfAQst (struct Svy_Survey *Svy,
/* Write one row for each answer */
HTM_TABLE_BeginPadding (5);
for (NumAns = 0;
NumAns < NumAnswers;
NumAns++)
{
row = mysql_fetch_row (mysql_res);
for (NumAns = 0;
NumAns < NumAnswers;
NumAns++)
{
row = mysql_fetch_row (mysql_res);
/* Get number of users who have marked this answer (row[1]) */
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
Err_ShowErrorAndExit ("Error when getting number of users who have marked an answer.");
/* Get number of users who have marked this answer (row[1]) */
if (sscanf (row[1],"%u",&NumUsrsThisAnswer) != 1)
Err_ShowErrorAndExit ("Error when getting number of users who have marked an answer.");
/* Convert the answer (row[2]), that is in HTML, to rigorous HTML */
if (!Svy_AllocateTextChoiceAnswer (SvyQst,NumAns))
/* Abort on error */
Ale_ShowAlertsAndExit ();
/* Convert the answer (row[2]), that is in HTML, to rigorous HTML */
if (!Svy_AllocateTextChoiceAnswer (SvyQst,NumAns))
/* Abort on error */
Ale_ShowAlertsAndExit ();
Str_Copy (SvyQst->AnsChoice[NumAns].Text,row[2],Svy_MAX_BYTES_ANSWER);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
SvyQst->AnsChoice[NumAns].Text,Svy_MAX_BYTES_ANSWER,false);
Str_Copy (SvyQst->AnsChoice[NumAns].Text,row[2],Svy_MAX_BYTES_ANSWER);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
SvyQst->AnsChoice[NumAns].Text,Svy_MAX_BYTES_ANSWER,false);
/* Selectors and label with the letter of the answer */
HTM_TR_Begin (NULL);
/* Selectors and label with the letter of the answer */
HTM_TR_Begin (NULL);
if (PutFormAnswerSurvey)
{
/* Write selector to choice this answer */
HTM_TD_Begin ("class=\"LT\"");
snprintf (StrAns,sizeof (StrAns),"Ans%010u",
(unsigned) SvyQst->QstCod);
if (SvyQst->AnswerType == Svy_ANS_UNIQUE_CHOICE)
HTM_INPUT_RADIO (StrAns,HTM_DONT_SUBMIT_ON_CLICK,
"id=\"Ans%010u_%010u\" value=\"%u\""
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u)\"",
(unsigned) SvyQst->QstCod,NumAns,NumAns,
NumAns,
(unsigned) SvyQst->QstCod,NumAnswers);
else // SvyQst->AnswerType == Svy_ANS_MULTIPLE_CHOICE
HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Ans%010u_%010u\" value=\"%u\"",
(unsigned) SvyQst->QstCod,NumAns,NumAns,
NumAns);
if (PutFormAnswerSurvey)
{
/* Write selector to choice this answer */
HTM_TD_Begin ("class=\"LT\"");
snprintf (StrAns,sizeof (StrAns),"Ans%010u",
(unsigned) SvyQst->QstCod);
switch (SvyQst->AnswerType)
{
case Svy_ANS_UNIQUE_CHOICE:
HTM_INPUT_RADIO (StrAns,HTM_DONT_SUBMIT_ON_CLICK,
"id=\"Ans%010u_%u\" value=\"%u\""
" onclick=\"selectUnselectRadio(this,this.form.Ans%010u,%u)\"",
(unsigned) SvyQst->QstCod,NumAns,NumAns,
(unsigned) SvyQst->QstCod,NumAnswers);
break;
case Svy_ANS_MULTIPLE_CHOICE:
HTM_INPUT_CHECKBOX (StrAns,HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Ans%010u_%u\" value=\"%u\"",
(unsigned) SvyQst->QstCod,NumAns,NumAns);
break;
default:
break;
}
HTM_TD_End ();
}
/* Write the number of option */
HTM_TD_Begin ("class=\"SVY_OPT LT\"");
HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"DAT_%s\"",
(unsigned) SvyQst->QstCod,NumAns,
The_GetSuffix ());
HTM_TxtF ("%u)",NumAns + 1);
HTM_LABEL_End ();
HTM_TD_End ();
}
/* Write the number of option */
HTM_TD_Begin ("class=\"SVY_OPT LT\"");
HTM_LABEL_Begin ("for=\"Ans%010u_%010u\" class=\"DAT_%s\"",
(unsigned) SvyQst->QstCod,NumAns,
The_GetSuffix ());
HTM_TxtF ("%u)",NumAns + 1);
HTM_LABEL_End ();
HTM_TD_End ();
/* Write the text of the answer */
HTM_TD_Begin ("class=\"LT\"");
HTM_LABEL_Begin ("for=\"Ans%010u_%u\" class=\"DAT_%s\"",
(unsigned) SvyQst->QstCod,NumAns,
The_GetSuffix ());
HTM_Txt (SvyQst->AnsChoice[NumAns].Text);
HTM_LABEL_End ();
HTM_TD_End ();
/* Write the text of the answer */
HTM_TD_Begin ("class=\"LT\"");
HTM_LABEL_Begin ("for=\"Ans%010u_%010u\" class=\"DAT_%s\"",
(unsigned) SvyQst->QstCod,NumAns,
The_GetSuffix ());
HTM_Txt (SvyQst->AnsChoice[NumAns].Text);
HTM_LABEL_End ();
HTM_TD_End ();
/* Show stats of this answer */
if (Svy->Status.ICanViewResults)
Svy_DrawBarNumUsrs (NumUsrsThisAnswer,Svy->NumUsrs);
/* Show stats of this answer */
if (Svy->Status.ICanViewResults)
Svy_DrawBarNumUsrs (NumUsrsThisAnswer,Svy->NumUsrs);
HTM_TR_End ();
HTM_TR_End ();
/* Free memory allocated for the answer */
Svy_FreeTextChoiceAnswer (SvyQst,NumAns);
}
/* Free memory allocated for the answer */
Svy_FreeTextChoiceAnswer (SvyQst,NumAns);
}
HTM_TABLE_End ();
}
else
HTM_BR ();
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/************** Get and write the answers of a survey question ***************/
/*****************************************************************************/
static void Svy_WriteCommentsOfAQst (struct Svy_Survey *Svy,
struct Svy_Question *SvyQst,
bool PutFormAnswerSurvey)
{
if (PutFormAnswerSurvey)
{
HTM_TEXTAREA_Begin ("name=\"Comments\""
" cols=\"60\" rows=\"4\""
" class=\"INPUT_%s\"",
The_GetSuffix ());
HTM_TEXTAREA_End ();
}
else if (Svy->Status.ICanViewComments)
{
HTM_Txt ("Comentarios..."); // TODO
}
}
/*****************************************************************************/
/***************** Draw a bar with the percentage of answers *****************/
/*****************************************************************************/

View File

@ -60,6 +60,7 @@ struct Svy_Survey
bool IHaveAnswered; // I have already answered this survey
bool ICanAnswer;
bool ICanViewResults;
bool ICanViewComments;
bool ICanEdit;
} Status;
};
@ -83,6 +84,19 @@ typedef enum
} Svy_AnswerType_t;
#define Svy_ANSWER_TYPE_DEFAULT Svy_ANS_UNIQUE_CHOICE
#define Svy_MAX_ANSWERS_PER_QUESTION 10
struct Svy_Question // Must be initialized to 0 before using it
{
long QstCod;
unsigned QstInd;
Svy_AnswerType_t AnswerType;
struct
{
char *Text;
} AnsChoice[Svy_MAX_ANSWERS_PER_QUESTION];
bool CommentsAllowed;
};
/*****************************************************************************/
/***************************** Public prototypes *****************************/
/*****************************************************************************/

View File

@ -836,19 +836,21 @@ void Svy_DB_RemoveGrpsSvysIn (HieLvl_Level_t Scope,long Cod)
/*************************** Create a new question ***************************/
/*****************************************************************************/
long Svy_DB_CreateQuestion (long SvyCod,unsigned QstInd,
Svy_AnswerType_t AnswerType,
long Svy_DB_CreateQuestion (long SvyCod,
const struct Svy_Question *SvyQst,
const char Stem[Cns_MAX_BYTES_TEXT + 1])
{
return
DB_QueryINSERTandReturnCode ("can not create question",
"INSERT INTO svy_questions"
" (SvyCod,QstInd,AnsType,Stem)"
" (SvyCod,QstInd,AnsType,CommentsAllowed,Stem)"
" VALUES"
" (%ld,%u,'%s','%s')",
" (%ld,%u,'%s','%c','%s')",
SvyCod,
QstInd,
Svy_DB_StrAnswerTypes[AnswerType],
SvyQst->QstInd,
Svy_DB_StrAnswerTypes[SvyQst->AnswerType],
SvyQst->CommentsAllowed ? 'Y' :
'N',
Stem);
}
@ -856,19 +858,22 @@ long Svy_DB_CreateQuestion (long SvyCod,unsigned QstInd,
/************************ Create an existing question ************************/
/*****************************************************************************/
void Svy_DB_UpdateQuestion (long SvyCod,long QstCod,
Svy_AnswerType_t AnswerType,
void Svy_DB_UpdateQuestion (long SvyCod,
const struct Svy_Question *SvyQst,
const char Stem[Cns_MAX_BYTES_TEXT + 1])
{
DB_QueryUPDATE ("can not update question",
"UPDATE svy_questions"
" SET Stem='%s',"
"AnsType='%s'"
"AnsType='%s',"
"CommentsAllowed='%c'"
" WHERE QstCod=%ld"
" AND SvyCod=%ld", // Extra check
Stem,
Svy_DB_StrAnswerTypes[AnswerType],
QstCod,
Svy_DB_StrAnswerTypes[SvyQst->AnswerType],
SvyQst->CommentsAllowed ? 'Y' :
'N',
SvyQst->QstCod,
SvyCod);
}
@ -924,10 +929,11 @@ unsigned Svy_DB_GetSurveyQsts (MYSQL_RES **mysql_res,long SvyCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get data of questions of a survey",
"SELECT QstCod," // row[0]
"QstInd," // row[1]
"AnsType," // row[2]
"Stem" // row[3]
"SELECT QstCod," // row[0]
"QstInd," // row[1]
"AnsType," // row[2]
"CommentsAllowed," // row[3]
"Stem" // row[4]
" FROM svy_questions"
" WHERE SvyCod=%ld"
" ORDER BY QstInd",
@ -942,10 +948,11 @@ unsigned Svy_DB_GetQstDataByCod (MYSQL_RES **mysql_res,long QstCod,long SvyCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get a question",
"SELECT QstCod," // row[0]
"QstInd," // row[1]
"AnsType," // row[2]
"Stem" // row[3]
"SELECT QstCod," // row[0]
"QstInd," // row[1]
"AnsType," // row[2]
"CommentsAllowed," // row[3]
"Stem" // row[4]
" FROM svy_questions"
" WHERE QstCod=%ld"
" AND SvyCod=%ld", // Extra check
@ -1110,10 +1117,7 @@ bool Svy_DB_CheckIfAnswerExists (long QstCod,unsigned AnsInd)
unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod)
{
unsigned NumAnswers;
/***** Get answers of a question from database *****/
NumAnswers = (unsigned)
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get answers of a question",
"SELECT AnsInd," // row[0]
"NumUsrs," // row[1]
@ -1122,10 +1126,6 @@ unsigned Svy_DB_GetAnswersQst (MYSQL_RES **mysql_res,long QstCod)
" WHERE QstCod=%ld"
" ORDER BY AnsInd",
QstCod);
if (!NumAnswers)
Err_WrongAnswerExit ();
return NumAnswers;
}
/*****************************************************************************/

View File

@ -73,11 +73,11 @@ void Svy_DB_RemoveGrpsAssociatedToSurvey (long SvyCod);
void Svy_DB_RemoveGrpsSvysIn (HieLvl_Level_t Scope,long Cod);
//--------------------------- Surveys questions -------------------------------
long Svy_DB_CreateQuestion (long SvyCod,unsigned QstInd,
Svy_AnswerType_t AnswerType,
long Svy_DB_CreateQuestion (long SvyCod,
const struct Svy_Question *SvyQst,
const char Stem[Cns_MAX_BYTES_TEXT + 1]);
void Svy_DB_UpdateQuestion (long SvyCod,long QstCod,
Svy_AnswerType_t AnswerType,
void Svy_DB_UpdateQuestion (long SvyCod,
const struct Svy_Question *SvyQst,
const char Stem[Cns_MAX_BYTES_TEXT + 1]);
void Svy_DB_ChangeIndexesQsts (long SvyCod,unsigned QstInd);

View File

@ -5429,7 +5429,30 @@ const char *Txt_Comments =
#elif L==9 // pt
"Coment&aacute;rios";
#elif L==10 // tr
"Comments"; // Çeviri lazim!
"Yorumlar";
#endif
const char *Txt_Comments_allowed =
#if L==1 // ca
"Comentaris permesos";
#elif L==2 // de
"Kommentare erlaubt";
#elif L==3 // en
"Comments allowed";
#elif L==4 // es
"Comentarios permitidos";
#elif L==5 // fr
"Commentaires autoris&eacute;s";
#elif L==6 // gn
"Ojeheja umi comentario";
#elif L==7 // it
"Commenti consentiti";
#elif L==8 // pl
"Komentarze dozwolone";
#elif L==9 // pt
"Coment&aacute;rios permitidos";
#elif L==10 // tr
"Yorumlara izin verilir";
#endif
const char *Txt_Configure_projects =
@ -28515,6 +28538,29 @@ const char *Txt_optional =
"optional"; // Çeviri lazim!
#endif
const char *Txt_Options =
#if L==1 // ca
"Opcions";
#elif L==2 // de
"Optionen";
#elif L==3 // en
"Options";
#elif L==4 // es
"Opciones";
#elif L==5 // fr
"Choix";
#elif L==6 // gn
"Opciones";
#elif L==7 // it
"Opzioni";
#elif L==8 // pl
"Opcje";
#elif L==9 // pt
"Op&ccedil;&otilde;es";
#elif L==10 // tr
"Se&ccedil;enekler";
#endif
const char *Txt_or_you_can_create_a_new_link_inside_the_folder_X = // Warning: it is very important to include %s in the following sentences
#if L==1 // ca
"&hellip;o pot crear un novo enlla&ccedil;"