// 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; char StrNumLines[10 + 1]; /***** 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 (NULL,"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 (NULL,"FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod); HTM_INPUT_TEXT ("FieldName",Rec_MAX_CHARS_NAME_FIELD, Gbl.Crs.Records.LstFields.Lst[NumField].Name,true, "class=\"REC_FIELDNAME\""); Frm_EndForm (); HTM_TD_End (); /* Number of lines in the form */ HTM_TD_Begin ("class=\"CM\""); Frm_StartForm (ActChgRowFie); Par_PutHiddenParamLong (NULL,"FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod); snprintf (StrNumLines,sizeof (StrNumLines), "%u", Gbl.Crs.Records.LstFields.Lst[NumField].NumLines); HTM_INPUT_TEXT ("NumLines",2,StrNumLines,true, "size=\"2\""); Frm_EndForm (); HTM_TD_End (); /* Visibility of a field */ HTM_TD_Begin ("class=\"CM\""); Frm_StartForm (ActChgVisFie); Par_PutHiddenParamLong (NULL,"FieldCod",Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod); fprintf (Gbl.F.Out,""); for (Vis = (Rec_VisibilityRecordFields_t) 0; Vis < (Rec_VisibilityRecordFields_t) Rec_NUM_TYPES_VISIBILITY; Vis++) { fprintf (Gbl.F.Out,"", Txt_RECORD_FIELD_VISIBILITY_MENU[Vis]); } HTM_SELECT_End (); 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 (NULL,"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 (); HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"("); for (Role = Rol_STD; Role <= Rol_TCH; Role++) { fprintf (Gbl.F.Out,"", Txt_ROLES_SINGUL_Abc[Role][UsrDat->Sex]); } HTM_SELECT_End (); break; case Rec_SHA_OTHER_EXISTING_USR_FORM: // The other user already exists in the platform if (Gbl.Hierarchy.Level == Hie_CRS) // Course selected { /***** Set default role *****/ switch (UsrDat->Roles.InCurrentCrs.Role) { case Rol_STD: // Student in current course case Rol_NET: // Non-editing teacher in current course case Rol_TCH: // Teacher in current course DefaultRoleInForm = UsrDat->Roles.InCurrentCrs.Role; break; default: // User does not belong to current course /* If there is a request of this user, default role is the requested role */ DefaultRoleInForm = Rol_GetRequestedRole (UsrDat->UsrCod); switch (DefaultRoleInForm) { case Rol_STD: // Role requested: student case Rol_NET: // Role requested: non-editing teacher case Rol_TCH: // Role requested: teacher break; default: // No role requested switch (Gbl.Action.Act) { case ActReqMdfStd: DefaultRoleInForm = Rol_STD; break; case ActReqMdfNET: DefaultRoleInForm = Rol_NET; break; case ActReqMdfTch: DefaultRoleInForm = Rol_TCH; break; default: if ((UsrDat->Roles.InCrss & (1 << Rol_TCH))) // Teacher in other courses DefaultRoleInForm = Rol_TCH; else if ((UsrDat->Roles.InCrss & (1 << Rol_NET))) // Non-editing teacher in other courses DefaultRoleInForm = Rol_NET; else DefaultRoleInForm = Rol_STD; break; } break; } break; } /***** Selector of role *****/ fprintf (Gbl.F.Out,"" "", (unsigned) DefaultRoleInForm, Txt_ROLES_SINGUL_Abc[DefaultRoleInForm][UsrDat->Sex]); HTM_SELECT_End (); } break; case Rec_SHA_OTHER_NEW_USR_FORM: // The user does not exist in platform if (Gbl.Hierarchy.Level == Hie_CRS) // Course selected switch (Gbl.Usrs.Me.Role.Logged) { case Rol_TCH: case Rol_DEG_ADM: case Rol_CTR_ADM: case Rol_INS_ADM: case Rol_SYS_ADM: /***** Set default role *****/ switch (Gbl.Action.Act) { case ActReqMdfStd: DefaultRoleInForm = Rol_STD; break; case ActReqMdfNET: DefaultRoleInForm = Rol_NET; break; case ActReqMdfTch: DefaultRoleInForm = Rol_TCH; break; default: DefaultRoleInForm = Rol_STD; break; } /***** Selector of role *****/ fprintf (Gbl.F.Out,"" "", (unsigned) Rol_GST,Txt_ROLES_SINGUL_Abc[Rol_GST][Usr_SEX_UNKNOWN]); HTM_SELECT_End (); break; default: // The rest of users can not register other users break; } break; default: break; } HTM_TD_End (); } else if (SexForm) { /***** Form to select a sex *****/ HTM_TD_Begin ("class=\"REC_C1_BOT RM %s\"",ClassForm); fprintf (Gbl.F.Out,"%s*:",Txt_Sex); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT LM\""); for (Sex = Usr_SEX_FEMALE; Sex <= Usr_SEX_MALE; Sex++) { HTM_LABEL_Begin ("class=\"REC_DAT_BOLD\""); HTM_INPUT_RADIO ("Sex",false, "value=\"%u\"%s required=\"required\"", (unsigned) Sex, Sex == Gbl.Usrs.Me.UsrDat.Sex ? " checked=\"checked\"" : ""); fprintf (Gbl.F.Out,"%s %s",Usr_StringsSexIcons[Sex],Txt_SEX_SINGULAR_Abc[Sex]); HTM_LABEL_End (); } HTM_TD_End (); } else // RoleForm == false, SexForm == false { /***** No form, only text *****/ HTM_TD_Begin ("class=\"REC_C1_BOT RM %s\"",ClassForm); fprintf (Gbl.F.Out,"%s:",Txt_Role); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT REC_DAT_BOLD LM\""); fprintf (Gbl.F.Out,"%s", Txt_ROLES_SINGUL_Abc[UsrDat->Roles.InCurrentCrs.Role][UsrDat->Sex]); HTM_TD_End (); } HTM_TR_End (); } /*****************************************************************************/ /*************************** Show user's surname 1 ***************************/ /*****************************************************************************/ static void Rec_ShowSurname1 (struct UsrData *UsrDat, Rec_SharedRecordViewType_t TypeOfView, bool ICanEdit, const char *ClassForm) { extern const char *Txt_Surname_1; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"Surname1\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s",Txt_Surname_1); if (TypeOfView == Rec_SHA_MY_RECORD_FORM) fprintf (Gbl.F.Out,"*"); fprintf (Gbl.F.Out,":"); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT REC_DAT_BOLD LM\""); if (ICanEdit) HTM_INPUT_TEXT ("Surname1",Usr_MAX_CHARS_FIRSTNAME_OR_SURNAME,UsrDat->Surname1,false, "class=\"REC_C2_BOT_INPUT\"%s", TypeOfView == Rec_SHA_MY_RECORD_FORM ? " required=\"required\"" : ""); else if (UsrDat->Surname1[0]) fprintf (Gbl.F.Out,"%s",UsrDat->Surname1); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*************************** Show user's surname 2 ***************************/ /*****************************************************************************/ static void Rec_ShowSurname2 (struct UsrData *UsrDat, bool ICanEdit, const char *ClassForm) { extern const char *Txt_Surname_2; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"Surname2\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s:",Txt_Surname_2); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT REC_DAT_BOLD LM\""); if (ICanEdit) HTM_INPUT_TEXT ("Surname2",Usr_MAX_CHARS_FIRSTNAME_OR_SURNAME, UsrDat->Surname2,false, "class=\"REC_C2_BOT_INPUT\""); else if (UsrDat->Surname2[0]) fprintf (Gbl.F.Out,"%s",UsrDat->Surname2); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /************************** Show user's first name ***************************/ /*****************************************************************************/ static void Rec_ShowFirstName (struct UsrData *UsrDat, Rec_SharedRecordViewType_t TypeOfView, bool ICanEdit, const char *ClassForm) { extern const char *Txt_First_name; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"FirstName\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s",Txt_First_name); if (TypeOfView == Rec_SHA_MY_RECORD_FORM) fprintf (Gbl.F.Out,"*"); fprintf (Gbl.F.Out,":"); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("colspan=\"2\" class=\"REC_C2_BOT REC_DAT_BOLD LM\""); if (ICanEdit) HTM_INPUT_TEXT ("FirstName",Usr_MAX_CHARS_FIRSTNAME_OR_SURNAME, UsrDat->FirstName,false, "class=\"REC_C2_BOT_INPUT\"%s", TypeOfView == Rec_SHA_MY_RECORD_FORM ? " required=\"required\"" : ""); else if (UsrDat->FirstName[0]) fprintf (Gbl.F.Out,"%s",UsrDat->FirstName); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /**************************** Show user's country ****************************/ /*****************************************************************************/ static void Rec_ShowCountry (struct UsrData *UsrDat, Rec_SharedRecordViewType_t TypeOfView, const char *ClassForm) { extern const char *Txt_Country; extern const char *Txt_Another_country; unsigned NumCty; /***** If list of countries is empty, try to get it *****/ if (!Gbl.Hierarchy.Sys.Ctys.Num) { Gbl.Hierarchy.Sys.Ctys.SelectedOrder = Cty_ORDER_BY_COUNTRY; Cty_GetListCountries (Cty_GET_BASIC_DATA); } HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"OthCtyCod\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s",Txt_Country); if (TypeOfView == Rec_SHA_MY_RECORD_FORM) fprintf (Gbl.F.Out,"*"); fprintf (Gbl.F.Out,":"); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("colspan=\"2\" class=\"REC_C2_BOT LM\""); /***** Selector of country *****/ fprintf (Gbl.F.Out,"" ""); for (NumCty = 0; NumCty < Gbl.Hierarchy.Sys.Ctys.Num; NumCty++) { fprintf (Gbl.F.Out,"", Gbl.Hierarchy.Sys.Ctys.Lst[NumCty].Name[Gbl.Prefs.Language]); } HTM_SELECT_End (); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Institution *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"OthInsCod\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s*:",Txt_Institution); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT LM\""); /* Get list of institutions in this country */ Ins_FreeListInstitutions (); if (Gbl.Usrs.Me.UsrDat.InsCtyCod > 0) Ins_GetListInstitutions (Gbl.Usrs.Me.UsrDat.InsCtyCod,Ins_GET_BASIC_DATA); /* Begin form to select institution */ Frm_StartFormAnchor (ActChgMyIns,Rec_MY_INS_CTR_DPT_ID); fprintf (Gbl.F.Out,"" "" "", Txt_Another_centre); for (NumCtr = 0; NumCtr < Gbl.Hierarchy.Ins.Ctrs.Num; NumCtr++) { fprintf (Gbl.F.Out,"", Gbl.Hierarchy.Ins.Ctrs.Lst[NumCtr].FullName); } HTM_SELECT_End (); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Department *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"%s\" class=\"%s\"",Dpt_PARAM_DPT_COD_NAME,ClassForm); fprintf (Gbl.F.Out,"%s*:",Txt_Department); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT LM\""); Frm_StartFormAnchor (ActChgMyDpt,Rec_MY_INS_CTR_DPT_ID); Dpt_WriteSelectorDepartment (Gbl.Usrs.Me.UsrDat.InsCod, // Departments in my institution Gbl.Usrs.Me.UsrDat.Tch.DptCod, // Selected department "REC_C2_BOT_INPUT", // Selector class -1L, // First option "", // Text when no department selected true); // Submit on change Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Office *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"Office\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s:",Txt_Office); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT LM\""); Frm_StartFormAnchor (ActChgMyOff,Rec_MY_INS_CTR_DPT_ID); HTM_INPUT_TEXT ("Office",Usr_MAX_CHARS_ADDRESS,Gbl.Usrs.Me.UsrDat.Tch.Office,true, "class=\"REC_C2_BOT_INPUT\""); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Phone *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"REC_C1_BOT RM\""); HTM_LABEL_Begin ("for=\"OfficePhone\" class=\"%s\"",ClassForm); fprintf (Gbl.F.Out,"%s:",Txt_Phone); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"REC_C2_BOT LM\""); Frm_StartFormAnchor (ActChgMyOffPho,Rec_MY_INS_CTR_DPT_ID); HTM_INPUT_TEL ("OfficePhone",Gbl.Usrs.Me.UsrDat.Tch.OfficePhone,true, " class=\"REC_C2_BOT_INPUT\""); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); } /***** End table and box *****/ Box_EndBoxTable (); /***** End section *****/ HTM_SECTION_End (); } /*****************************************************************************/ /******** Receive form data to change the country of my institution **********/ /*****************************************************************************/ void Rec_ChgCountryOfMyInstitution (void) { unsigned NumInss; /***** Get country code of my institution *****/ Gbl.Usrs.Me.UsrDat.InsCtyCod = Cty_GetAndCheckParamOtherCtyCod (0); /***** When country changes, the institution, centre and department must be reset *****/ NumInss = Ins_GetNumInssInCty (Gbl.Usrs.Me.UsrDat.InsCtyCod); if (NumInss) { Gbl.Usrs.Me.UsrDat.InsCod = -1L; Gbl.Usrs.Me.UsrDat.Tch.CtrCod = -1L; Gbl.Usrs.Me.UsrDat.Tch.DptCod = -1L; } else // Country has no institutions { Gbl.Usrs.Me.UsrDat.InsCod = 0; // Another institution Gbl.Usrs.Me.UsrDat.Tch.CtrCod = 0; // Another centre Gbl.Usrs.Me.UsrDat.Tch.DptCod = 0; // Another department } /***** Update institution, centre and department *****/ Enr_UpdateInstitutionCentreDepartment (); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); } /*****************************************************************************/ /**************** Receive form data to change my institution *****************/ /*****************************************************************************/ void Rec_UpdateMyInstitution (void) { struct Instit Ins; unsigned NumCtrs; unsigned NumDpts; /***** Get my institution *****/ /* Get institution code */ Ins.InsCod = Ins_GetAndCheckParamOtherInsCod (0); // 0 (another institution) is allowed here /* Get country of institution */ if (Ins.InsCod > 0) { Ins_GetDataOfInstitutionByCod (&Ins,Ins_GET_BASIC_DATA); if (Gbl.Usrs.Me.UsrDat.InsCtyCod != Ins.CtyCod) Gbl.Usrs.Me.UsrDat.InsCtyCod = Ins.CtyCod; } /* Set institution code */ Gbl.Usrs.Me.UsrDat.InsCod = Ins.InsCod; /***** When institution changes, the centre and department must be reset *****/ NumCtrs = Ctr_GetNumCtrsInIns (Gbl.Usrs.Me.UsrDat.InsCod); NumDpts = Dpt_GetNumDptsInIns (Gbl.Usrs.Me.UsrDat.InsCod); Gbl.Usrs.Me.UsrDat.Tch.CtrCod = (NumCtrs ? -1L : 0); Gbl.Usrs.Me.UsrDat.Tch.DptCod = (NumDpts ? -1L : 0); /***** Update institution, centre and department *****/ Enr_UpdateInstitutionCentreDepartment (); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); } /*****************************************************************************/ /******************* Receive form data to change my centre *******************/ /*****************************************************************************/ void Rec_UpdateMyCentre (void) { struct Centre Ctr; /***** Get my centre *****/ /* Get centre code */ Ctr.CtrCod = Ctr_GetAndCheckParamOtherCtrCod (0); // 0 (another centre) is allowed here /* Get institution of centre */ if (Ctr.CtrCod > 0) { Ctr_GetDataOfCentreByCod (&Ctr); if (Gbl.Usrs.Me.UsrDat.InsCod != Ctr.InsCod) { Gbl.Usrs.Me.UsrDat.InsCod = Ctr.InsCod; Gbl.Usrs.Me.UsrDat.Tch.DptCod = -1L; } } /* Set centre code */ Gbl.Usrs.Me.UsrDat.Tch.CtrCod = Ctr.CtrCod; /***** Update institution, centre and department *****/ Enr_UpdateInstitutionCentreDepartment (); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); } /*****************************************************************************/ /***************** Receive form data to change my department *****************/ /*****************************************************************************/ void Rec_UpdateMyDepartment (void) { struct Department Dpt; /***** Get my department *****/ /* Get department code */ Dpt.DptCod = Dpt_GetAndCheckParamDptCod (0); // 0 (another department) is allowed here /* Get institution of department */ if (Dpt.DptCod > 0) { Dpt_GetDataOfDepartmentByCod (&Dpt); if (Gbl.Usrs.Me.UsrDat.InsCod != Dpt.InsCod) { Gbl.Usrs.Me.UsrDat.InsCod = Dpt.InsCod; Gbl.Usrs.Me.UsrDat.Tch.CtrCod = -1L; } } /***** Update institution, centre and department *****/ Gbl.Usrs.Me.UsrDat.Tch.DptCod = Dpt.DptCod; Enr_UpdateInstitutionCentreDepartment (); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); } /*****************************************************************************/ /******************* Receive form data to change my office *******************/ /*****************************************************************************/ void Rec_UpdateMyOffice (void) { /***** Get my office *****/ Par_GetParToText ("Office",Gbl.Usrs.Me.UsrDat.Tch.Office,Usr_MAX_BYTES_ADDRESS); /***** Update office *****/ DB_QueryUPDATE ("can not update office", "UPDATE usr_data SET Office='%s' WHERE UsrCod=%ld", Gbl.Usrs.Me.UsrDat.Tch.Office, Gbl.Usrs.Me.UsrDat.UsrCod); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); } /*****************************************************************************/ /**************** Receive form data to change my office phone ****************/ /*****************************************************************************/ void Rec_UpdateMyOfficePhone (void) { /***** Get my office *****/ Par_GetParToText ("OfficePhone",Gbl.Usrs.Me.UsrDat.Tch.OfficePhone,Usr_MAX_BYTES_PHONE); /***** Update office phone *****/ DB_QueryUPDATE ("can not update office phone", "UPDATE usr_data SET OfficePhone='%s' WHERE UsrCod=%ld", Gbl.Usrs.Me.UsrDat.Tch.OfficePhone, Gbl.Usrs.Me.UsrDat.UsrCod); /***** Show form again *****/ Rec_ShowMySharedRecordAndMore (); }