// swad_record.c: users' record cards
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2019 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include // For PATH_MAX
#include // For NULL
#include // For calloc
#include
#include "swad_account.h"
#include "swad_action.h"
#include "swad_box.h"
#include "swad_config.h"
#include "swad_database.h"
#include "swad_enrolment.h"
#include "swad_follow.h"
#include "swad_form.h"
#include "swad_global.h"
#include "swad_HTML.h"
#include "swad_ID.h"
#include "swad_logo.h"
#include "swad_network.h"
#include "swad_parameter.h"
#include "swad_photo.h"
#include "swad_privacy.h"
#include "swad_QR.h"
#include "swad_record.h"
#include "swad_role.h"
#include "swad_setting.h"
#include "swad_user.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
#define Rec_INSTITUTION_LOGO_SIZE 64
#define Rec_DEGREE_LOGO_SIZE 64
#define Rec_USR_MIN_AGE 12 // years old
#define Rec_USR_MAX_AGE 120 // years old
#define Rec_SHOW_OFFICE_HOURS_DEFAULT true
#define Rec_MY_INS_CTR_DPT_ID "my_ins_ctr_dpt_section"
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Rec_WriteHeadingRecordFields (void);
static void Rec_PutParamFielCod (void);
static void Rec_GetFieldByCod (long FieldCod,char Name[Rec_MAX_BYTES_NAME_FIELD + 1],
unsigned *NumLines,Rec_VisibilityRecordFields_t *Visibility);
static void Rec_ListRecordsGsts (Rec_SharedRecordViewType_t TypeOfView);
static void Rec_ShowRecordOneStdCrs (void);
static void Rec_ListRecordsStds (Rec_SharedRecordViewType_t ShaTypeOfView,
Rec_CourseRecordViewType_t CrsTypeOfView);
static void Rec_ShowRecordOneTchCrs (void);
static void Rec_ListRecordsTchs (Rec_SharedRecordViewType_t TypeOfView);
static void Rec_ShowLinkToPrintPreviewOfRecords (void);
static void Rec_GetParamRecordsPerPage (void);
static void Rec_WriteFormShowOfficeHoursOneTch (bool ShowOfficeHours);
static void Rec_WriteFormShowOfficeHoursSeveralTchs (bool ShowOfficeHours);
static void Rec_PutParamsShowOfficeHoursOneTch (void);
static void Rec_PutParamsShowOfficeHoursSeveralTchs (void);
static bool Rec_GetParamShowOfficeHours (void);
static void Rec_ShowCrsRecord (Rec_CourseRecordViewType_t TypeOfView,
struct UsrData *UsrDat,const char *Anchor);
static void Rec_ShowMyCrsRecordUpdated (void);
static bool Rec_CheckIfICanEditField (Rec_VisibilityRecordFields_t Visibility);
static void Rec_PutIconsCommands (void);
static void Rec_PutParamsMyTsts (void);
static void Rec_PutParamsStdTsts (void);
static void Rec_PutParamsWorks (void);
static void Rec_PutParamsStudent (void);
static void Rec_PutParamsMsgUsr (void);
static void Rec_ShowInstitutionInHead (struct Instit *Ins,bool PutFormLinks);
static void Rec_ShowPhoto (struct UsrData *UsrDat);
static void Rec_ShowFullName (struct UsrData *UsrDat);
static void Rec_ShowNickname (struct UsrData *UsrDat,bool PutFormLinks);
static void Rec_ShowCountryInHead (struct UsrData *UsrDat,bool ShowData);
static void Rec_ShowWebsAndSocialNets (struct UsrData *UsrDat,
Rec_SharedRecordViewType_t TypeOfView);
static void Rec_ShowEmail (struct UsrData *UsrDat,const char *ClassForm);
static void Rec_ShowUsrIDs (struct UsrData *UsrDat,const char *ClassForm,
const char *Anchor);
static void Rec_ShowRole (struct UsrData *UsrDat,
Rec_SharedRecordViewType_t TypeOfView,
const char *ClassForm);
static void Rec_ShowSurname1 (struct UsrData *UsrDat,
Rec_SharedRecordViewType_t TypeOfView,
bool ICanEdit,
const char *ClassForm);
static void Rec_ShowSurname2 (struct UsrData *UsrDat,
bool ICanEdit,
const char *ClassForm);
static void Rec_ShowFirstName (struct UsrData *UsrDat,
Rec_SharedRecordViewType_t TypeOfView,
bool ICanEdit,
const char *ClassForm);
static void Rec_ShowCountry (struct UsrData *UsrDat,
Rec_SharedRecordViewType_t TypeOfView,
const char *ClassForm);
static void Rec_ShowOriginPlace (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowDateOfBirth (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowLocalAddress (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowLocalPhone (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowFamilyAddress (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowFamilyPhone (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowComments (struct UsrData *UsrDat,
bool ShowData,bool ICanEdit,
const char *ClassForm);
static void Rec_ShowTeacherRows (struct UsrData *UsrDat,
struct Instit *Ins,
bool ShowData,const char *ClassForm);
static void Rec_ShowInstitution (struct Instit *Ins,
bool ShowData,const char *ClassForm);
static void Rec_ShowCentre (struct UsrData *UsrDat,
bool ShowData,const char *ClassForm);
static void Rec_ShowDepartment (struct UsrData *UsrDat,
bool ShowData,const char *ClassForm);
static void Rec_ShowOffice (struct UsrData *UsrDat,
bool ShowData,const char *ClassForm);
static void Rec_ShowOfficePhone (struct UsrData *UsrDat,
bool ShowData,const char *ClassForm);
static void Rec_WriteLinkToDataProtectionClause (void);
static void Rec_GetUsrExtraDataFromRecordForm (struct UsrData *UsrDat);
static void Rec_GetUsrCommentsFromForm (struct UsrData *UsrDat);
static void Rec_ShowFormMyInsCtrDpt (bool IAmATeacher);
/*****************************************************************************/
/*************** Create, edit and remove fields of records *******************/
/*****************************************************************************/
void Rec_ReqEditRecordFields (void)
{
extern const char *Hlp_USERS_Students_course_record_card;
extern const char *Txt_There_are_no_record_fields_in_the_course_X;
extern const char *Txt_Record_fields;
/***** Get list of fields of records in current course *****/
Rec_GetListRecordFieldsInCurrentCrs ();
/***** List the current fields of records for edit them *****/
if (Gbl.Crs.Records.LstFields.Num) // Fields found...
{
/* Begin box and table */
Box_StartBoxTable (NULL,Txt_Record_fields,NULL,
Hlp_USERS_Students_course_record_card,Box_NOT_CLOSABLE,2);
Rec_ListFieldsRecordsForEdition ();
/* End table and box */
Box_EndBoxTable ();
}
else // No fields of records found for current course in the database
Ale_ShowAlert (Ale_INFO,Txt_There_are_no_record_fields_in_the_course_X,
Gbl.Hierarchy.Crs.FullName);
/***** Put a form to create a new record field *****/
Rec_ShowFormCreateRecordField ();
/* Free list of fields of records */
Rec_FreeListFields ();
}
/*****************************************************************************/
/****** Create a list with the fields of records from current course *********/
/*****************************************************************************/
void Rec_GetListRecordFieldsInCurrentCrs (void)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRow;
unsigned Vis;
if (++Gbl.Crs.Records.LstFields.NestedCalls > 1) // If the list is already created, don't do anything
return;
/***** Get fields of records in a course from database *****/
Gbl.Crs.Records.LstFields.Num =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get fields of records"
" in a course",
"SELECT FieldCod,FieldName,NumLines,Visibility"
" FROM crs_record_fields"
" WHERE CrsCod=%ld ORDER BY FieldName",
Gbl.Hierarchy.Crs.CrsCod);
/***** Get the fields of records *****/
if (Gbl.Crs.Records.LstFields.Num)
{
/***** Create a list of fields *****/
if ((Gbl.Crs.Records.LstFields.Lst = (struct RecordField *) calloc (Gbl.Crs.Records.LstFields.Num,sizeof (struct RecordField))) == NULL)
Lay_NotEnoughMemoryExit ();
/***** Get the fields *****/
for (NumRow = 0;
NumRow < Gbl.Crs.Records.LstFields.Num;
NumRow++)
{
/* Get next field */
row = mysql_fetch_row (mysql_res);
/* Get the code of field (row[0]) */
if ((Gbl.Crs.Records.LstFields.Lst[NumRow].FieldCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of field.");
/* Name of the field (row[1]) */
Str_Copy (Gbl.Crs.Records.LstFields.Lst[NumRow].Name,row[1],
Rec_MAX_BYTES_NAME_FIELD);
/* Number of lines (row[2]) */
Gbl.Crs.Records.LstFields.Lst[NumRow].NumLines = Rec_ConvertToNumLinesField (row[2]);
/* Visible or editable by students? (row[3]) */
if (sscanf (row[3],"%u",&Vis) != 1)
Lay_ShowErrorAndExit ("Error when getting field of record in current course.");
if (Vis < Rec_NUM_TYPES_VISIBILITY)
Gbl.Crs.Records.LstFields.Lst[NumRow].Visibility = (Rec_VisibilityRecordFields_t) Vis;
else
Gbl.Crs.Records.LstFields.Lst[NumRow].Visibility = Rec_VISIBILITY_DEFAULT;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********* List the fields of records already present in database ************/
/*****************************************************************************/
void Rec_ListFieldsRecordsForEdition (void)
{
extern const char *Txt_RECORD_FIELD_VISIBILITY_MENU[Rec_NUM_TYPES_VISIBILITY];
unsigned NumField;
Rec_VisibilityRecordFields_t Vis;
/***** Write heading *****/
Rec_WriteHeadingRecordFields ();
/***** List the fields *****/
for (NumField = 0;
NumField < Gbl.Crs.Records.LstFields.Num;
NumField++)
{
HTM_TR_Begin (NULL);
/* Write icon to remove the field */
HTM_TD_Begin ("class=\"BM\"");
Frm_StartForm (ActReqRemFie);
Par_PutHiddenParamLong ("FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod);
Ico_PutIconRemove ();
Frm_EndForm ();
HTM_TD_End ();
/* Name of the field */
HTM_TD_Begin ("class=\"LM\"");
Frm_StartForm (ActRenFie);
Par_PutHiddenParamLong ("FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod);
fprintf (Gbl.F.Out,"",
Rec_MAX_CHARS_NAME_FIELD,
Gbl.Crs.Records.LstFields.Lst[NumField].Name,
Gbl.Form.Id);
Frm_EndForm ();
HTM_TD_End ();
/* Number of lines in the form */
HTM_TD_Begin ("class=\"CM\"");
Frm_StartForm (ActChgRowFie);
Par_PutHiddenParamLong ("FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod);
fprintf (Gbl.F.Out,"",
Gbl.Crs.Records.LstFields.Lst[NumField].NumLines,
Gbl.Form.Id);
Frm_EndForm ();
HTM_TD_End ();
/* Visibility of a field */
HTM_TD_Begin ("class=\"CM\"");
Frm_StartForm (ActChgVisFie);
Par_PutHiddenParamLong ("FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod);
fprintf (Gbl.F.Out,"");
Frm_EndForm ();
HTM_TD_End ();
HTM_TR_End ();
}
}
/*****************************************************************************/
/******************* Show form to create a new record field ******************/
/*****************************************************************************/
void Rec_ShowFormCreateRecordField (void)
{
extern const char *Hlp_USERS_Students_course_record_card;
extern const char *Txt_New_record_field;
extern const char *Txt_RECORD_FIELD_VISIBILITY_MENU[Rec_NUM_TYPES_VISIBILITY];
extern const char *Txt_Create_record_field;
Rec_VisibilityRecordFields_t Vis;
/***** Begin form *****/
Frm_StartForm (ActNewFie);
/***** Begin box and table *****/
Box_StartBoxTable (NULL,Txt_New_record_field,NULL,
Hlp_USERS_Students_course_record_card,Box_NOT_CLOSABLE,2);
/***** Write heading *****/
Rec_WriteHeadingRecordFields ();
/***** Write disabled icon to remove the field *****/
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"BM\"");
Ico_PutIconRemovalNotAllowed ();
HTM_TD_End ();
/***** Field name *****/
HTM_TD_Begin ("class=\"LM\"");
fprintf (Gbl.F.Out,"",
Rec_MAX_CHARS_NAME_FIELD,Gbl.Crs.Records.Field.Name);
HTM_TD_End ();
/***** Number of lines in form ******/
HTM_TD_Begin ("class=\"CM\"");
fprintf (Gbl.F.Out,"",
Gbl.Crs.Records.Field.NumLines);
HTM_TD_End ();
/***** Visibility to students *****/
HTM_TD_Begin ("class=\"CM\"");
fprintf (Gbl.F.Out,"");
HTM_TD_End ();
HTM_TR_End ();
/***** End table, send button and end box *****/
Box_EndBoxTableWithButton (Btn_CREATE_BUTTON,Txt_Create_record_field);
/***** End form *****/
Frm_EndForm ();
}
/*****************************************************************************/
/************************** Write heading of groups **************************/
/*****************************************************************************/
static void Rec_WriteHeadingRecordFields (void)
{
extern const char *Txt_Field_BR_name;
extern const char *Txt_No_of_BR_lines;
extern const char *Txt_Visible_by_BR_the_student;
HTM_TR_Begin (NULL);
HTM_TH_Empty (1);
HTM_TH (1,1,"CM",Txt_Field_BR_name);
HTM_TH (1,1,"CM",Txt_No_of_BR_lines);
HTM_TH (1,1,"CM",Txt_Visible_by_BR_the_student);
HTM_TR_End ();
}
/*****************************************************************************/
/*************** Receive data from a form of record fields *******************/
/*****************************************************************************/
void Rec_ReceiveFormField (void)
{
extern const char *Txt_The_record_field_X_already_exists;
extern const char *Txt_You_must_specify_the_name_of_the_new_record_field;
/***** Get parameters from the form *****/
/* Get the name of the field */
Par_GetParToText ("FieldName",Gbl.Crs.Records.Field.Name,
Rec_MAX_BYTES_NAME_FIELD);
/* Get the number of lines */
Gbl.Crs.Records.Field.NumLines = (unsigned)
Par_GetParToUnsignedLong ("NumLines",
Rec_MIN_LINES_IN_EDITION_FIELD,
Rec_MAX_LINES_IN_EDITION_FIELD,
Rec_DEF_LINES_IN_EDITION_FIELD);
/* Get the field visibility by students */
Gbl.Crs.Records.Field.Visibility = (Rec_VisibilityRecordFields_t)
Par_GetParToUnsignedLong ("Visibility",
0,
Rec_NUM_TYPES_VISIBILITY - 1,
(unsigned long) Rec_VISIBILITY_DEFAULT);
if (Gbl.Crs.Records.Field.Name[0]) // If there's a name
{
/***** If the field already was in the database... *****/
if (Rec_CheckIfRecordFieldIsRepeated (Gbl.Crs.Records.Field.Name))
Ale_ShowAlert (Ale_ERROR,Txt_The_record_field_X_already_exists,
Gbl.Crs.Records.Field.Name);
else // Add the new field to the database
Rec_CreateRecordField ();
}
else // If there is not name
Ale_ShowAlert (Ale_ERROR,Txt_You_must_specify_the_name_of_the_new_record_field);
/***** Show the form again *****/
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/********* Get number of lines of the form to edit a record field ************/
/*****************************************************************************/
unsigned Rec_ConvertToNumLinesField (const char *StrNumLines)
{
int NumLines;
if (sscanf (StrNumLines,"%d",&NumLines) != 1)
return Rec_DEF_LINES_IN_EDITION_FIELD;
else if (NumLines < Rec_MIN_LINES_IN_EDITION_FIELD)
return Rec_MIN_LINES_IN_EDITION_FIELD;
else if (NumLines > Rec_MAX_LINES_IN_EDITION_FIELD)
return Rec_MAX_LINES_IN_EDITION_FIELD;
return (unsigned) NumLines;
}
/*****************************************************************************/
/* Check if the name of the field of record equals any of the existing ones **/
/*****************************************************************************/
bool Rec_CheckIfRecordFieldIsRepeated (const char *FieldName)
{
bool FieldIsRepeated = false;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRow,NumRows;
/* Query database */
if ((NumRows = Rec_GetAllFieldsInCurrCrs (&mysql_res)) > 0) // If se han encontrado groups...
/* Compare with all the tipos of group from the database */
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next type of group */
row = mysql_fetch_row (mysql_res);
/* The name of the field is in row[1] */
if (!strcasecmp (FieldName,row[1]))
{
FieldIsRepeated = true;
break;
}
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
return FieldIsRepeated;
}
/*****************************************************************************/
/******* Get the fields of records already present in current course *********/
/*****************************************************************************/
unsigned long Rec_GetAllFieldsInCurrCrs (MYSQL_RES **mysql_res)
{
/***** Get fields of records in current course from database *****/
return DB_QuerySELECT (mysql_res,"can not get fields of records"
" in a course",
"SELECT FieldCod,FieldName,Visibility"
" FROM crs_record_fields"
" WHERE CrsCod=%ld ORDER BY FieldName",
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/************************* Create a field of record **************************/
/*****************************************************************************/
void Rec_CreateRecordField (void)
{
extern const char *Txt_Created_new_record_field_X;
/***** Create the new field *****/
DB_QueryINSERT ("can not create field of record",
"INSERT INTO crs_record_fields"
" (CrsCod,FieldName,NumLines,Visibility)"
" VALUES"
" (%ld,'%s',%u,%u)",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Crs.Records.Field.Name,
Gbl.Crs.Records.Field.NumLines,
(unsigned) Gbl.Crs.Records.Field.Visibility);
/***** Write message of success *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_record_field_X,
Gbl.Crs.Records.Field.Name);
}
/*****************************************************************************/
/**************** Request the removing of a field of records *****************/
/*****************************************************************************/
void Rec_ReqRemField (void)
{
unsigned NumRecords;
/***** Get the code of field *****/
if ((Gbl.Crs.Records.Field.FieldCod = Rec_GetFieldCod ()) == -1)
Lay_ShowErrorAndExit ("Code of field is missing.");
/***** Check if exists any record with that field filled *****/
if ((NumRecords = Rec_CountNumRecordsInCurrCrsWithField (Gbl.Crs.Records.Field.FieldCod))) // There are records with that field filled
Rec_AskConfirmRemFieldWithRecords (NumRecords);
else // There are no records with that field filled
Rec_RemoveFieldFromDB ();
}
/*****************************************************************************/
/************ Get a parameter with a code of field of records ****************/
/*****************************************************************************/
long Rec_GetFieldCod (void)
{
/***** Get the code of the field *****/
return Par_GetParToLong ("FieldCod");
}
/*****************************************************************************/
/*************** Get the number of records with a field filled ***************/
/*****************************************************************************/
unsigned Rec_CountNumRecordsInCurrCrsWithField (long FieldCod)
{
/***** Get number of cards with a given field in a course from database *****/
return
(unsigned) DB_QueryCOUNT ("can not get number of records"
" with a given field not empty in a course",
"SELECT COUNT(*) FROM crs_records"
" WHERE FieldCod=%ld",
FieldCod);
}
/*****************************************************************************/
/******* Request confirmation for the removing of a field with records *******/
/*****************************************************************************/
void Rec_AskConfirmRemFieldWithRecords (unsigned NumRecords)
{
extern const char *Txt_Do_you_really_want_to_remove_the_field_X_from_the_records_of_Y_Z_;
extern const char *Txt_Remove_record_field;
/***** Get from the database the name of the field *****/
Rec_GetFieldByCod (Gbl.Crs.Records.Field.FieldCod,
Gbl.Crs.Records.Field.Name,
&Gbl.Crs.Records.Field.NumLines,
&Gbl.Crs.Records.Field.Visibility);
/***** Show question and button to remove my photo *****/
Ale_ShowAlertAndButton (ActRemFie,NULL,NULL,Rec_PutParamFielCod,
Btn_REMOVE_BUTTON,Txt_Remove_record_field,
Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_field_X_from_the_records_of_Y_Z_,
Gbl.Crs.Records.Field.Name,Gbl.Hierarchy.Crs.FullName,
NumRecords);
/***** List record fields again *****/
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/************** Remove from the database a field of records ******************/
/*****************************************************************************/
void Rec_RemoveFieldFromDB (void)
{
extern const char *Txt_Record_field_X_removed;
/***** Get from the database the name of the field *****/
Rec_GetFieldByCod (Gbl.Crs.Records.Field.FieldCod,
Gbl.Crs.Records.Field.Name,
&Gbl.Crs.Records.Field.NumLines,
&Gbl.Crs.Records.Field.Visibility);
/***** Remove field from all records *****/
DB_QueryDELETE ("can not remove field from all students' records",
"DELETE FROM crs_records WHERE FieldCod=%ld",
Gbl.Crs.Records.Field.FieldCod);
/***** Remove the field *****/
DB_QueryDELETE ("can not remove field of record",
"DELETE FROM crs_record_fields WHERE FieldCod=%ld",
Gbl.Crs.Records.Field.FieldCod);
/***** Write message to show the change made *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_Record_field_X_removed,
Gbl.Crs.Records.Field.Name);
/***** Show the form again *****/
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/********************** Put parameter with field code ************************/
/*****************************************************************************/
static void Rec_PutParamFielCod (void)
{
Par_PutHiddenParamLong ("FieldCod",Gbl.Crs.Records.Field.FieldCod);
}
/*****************************************************************************/
/************** Get the data of a field of records from its code *************/
/*****************************************************************************/
static void Rec_GetFieldByCod (long FieldCod,char Name[Rec_MAX_BYTES_NAME_FIELD + 1],
unsigned *NumLines,Rec_VisibilityRecordFields_t *Visibility)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
unsigned Vis;
/***** Get a field of a record in a course from database *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get a field of a record"
" in a course",
"SELECT FieldName,NumLines,Visibility"
" FROM crs_record_fields"
" WHERE CrsCod=%ld AND FieldCod=%ld",
Gbl.Hierarchy.Crs.CrsCod,FieldCod);
/***** Count number of rows in result *****/
if (NumRows != 1)
Lay_ShowErrorAndExit ("Error when getting a field of a record in a course.");
/***** Get the field *****/
row = mysql_fetch_row (mysql_res);
/* Name of the field */
Str_Copy (Name,row[0],
Rec_MAX_BYTES_NAME_FIELD);
/* Number of lines of the field (row[1]) */
*NumLines = Rec_ConvertToNumLinesField (row[1]);
/* Visible or editable by students? (row[2]) */
if (sscanf (row[2],"%u",&Vis) != 1)
Lay_ShowErrorAndExit ("Error when getting a field of a record in a course.");
if (Vis < Rec_NUM_TYPES_VISIBILITY)
*Visibility = (Rec_VisibilityRecordFields_t) Vis;
else
*Visibility = Rec_VISIBILITY_DEFAULT;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/************************* Remove a field of records *************************/
/*****************************************************************************/
void Rec_RemoveField (void)
{
/***** Get the code of the field *****/
if ((Gbl.Crs.Records.Field.FieldCod = Rec_GetFieldCod ()) == -1)
Lay_ShowErrorAndExit ("Code of field is missing.");
/***** Borrarlo from the database *****/
Rec_RemoveFieldFromDB ();
}
/*****************************************************************************/
/************************** Rename a field of records ************************/
/*****************************************************************************/
void Rec_RenameField (void)
{
extern const char *Txt_You_can_not_leave_the_name_of_the_field_X_empty;
extern const char *Txt_The_record_field_X_already_exists;
extern const char *Txt_The_record_field_X_has_been_renamed_as_Y;
extern const char *Txt_The_name_of_the_field_X_has_not_changed;
char NewFieldName[Rec_MAX_BYTES_NAME_FIELD + 1];
/***** Get parameters of the form *****/
/* Get the code of the field */
if ((Gbl.Crs.Records.Field.FieldCod = Rec_GetFieldCod ()) == -1)
Lay_ShowErrorAndExit ("Code of field is missing.");
/* Get the new group name */
Par_GetParToText ("FieldName",NewFieldName,Rec_MAX_BYTES_NAME_FIELD);
/***** Get from the database the old field name *****/
Rec_GetFieldByCod (Gbl.Crs.Records.Field.FieldCod,
Gbl.Crs.Records.Field.Name,
&Gbl.Crs.Records.Field.NumLines,
&Gbl.Crs.Records.Field.Visibility);
/***** Check if new name is empty *****/
if (!NewFieldName[0])
Ale_ShowAlert (Ale_ERROR,Txt_You_can_not_leave_the_name_of_the_field_X_empty,
Gbl.Crs.Records.Field.Name);
else
{
/***** Check if the name of the olde field match the new one
(this happens when return is pressed without changes) *****/
if (strcmp (Gbl.Crs.Records.Field.Name,NewFieldName)) // Different names
{
/***** If the group ya estaba in the database... *****/
if (Rec_CheckIfRecordFieldIsRepeated (NewFieldName))
Ale_ShowAlert (Ale_ERROR,Txt_The_record_field_X_already_exists,
NewFieldName);
else
{
/* Update the table of fields changing then old name by the new one */
DB_QueryUPDATE ("can not update name of field of record",
"UPDATE crs_record_fields SET FieldName='%s'"
" WHERE FieldCod=%ld",
NewFieldName,Gbl.Crs.Records.Field.FieldCod);
/***** Write message to show the change made *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_The_record_field_X_has_been_renamed_as_Y,
Gbl.Crs.Records.Field.Name,NewFieldName);
}
}
else // The same name
Ale_ShowAlert (Ale_INFO,Txt_The_name_of_the_field_X_has_not_changed,
NewFieldName);
}
/***** Show the form again *****/
Str_Copy (Gbl.Crs.Records.Field.Name,NewFieldName,
Rec_MAX_BYTES_NAME_FIELD);
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/********* Change number of lines of the form of a field of records **********/
/*****************************************************************************/
void Rec_ChangeLinesField (void)
{
extern const char *Txt_The_number_of_editing_lines_in_the_record_field_X_has_not_changed;
extern const char *Txt_From_now_on_the_number_of_editing_lines_of_the_field_X_is_Y;
unsigned NewNumLines;
/***** Get parameters of the form *****/
/* Get the code of field */
if ((Gbl.Crs.Records.Field.FieldCod = Rec_GetFieldCod ()) == -1)
Lay_ShowErrorAndExit ("Code of field is missing.");
/* Get the new number of lines */
NewNumLines = (unsigned)
Par_GetParToUnsignedLong ("NumLines",
Rec_MIN_LINES_IN_EDITION_FIELD,
Rec_MAX_LINES_IN_EDITION_FIELD,
Rec_DEF_LINES_IN_EDITION_FIELD);
/* Get from the database the number of lines of the field */
Rec_GetFieldByCod (Gbl.Crs.Records.Field.FieldCod,Gbl.Crs.Records.Field.Name,&Gbl.Crs.Records.Field.NumLines,&Gbl.Crs.Records.Field.Visibility);
/***** Check if the old number of rows matches the new one
(this happens when return is pressed without changes) *****/
if (Gbl.Crs.Records.Field.NumLines == NewNumLines)
Ale_ShowAlert (Ale_INFO,Txt_The_number_of_editing_lines_in_the_record_field_X_has_not_changed,
Gbl.Crs.Records.Field.Name);
else
{
/***** Update of the table of fields changing the old maximum of students by the new one *****/
DB_QueryUPDATE ("can not update the number of lines of a record field",
"UPDATE crs_record_fields SET NumLines=%u"
" WHERE FieldCod=%ld",
NewNumLines,Gbl.Crs.Records.Field.FieldCod);
/***** Write message to show the change made *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_From_now_on_the_number_of_editing_lines_of_the_field_X_is_Y,
Gbl.Crs.Records.Field.Name,NewNumLines);
}
/***** Show the form again *****/
Gbl.Crs.Records.Field.NumLines = NewNumLines;
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/************ Change wisibility by students of a field of records ************/
/*****************************************************************************/
void Rec_ChangeVisibilityField (void)
{
extern const char *Txt_The_visibility_of_the_record_field_X_has_not_changed;
extern const char *Txt_RECORD_FIELD_VISIBILITY_MSG[Rec_NUM_TYPES_VISIBILITY];
Rec_VisibilityRecordFields_t NewVisibility;
/***** Get parameters of the form *****/
/* Get the code of field */
if ((Gbl.Crs.Records.Field.FieldCod = Rec_GetFieldCod ()) == -1)
Lay_ShowErrorAndExit ("Code of field is missing.");
/* Get the new visibility of the field */
NewVisibility = (Rec_VisibilityRecordFields_t)
Par_GetParToUnsignedLong ("Visibility",
0,
Rec_NUM_TYPES_VISIBILITY - 1,
(unsigned long) Rec_VISIBILITY_DEFAULT);
/* Get from the database the visibility of the field */
Rec_GetFieldByCod (Gbl.Crs.Records.Field.FieldCod,Gbl.Crs.Records.Field.Name,&Gbl.Crs.Records.Field.NumLines,&Gbl.Crs.Records.Field.Visibility);
/***** Check if the old visibility matches the new one
(this happens when return is pressed without changes) *****/
if (Gbl.Crs.Records.Field.Visibility == NewVisibility)
Ale_ShowAlert (Ale_INFO,Txt_The_visibility_of_the_record_field_X_has_not_changed,
Gbl.Crs.Records.Field.Name);
else
{
/***** Update of the table of fields changing the old visibility by the new *****/
DB_QueryUPDATE ("can not update the visibility of a record field",
"UPDATE crs_record_fields SET Visibility=%u"
" WHERE FieldCod=%ld",
(unsigned) NewVisibility,
Gbl.Crs.Records.Field.FieldCod);
/***** Write message to show the change made *****/
Ale_ShowAlert (Ale_SUCCESS,Txt_RECORD_FIELD_VISIBILITY_MSG[NewVisibility],
Gbl.Crs.Records.Field.Name);
}
/***** Show the form again *****/
Gbl.Crs.Records.Field.Visibility = NewVisibility;
Rec_ReqEditRecordFields ();
}
/*****************************************************************************/
/********************** Liberar list of fields of records ********************/
/*****************************************************************************/
void Rec_FreeListFields (void)
{
if (Gbl.Crs.Records.LstFields.NestedCalls > 0)
if (--Gbl.Crs.Records.LstFields.NestedCalls == 0)
if (Gbl.Crs.Records.LstFields.Lst)
{
free ((void *) Gbl.Crs.Records.LstFields.Lst);
Gbl.Crs.Records.LstFields.Lst = NULL;
Gbl.Crs.Records.LstFields.Num = 0;
}
}
/*****************************************************************************/
/******************* Put a link to list official students ********************/
/*****************************************************************************/
void Rec_PutLinkToEditRecordFields (void)
{
extern const char *Txt_Edit_record_fields;
/***** Link to edit record fields *****/
Lay_PutContextualLinkIconText (ActEdiRecFie,NULL,NULL,
"pen.svg",
Txt_Edit_record_fields);
}
/*****************************************************************************/
/*********************** Draw records of several guests **********************/
/*****************************************************************************/
void Rec_ListRecordsGstsShow (void)
{
Gbl.Action.Original = ActSeeRecSevGst; // Used to know where to go when confirming ID
Rec_ListRecordsGsts (Rec_SHA_RECORD_LIST);
}
void Rec_ListRecordsGstsPrint (void)
{
/***** List records ready to be printed *****/
Rec_ListRecordsGsts (Rec_SHA_RECORD_PRINT);
}
static void Rec_ListRecordsGsts (Rec_SharedRecordViewType_t TypeOfView)
{
unsigned NumUsr = 0;
const char *Ptr;
struct UsrData UsrDat;
char RecordSectionId[32];
/***** Get list of selected users if not already got *****/
Usr_GetListsSelectedUsrsCods ();
/***** Assign users listing type depending on current action *****/
Gbl.Usrs.Listing.RecsUsrs = Rec_RECORD_USERS_GUESTS;
/***** Get parameter with number of user records per page (only for printing) *****/
if (TypeOfView == Rec_SHA_RECORD_PRINT)
Rec_GetParamRecordsPerPage ();
if (TypeOfView == Rec_SHA_RECORD_LIST) // Listing several records
{
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
/* Print view */
Frm_StartForm (ActPrnRecSevGst);
Usr_PutHiddenParSelectedUsrsCods ();
Rec_ShowLinkToPrintPreviewOfRecords ();
Frm_EndForm ();
Mnu_ContextMenuEnd ();
}
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
UsrDat.Accepted = false; // Guests have no courses,...
// ...so they have not accepted...
// ...inscription in any course
/***** List the records *****/
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
while (*Ptr)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,UsrDat.EncryptedUsrCod,
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
Usr_GetUsrCodFromEncryptedUsrCod (&UsrDat);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS)) // Get from the database the data of the student
{
/* Start container for this user */
snprintf (RecordSectionId,sizeof (RecordSectionId),
"record_%u",
NumUsr);
HTM_SECTION_Begin (RecordSectionId);
if (Gbl.Action.Act == ActPrnRecSevGst &&
NumUsr != 0 &&
(NumUsr % Gbl.Usrs.Listing.RecsPerPag) == 0)
HTM_DIV_Begin ("class=\"REC_USR\" style=\"page-break-before:always;\"");
else
HTM_DIV_Begin ("class=\"REC_USR\"");
/* Show optional alert */
if (UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod) // Selected user
Ale_ShowAlerts (NULL);
/* Shared record */
HTM_DIV_Begin ("class=\"REC_LEFT\"");
Rec_ShowSharedUsrRecord (TypeOfView,&UsrDat,RecordSectionId);
HTM_DIV_End ();
/* End container for this user */
HTM_DIV_End ();
HTM_SECTION_End ();
NumUsr++;
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
/***** Free memory used by list of selected users' codes *****/
Usr_FreeListsSelectedUsrsCods ();
}
/*****************************************************************************/
/********** Get user's data and draw record of one unique student ************/
/*****************************************************************************/
void Rec_GetUsrAndShowRecOneStdCrs (void)
{
/***** Get the selected student *****/
Usr_GetParamOtherUsrCodEncryptedAndGetListIDs ();
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS)) // Get from the database the data of the student
if (Usr_CheckIfICanViewRecordStd (&Gbl.Usrs.Other.UsrDat))
Rec_ShowRecordOneStdCrs ();
}
/*****************************************************************************/
/******************** Draw record of one unique student **********************/
/*****************************************************************************/
static void Rec_ShowRecordOneStdCrs (void)
{
bool ItsMe;
/***** Get if student has accepted enrolment in current course *****/
Gbl.Usrs.Other.UsrDat.Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (&Gbl.Usrs.Other.UsrDat);
/***** Assign users listing type depending on current action *****/
Gbl.Usrs.Listing.RecsUsrs = Rec_RECORD_USERS_STUDENTS;
/***** Get list of fields of records in current course *****/
Rec_GetListRecordFieldsInCurrentCrs ();
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
/* Edit record fields */
if (Gbl.Usrs.Me.Role.Logged == Rol_TCH)
Rec_PutLinkToEditRecordFields ();
/* Print view */
Frm_StartForm (ActPrnRecSevStd);
Usr_CreateListSelectedUsrsCodsAndFillWithOtherUsr ();
Usr_PutHiddenParSelectedUsrsCods ();
Usr_FreeListsSelectedUsrsCods ();
Rec_ShowLinkToPrintPreviewOfRecords ();
Frm_EndForm ();
Mnu_ContextMenuEnd ();
/***** Show optional alert (result of editing data in course record) *****/
Ale_ShowAlerts (NULL);
/***** Start container for this user *****/
HTM_DIV_Begin ("class=\"REC_USR\"");
/***** Shared record *****/
HTM_DIV_Begin ("class=\"REC_LEFT\"");
Rec_ShowSharedUsrRecord (Rec_SHA_RECORD_LIST,&Gbl.Usrs.Other.UsrDat,NULL);
HTM_DIV_End ();
/***** Record of the student in the course *****/
if (Gbl.Crs.Records.LstFields.Num) // There are fields in the record
{
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_STD:
ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod);
if (ItsMe)
{
HTM_DIV_Begin ("class=\"REC_RIGHT\"");
Rec_ShowCrsRecord (Rec_CRS_MY_RECORD_AS_STUDENT_FORM,&Gbl.Usrs.Other.UsrDat,NULL);
HTM_DIV_End ();
}
break;
case Rol_NET:
case Rol_TCH:
case Rol_SYS_ADM:
HTM_DIV_Begin ("class=\"REC_RIGHT\"");
Rec_ShowCrsRecord (Rec_CRS_LIST_ONE_RECORD,&Gbl.Usrs.Other.UsrDat,NULL);
HTM_DIV_End ();
break;
default:
break;
}
}
/***** End container for this user *****/
HTM_DIV_End ();
/***** Free list of fields of records *****/
Rec_FreeListFields ();
}
/*****************************************************************************/
/******************** Draw records of several students ***********************/
/*****************************************************************************/
void Rec_ListRecordsStdsShow (void)
{
Gbl.Action.Original = ActSeeRecSevStd; // Used to know where to go when confirming ID...
// ...or changing course record
Rec_ListRecordsStds (Rec_SHA_RECORD_LIST,
Rec_CRS_LIST_SEVERAL_RECORDS);
}
void Rec_ListRecordsStdsPrint (void)
{
/***** List records ready to be printed *****/
Rec_ListRecordsStds (Rec_SHA_RECORD_PRINT,
Rec_CRS_PRINT_SEVERAL_RECORDS);
}
static void Rec_ListRecordsStds (Rec_SharedRecordViewType_t ShaTypeOfView,
Rec_CourseRecordViewType_t CrsTypeOfView)
{
unsigned NumUsr = 0;
const char *Ptr;
struct UsrData UsrDat;
bool ItsMe;
char RecordSectionId[32];
/***** Get list of selected users if not already got *****/
Usr_GetListsSelectedUsrsCods ();
/***** Assign users listing type depending on current action *****/
Gbl.Usrs.Listing.RecsUsrs = Rec_RECORD_USERS_STUDENTS;
/***** Get parameter with number of user records per page (only for printing) *****/
if (ShaTypeOfView == Rec_SHA_RECORD_PRINT)
Rec_GetParamRecordsPerPage ();
/***** Get list of fields of records in current course *****/
Rec_GetListRecordFieldsInCurrentCrs ();
if (ShaTypeOfView == Rec_SHA_RECORD_LIST)
{
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
/* Edit record fields */
if (Gbl.Usrs.Me.Role.Logged == Rol_TCH)
Rec_PutLinkToEditRecordFields ();
/* Print view */
Frm_StartForm (ActPrnRecSevStd);
Usr_PutHiddenParSelectedUsrsCods ();
Rec_ShowLinkToPrintPreviewOfRecords ();
Frm_EndForm ();
Mnu_ContextMenuEnd ();
}
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** List the records *****/
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
while (*Ptr)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,UsrDat.EncryptedUsrCod,
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
Usr_GetUsrCodFromEncryptedUsrCod (&UsrDat);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS)) // Get from the database the data of the student
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
{
/* Check if this user has accepted
his/her inscription in the current course */
UsrDat.Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (&UsrDat);
/* Start container for this user */
snprintf (RecordSectionId,sizeof (RecordSectionId),
"record_%u",
NumUsr);
HTM_SECTION_Begin (RecordSectionId);
if (Gbl.Action.Act == ActPrnRecSevStd &&
NumUsr != 0 &&
(NumUsr % Gbl.Usrs.Listing.RecsPerPag) == 0)
HTM_DIV_Begin ("class=\"REC_USR\" style=\"page-break-before:always;\"");
else
HTM_DIV_Begin ("class=\"REC_USR\"");
/* Show optional alert */
if (UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod) // Selected user
Ale_ShowAlerts (NULL);
/* Shared record */
HTM_DIV_Begin ("class=\"REC_LEFT\"");
Rec_ShowSharedUsrRecord (ShaTypeOfView,&UsrDat,RecordSectionId);
HTM_DIV_End ();
/* Record of the student in the course */
if (Gbl.Crs.Records.LstFields.Num) // There are fields in the record
{
ItsMe = Usr_ItsMe (UsrDat.UsrCod);
if ( Gbl.Usrs.Me.Role.Logged == Rol_NET ||
Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM ||
(Gbl.Usrs.Me.Role.Logged == Rol_STD && // I am student in this course...
ItsMe)) // ...and it's me
{
HTM_DIV_Begin ("class=\"REC_RIGHT\"");
Rec_ShowCrsRecord (CrsTypeOfView,&UsrDat,RecordSectionId);
HTM_DIV_End ();
}
}
/* End container for this user */
HTM_DIV_End ();
HTM_SECTION_End ();
NumUsr++;
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
/***** Free list of fields of records *****/
Rec_FreeListFields ();
/***** Free memory used by list of selected users' codes *****/
Usr_FreeListsSelectedUsrsCods ();
}
/*****************************************************************************/
/********** Get user's data and draw record of one unique teacher ************/
/*****************************************************************************/
void Rec_GetUsrAndShowRecOneTchCrs (void)
{
/***** Get the selected teacher *****/
Usr_GetParamOtherUsrCodEncryptedAndGetListIDs ();
/***** Show the record *****/
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS)) // Get from the database the data of the teacher
if (Usr_CheckIfICanViewRecordTch (&Gbl.Usrs.Other.UsrDat))
Rec_ShowRecordOneTchCrs ();
}
/*****************************************************************************/
/******************** Draw record of one unique teacher **********************/
/*****************************************************************************/
static void Rec_ShowRecordOneTchCrs (void)
{
extern const char *Hlp_USERS_Teachers_timetable;
extern const char *Txt_TIMETABLE_TYPES[TT_NUM_TIMETABLE_TYPES];
char Width[10 + 2 + 1];
bool ShowOfficeHours;
/***** Width for office hours *****/
snprintf (Width,sizeof (Width),
"%upx",
Rec_RECORD_WIDTH);
/***** Get if teacher has accepted enrolment in current course *****/
Gbl.Usrs.Other.UsrDat.Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (&Gbl.Usrs.Other.UsrDat);
/***** Assign users listing type depending on current action *****/
Gbl.Usrs.Listing.RecsUsrs = Rec_RECORD_USERS_TEACHERS;
/***** Get if I want to see teachers' office hours in teachers' records *****/
ShowOfficeHours = Rec_GetParamShowOfficeHours ();
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
/* Show office hours? */
Rec_WriteFormShowOfficeHoursOneTch (ShowOfficeHours);
/* Print view */
Frm_StartForm (ActPrnRecSevTch);
Usr_CreateListSelectedUsrsCodsAndFillWithOtherUsr ();
Usr_PutHiddenParSelectedUsrsCods ();
Usr_FreeListsSelectedUsrsCods ();
Par_PutHiddenParamChar ("ParamOfficeHours",'Y');
Par_PutHiddenParamChar ("ShowOfficeHours",ShowOfficeHours ? 'Y' :
'N');
Rec_ShowLinkToPrintPreviewOfRecords ();
Frm_EndForm ();
Mnu_ContextMenuEnd ();
/***** Start container for this user *****/
HTM_DIV_Begin ("class=\"REC_USR\"");
/***** Shared record *****/
HTM_DIV_Begin ("class=\"REC_LEFT\"");
Rec_ShowSharedUsrRecord (Rec_SHA_RECORD_LIST,&Gbl.Usrs.Other.UsrDat,NULL);
HTM_DIV_End ();
/***** Office hours *****/
if (ShowOfficeHours)
{
HTM_DIV_Begin ("class=\"REC_RIGHT\"");
Gbl.TimeTable.Type = TT_TUTORING_TIMETABLE;
Box_BoxBegin (Width,Txt_TIMETABLE_TYPES[Gbl.TimeTable.Type],NULL,
Hlp_USERS_Teachers_timetable,Box_NOT_CLOSABLE);
TT_ShowTimeTable (Gbl.Usrs.Other.UsrDat.UsrCod);
Box_BoxEnd ();
HTM_DIV_End ();
}
/***** Start container for this user *****/
HTM_DIV_End ();
}
/*****************************************************************************/
/******************** Draw records of several teachers ***********************/
/*****************************************************************************/
void Rec_ListRecordsTchsShow (void)
{
Gbl.Action.Original = ActSeeRecSevTch; // Used to know where to go when confirming ID
Rec_ListRecordsTchs (Rec_SHA_RECORD_LIST);
}
void Rec_ListRecordsTchsPrint (void)
{
/***** List records ready to be printed *****/
Rec_ListRecordsTchs (Rec_SHA_RECORD_PRINT);
}
static void Rec_ListRecordsTchs (Rec_SharedRecordViewType_t TypeOfView)
{
extern const char *Hlp_USERS_Teachers_timetable;
extern const char *Txt_TIMETABLE_TYPES[TT_NUM_TIMETABLE_TYPES];
unsigned NumUsr = 0;
const char *Ptr;
struct UsrData UsrDat;
char RecordSectionId[32];
bool ShowOfficeHours;
char Width[10 + 2 + 1];
/***** Get list of selected users if not already got *****/
Usr_GetListsSelectedUsrsCods ();
/***** Width for office hours *****/
snprintf (Width,sizeof (Width),
"%upx",
Rec_RECORD_WIDTH);
/***** Assign users listing type depending on current action *****/
Gbl.Usrs.Listing.RecsUsrs = Rec_RECORD_USERS_TEACHERS;
/***** Get if I want to see teachers' office hours in teachers' records *****/
ShowOfficeHours = Rec_GetParamShowOfficeHours ();
/***** Get parameter with number of user records per page (only for printing) *****/
if (Gbl.Action.Act == ActPrnRecSevTch)
Rec_GetParamRecordsPerPage ();
if (Gbl.Action.Act == ActSeeRecSevTch)
{
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
/* Show office hours? */
Rec_WriteFormShowOfficeHoursSeveralTchs (ShowOfficeHours);
/* Print view */
Frm_StartForm (ActPrnRecSevTch);
Usr_PutHiddenParSelectedUsrsCods ();
Par_PutHiddenParamChar ("ParamOfficeHours",'Y');
Par_PutHiddenParamChar ("ShowOfficeHours",
ShowOfficeHours ? 'Y' :
'N');
Rec_ShowLinkToPrintPreviewOfRecords ();
Frm_EndForm ();
Mnu_ContextMenuEnd ();
}
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** List the records *****/
Ptr = Gbl.Usrs.Selected.List[Rol_UNK];
while (*Ptr)
{
Par_GetNextStrUntilSeparParamMult (&Ptr,UsrDat.EncryptedUsrCod,
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
Usr_GetUsrCodFromEncryptedUsrCod (&UsrDat);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS)) // Get from the database the data of the student
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
{
/* Check if this user has accepted
his/her inscription in the current course */
UsrDat.Accepted = Usr_CheckIfUsrHasAcceptedInCurrentCrs (&UsrDat);
/* Start container for this user */
snprintf (RecordSectionId,sizeof (RecordSectionId),
"record_%u",
NumUsr);
HTM_SECTION_Begin (RecordSectionId);
if (Gbl.Action.Act == ActPrnRecSevTch &&
NumUsr != 0 &&
(NumUsr % Gbl.Usrs.Listing.RecsPerPag) == 0)
HTM_DIV_Begin ("class=\"REC_USR\" style=\"page-break-before:always;\"");
else
HTM_DIV_Begin ("class=\"REC_USR\"");
/* Show optional alert */
if (UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod) // Selected user
Ale_ShowAlerts (NULL);
/* Shared record */
HTM_DIV_Begin ("class=\"REC_LEFT\"");
Rec_ShowSharedUsrRecord (TypeOfView,&UsrDat,RecordSectionId);
HTM_DIV_End ();
/* Office hours */
if (ShowOfficeHours)
{
HTM_DIV_Begin ("class=\"REC_RIGHT\"");
Gbl.TimeTable.Type = TT_TUTORING_TIMETABLE;
Box_BoxBegin (Width,Txt_TIMETABLE_TYPES[Gbl.TimeTable.Type],NULL,
Hlp_USERS_Teachers_timetable,Box_NOT_CLOSABLE);
TT_ShowTimeTable (UsrDat.UsrCod);
Box_BoxEnd ();
HTM_DIV_End ();
}
/* End container for this user */
HTM_DIV_End ();
HTM_SECTION_End ();
NumUsr++;
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
/***** Free memory used by list of selected users' codes *****/
Usr_FreeListsSelectedUsrsCods ();
}
/*****************************************************************************/
/*************** Show a link to print preview of users' records **************/
/*****************************************************************************/
static void Rec_ShowLinkToPrintPreviewOfRecords (void)
{
extern const char *The_ClassFormOutBoxBold[The_NUM_THEMES];
extern const char *The_ClassFormInBox[The_NUM_THEMES];
extern const char *Txt_Print;
extern const char *Txt_record_cards_per_page;
unsigned i;
Frm_LinkFormSubmit (Txt_Print,The_ClassFormOutBoxBold[Gbl.Prefs.Theme],NULL);
Ico_PutIconTextLink ("print.svg",
Txt_Print);
Frm_LinkFormEnd ();
fprintf (Gbl.F.Out,"