// swad_centre.c: centres /* 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 ***********************************/ /*****************************************************************************/ #define _GNU_SOURCE // For asprintf #include // For NULL #include // For boolean type #include // For asprintf #include // For calloc #include // For string functions #include // For the macro WEXITSTATUS #include // For unlink #include "swad_box.h" #include "swad_centre.h" #include "swad_constant.h" #include "swad_database.h" #include "swad_form.h" #include "swad_global.h" #include "swad_help.h" #include "swad_hierarchy.h" #include "swad_HTML.h" #include "swad_institution.h" #include "swad_language.h" #include "swad_logo.h" #include "swad_parameter.h" #include "swad_QR.h" #include "swad_string.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private constants *****************************/ /*****************************************************************************/ // Centre photo will be saved with: // - maximum width of Ctr_PHOTO_SAVED_MAX_HEIGHT // - maximum height of Ctr_PHOTO_SAVED_MAX_HEIGHT // - maintaining the original aspect ratio (aspect ratio recommended: 3:2) #define Ctr_RECOMMENDED_ASPECT_RATIO "3:2" #define Ctr_PHOTO_SAVED_MAX_WIDTH 768 #define Ctr_PHOTO_SAVED_MAX_HEIGHT 512 #define Ctr_PHOTO_SAVED_QUALITY 75 // 1 to 100 /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ /*****************************************************************************/ /***************************** Private variables *****************************/ /*****************************************************************************/ static struct Centre *Ctr_EditingCtr = NULL; // Static variable to keep the centre being edited /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Ctr_Configuration (bool PrintView); static void Ctr_PutIconsCtrConfig (void); static void Ctr_PutIconToChangePhoto (void); static void Ctr_ShowNumUsrsInCrssOfCtr (Rol_Role_t Role); static void Ctr_ListCentres (void); static bool Ctr_CheckIfICanCreateCentres (void); static void Ctr_PutIconsListingCentres (void); static void Ctr_PutIconToEditCentres (void); static void Ctr_ListOneCentreForSeeing (struct Centre *Ctr,unsigned NumCtr); static void Ctr_GetParamCtrOrder (void); static void Ctr_EditCentresInternal (void); static void Ctr_PutIconsEditingCentres (void); static void Ctr_GetPhotoAttribution (long CtrCod,char **PhotoAttribution); static void Ctr_FreePhotoAttribution (char **PhotoAttribution); static void Ctr_ListCentresForEdition (void); static bool Ctr_CheckIfICanEditACentre (struct Centre *Ctr); static Ctr_StatusTxt_t Ctr_GetStatusTxtFromStatusBits (Ctr_Status_t Status); static Ctr_Status_t Ctr_GetStatusBitsFromStatusTxt (Ctr_StatusTxt_t StatusTxt); static void Ctr_PutParamOtherCtrCod (long CtrCod); static void Ctr_UpdateCtrInsDB (long CtrCod,long InsCod); static void Ctr_UpdateCtrPlcDB (long CtrCod,long NewPlcCod); static void Ctr_RenameCentre (struct Centre *Ctr,Cns_ShrtOrFullName_t ShrtOrFullName); static bool Ctr_CheckIfCtrNameExistsInIns (const char *FieldName,const char *Name,long CtrCod,long InsCod); static void Ctr_UpdateInsNameDB (long CtrCod,const char *FieldName,const char *NewCtrName); static void Ctr_UpdateCtrWWWDB (long CtrCod, const char NewWWW[Cns_MAX_BYTES_WWW + 1]); static void Ctr_ShowAlertAndButtonToGoToCtr (void); static void Ctr_PutParamGoToCtr (void); static void Ctr_PutFormToCreateCentre (void); static void Ctr_PutHeadCentresForSeeing (bool OrderSelectable); static void Ctr_PutHeadCentresForEdition (void); static void Ctr_RecFormRequestOrCreateCtr (unsigned Status); static void Ctr_CreateCentre (unsigned Status); static void Ctr_EditingCentreConstructor (void); static void Ctr_EditingCentreDestructor (void); /*****************************************************************************/ /******************* List centres with pending degrees ***********************/ /*****************************************************************************/ void Ctr_SeeCtrWithPendingDegs (void) { extern const char *Hlp_SYSTEM_Hierarchy_pending; extern const char *Txt_Centres_with_pending_degrees; extern const char *Txt_Centre; extern const char *Txt_Degrees_ABBREVIATION; extern const char *Txt_There_are_no_centres_with_requests_for_degrees_to_be_confirmed; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCtrs; unsigned NumCtr; struct Centre Ctr; const char *BgColor; /***** Get centres with pending degrees *****/ switch (Gbl.Usrs.Me.Role.Logged) { case Rol_CTR_ADM: NumCtrs = (unsigned) DB_QuerySELECT (&mysql_res,"can not get centres" " with pending degrees", "SELECT degrees.CtrCod,COUNT(*)" " FROM degrees,ctr_admin,centres" " WHERE (degrees.Status & %u)<>0" " AND degrees.CtrCod=ctr_admin.CtrCod" " AND ctr_admin.UsrCod=%ld" " AND degrees.CtrCod=centres.CtrCod" " GROUP BY degrees.CtrCod ORDER BY centres.ShortName", (unsigned) Deg_STATUS_BIT_PENDING, Gbl.Usrs.Me.UsrDat.UsrCod); break; case Rol_SYS_ADM: NumCtrs = (unsigned) DB_QuerySELECT (&mysql_res,"can not get centres" " with pending degrees", "SELECT degrees.CtrCod,COUNT(*)" " FROM degrees,centres" " WHERE (degrees.Status & %u)<>0" " AND degrees.CtrCod=centres.CtrCod" " GROUP BY degrees.CtrCod ORDER BY centres.ShortName", (unsigned) Deg_STATUS_BIT_PENDING); break; default: // Forbidden for other users return; } if (NumCtrs) { /***** Begin box and table *****/ Box_StartBoxTable (NULL,Txt_Centres_with_pending_degrees,NULL, Hlp_SYSTEM_Hierarchy_pending,Box_NOT_CLOSABLE,2); /***** Wrtie heading *****/ HTM_TR_Begin (NULL); HTM_TH (1,1,"LM",Txt_Centre); HTM_TH (1,1,"RM",Txt_Degrees_ABBREVIATION); HTM_TR_End (); /***** List the centres *****/ for (NumCtr = 0; NumCtr < NumCtrs; NumCtr++) { /* Get next centre */ row = mysql_fetch_row (mysql_res); /* Get centre code (row[0]) */ Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[0]); BgColor = (Ctr.CtrCod == Gbl.Hierarchy.Ctr.CtrCod) ? "LIGHT_BLUE" : Gbl.ColorRows[Gbl.RowEvenOdd]; /* Get data of centre */ Ctr_GetDataOfCentreByCod (&Ctr); /* Centre logo and full name */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"LM %s\"",BgColor); Ctr_DrawCentreLogoAndNameWithLink (&Ctr,ActSeeDeg, "DAT_NOBR","CM"); HTM_TD_End (); /* Number of pending degrees (row[1]) */ HTM_TD_Begin ("class=\"DAT RM %s\"",BgColor); fprintf (Gbl.F.Out,"%s",row[1]); HTM_TD_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; HTM_TR_End (); } /***** End table and box *****/ Box_EndBoxTable (); } else Ale_ShowAlert (Ale_INFO,Txt_There_are_no_centres_with_requests_for_degrees_to_be_confirmed); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /******************** Draw centre logo and name with link ********************/ /*****************************************************************************/ void Ctr_DrawCentreLogoAndNameWithLink (struct Centre *Ctr,Act_Action_t Action, const char *ClassLink,const char *ClassLogo) { extern const char *Txt_Go_to_X; /***** Begin form *****/ Frm_StartFormGoTo (Action); Ctr_PutParamCtrCod (Ctr->CtrCod); /***** Link to action *****/ snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Go_to_X, Ctr->FullName); Frm_LinkFormSubmit (Gbl.Title,ClassLink,NULL); /***** Centre logo and name *****/ Log_DrawLogo (Hie_CTR,Ctr->CtrCod,Ctr->ShrtName,16,ClassLogo,true); fprintf (Gbl.F.Out," %s",Ctr->FullName); /***** End link *****/ Frm_LinkFormEnd (); /***** End form *****/ Frm_EndForm (); } /*****************************************************************************/ /****************** Show information of the current centre *******************/ /*****************************************************************************/ void Ctr_ShowConfiguration (void) { Ctr_Configuration (false); /***** Show help to enrol me *****/ Hlp_ShowHelpWhatWouldYouLikeToDo (); } /*****************************************************************************/ /****************** Print information of the current centre ******************/ /*****************************************************************************/ void Ctr_PrintConfiguration (void) { Ctr_Configuration (true); } /*****************************************************************************/ /******************* Information of the current centre ***********************/ /*****************************************************************************/ static void Ctr_Configuration (bool PrintView) { extern const char *Hlp_CENTRE_Information; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Institution; extern const char *Txt_Centre; extern const char *Txt_Short_name; extern const char *Txt_Another_place; extern const char *Txt_Web; extern const char *Txt_Shortcut; extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; extern const char *Txt_QR_code; extern const char *Txt_Users_of_the_centre; extern const char *Txt_Place; extern const char *Txt_Degrees; extern const char *Txt_Degrees_of_CENTRE_X; extern const char *Txt_Courses; unsigned NumIns; unsigned NumPlc; struct Place Plc; char PathPhoto[PATH_MAX + 1]; bool PhotoExists; char *PhotoAttribution = NULL; bool PutLink; char *URL; char *Icon; /***** Trivial check *****/ if (Gbl.Hierarchy.Ctr.CtrCod <= 0) // No centre selected return; /***** Path to photo *****/ snprintf (PathPhoto,sizeof (PathPhoto), "%s/%02u/%u/%u.jpg", Cfg_PATH_CTR_PUBLIC, (unsigned) (Gbl.Hierarchy.Ctr.CtrCod % 100), (unsigned) Gbl.Hierarchy.Ctr.CtrCod, (unsigned) Gbl.Hierarchy.Ctr.CtrCod); PhotoExists = Fil_CheckIfPathExists (PathPhoto); /***** Begin box *****/ if (PrintView) Box_BoxBegin (NULL,NULL,NULL, NULL,Box_NOT_CLOSABLE); else Box_BoxBegin (NULL,NULL,Ctr_PutIconsCtrConfig, Hlp_CENTRE_Information,Box_NOT_CLOSABLE); /***** Title *****/ PutLink = !PrintView && Gbl.Hierarchy.Ctr.WWW[0]; HTM_DIV_Begin ("class=\"FRAME_TITLE FRAME_TITLE_BIG\""); if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\"" " class=\"FRAME_TITLE_BIG\" title=\"%s\"", Gbl.Hierarchy.Ctr.WWW, Gbl.Hierarchy.Ctr.FullName); Log_DrawLogo (Hie_CTR,Gbl.Hierarchy.Ctr.CtrCod, Gbl.Hierarchy.Ctr.ShrtName,64,NULL,true); fprintf (Gbl.F.Out,"
%s",Gbl.Hierarchy.Ctr.FullName); if (PutLink) HTM_A_End (); HTM_DIV_End (); /***** Centre photo *****/ if (PhotoExists) { /* Get photo attribution */ Ctr_GetPhotoAttribution (Gbl.Hierarchy.Ctr.CtrCod,&PhotoAttribution); /* Photo image */ HTM_DIV_Begin ("class=\"DAT_SMALL CM\""); if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"DAT_N\"", Gbl.Hierarchy.Ctr.WWW); if (asprintf (&URL,"%s/%02u/%u", Cfg_URL_CTR_PUBLIC, (unsigned) (Gbl.Hierarchy.Ctr.CtrCod % 100), (unsigned) Gbl.Hierarchy.Ctr.CtrCod) < 0) Lay_NotEnoughMemoryExit (); if (asprintf (&Icon,"%u.jpg", (unsigned) Gbl.Hierarchy.Ctr.CtrCod) < 0) Lay_NotEnoughMemoryExit (); HTM_IMG (URL,Icon,Gbl.Hierarchy.Ctr.FullName, "class=\"%s\"",PrintView ? "CENTRE_PHOTO_PRINT" : "CENTRE_PHOTO_SHOW"); free ((void *) Icon); free ((void *) URL); if (PutLink) HTM_A_End (); HTM_DIV_End (); /* Photo attribution */ if (!PrintView && Gbl.Usrs.Me.Role.Logged >= Rol_CTR_ADM) // Only centre admins, institution admins and centre admins // have permission to edit photo attribution { HTM_DIV_Begin ("class=\"CM\""); Frm_StartForm (ActChgCtrPhoAtt); HTM_TEXTAREA_Begin ("id=\"AttributionArea\" name=\"Attribution\" rows=\"2\"" " onchange=\"document.getElementById('%s').submit();return false;\"", Gbl.Form.Id); if (PhotoAttribution) fprintf (Gbl.F.Out,"%s",PhotoAttribution); HTM_TEXTAREA_End (); Frm_EndForm (); HTM_DIV_End (); } else if (PhotoAttribution) { HTM_DIV_Begin ("class=\"ATTRIBUTION\""); fprintf (Gbl.F.Out,"%s",PhotoAttribution); HTM_DIV_End (); } /* Free memory used for photo attribution */ Ctr_FreePhotoAttribution (&PhotoAttribution); } /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); /***** Institution *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"OthInsCod\" class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Institution); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT_N LM\""); if (!PrintView && Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM) // Only system admins can move a centre to another institution { /* Get list of institutions of the current country */ Ins_GetListInstitutions (Gbl.Hierarchy.Cty.CtyCod,Ins_GET_BASIC_DATA); /* Put form to select institution */ Frm_StartForm (ActChgCtrInsCfg); fprintf (Gbl.F.Out,"", Gbl.Form.Id); fprintf (Gbl.F.Out,"",Txt_Another_place); for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) fprintf (Gbl.F.Out,"", Gbl.Plcs.Lst[NumPlc].PlcCod, (Gbl.Plcs.Lst[NumPlc].PlcCod == Gbl.Hierarchy.Ctr.PlcCod) ? " selected=\"selected\"" : "", Gbl.Plcs.Lst[NumPlc].ShrtName); HTM_SELECT_End (); Frm_EndForm (); /* Free list of places */ Plc_FreeListPlaces (); } else // I can not change centre place fprintf (Gbl.F.Out,"%s",Plc.FullName); HTM_TD_End (); HTM_TR_End (); /***** Centre WWW *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"WWW\" class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Web); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); if (!PrintView && Gbl.Usrs.Me.Role.Logged >= Rol_CTR_ADM) // Only centre admins, institution admins and system admins // can change centre WWW { /* Form to change centre WWW */ Frm_StartForm (ActChgCtrWWWCfg); HTM_INPUT_URL ("WWW",Gbl.Hierarchy.Ctr.WWW,true, "class=\"INPUT_WWW\""); Frm_EndForm (); } else // I can not change centre WWW { HTM_DIV_Begin ("class=\"EXTERNAL_WWW_LONG\""); HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"DAT\"", Gbl.Hierarchy.Ctr.WWW); fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Ctr.WWW); HTM_A_End (); HTM_DIV_End (); } HTM_TD_End (); HTM_TR_End (); /***** Shortcut to the centre *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Shortcut); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); HTM_A_Begin ("href=\"%s/%s?ctr=%ld\" class=\"DAT\" target=\"_blank\"", Cfg_URL_SWAD_CGI, Lan_STR_LANG_ID[Gbl.Prefs.Language], Gbl.Hierarchy.Ctr.CtrCod); fprintf (Gbl.F.Out,"%s/%s?ctr=%ld", Cfg_URL_SWAD_CGI, Lan_STR_LANG_ID[Gbl.Prefs.Language], Gbl.Hierarchy.Ctr.CtrCod); HTM_A_End (); HTM_TD_End (); HTM_TR_End (); if (PrintView) { /***** QR code with link to the centre *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_QR_code); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); QR_LinkTo (250,"ctr",Gbl.Hierarchy.Ctr.CtrCod); HTM_TD_End (); HTM_TR_End (); } else { /***** Number of users who claim to belong to this centre *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Users_of_the_centre); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Usr_GetNumUsrsWhoClaimToBelongToCtr (Gbl.Hierarchy.Ctr.CtrCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of degrees *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Degrees); HTM_TD_End (); /* Form to go to see degrees of this centre */ HTM_TD_Begin ("class=\"LM\""); Frm_StartFormGoTo (ActSeeDeg); Ctr_PutParamCtrCod (Gbl.Hierarchy.Ctr.CtrCod); snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Degrees_of_CENTRE_X, Gbl.Hierarchy.Ctr.ShrtName); Frm_LinkFormSubmit (Gbl.Title,"DAT",NULL); fprintf (Gbl.F.Out,"%u",Deg_GetNumDegsInCtr (Gbl.Hierarchy.Ctr.CtrCod)); Frm_LinkFormEnd (); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); /***** Number of courses *****/ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:",Txt_Courses); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Crs_GetNumCrssInCtr (Gbl.Hierarchy.Ctr.CtrCod)); HTM_TD_End (); HTM_TR_End (); /***** Number of users in courses of this centre *****/ Ctr_ShowNumUsrsInCrssOfCtr (Rol_TCH); Ctr_ShowNumUsrsInCrssOfCtr (Rol_NET); Ctr_ShowNumUsrsInCrssOfCtr (Rol_STD); Ctr_ShowNumUsrsInCrssOfCtr (Rol_UNK); } /***** End table *****/ HTM_TABLE_End (); /***** End box *****/ Box_BoxEnd (); } /*****************************************************************************/ /************ Put contextual icons in configuration of a centre **************/ /*****************************************************************************/ static void Ctr_PutIconsCtrConfig (void) { /***** Put icon to print info about centre *****/ Ico_PutContextualIconToPrint (ActPrnCtrInf,NULL); /***** Put icon to view places *****/ Plc_PutIconToViewPlaces (); if (Gbl.Usrs.Me.Role.Logged >= Rol_CTR_ADM) // Only centre admins, institution admins and system admins // have permission to upload logo and photo of the centre { /***** Put icon to upload logo of centre *****/ Log_PutIconToChangeLogo (Hie_CTR); /***** Put icon to upload photo of centre *****/ Ctr_PutIconToChangePhoto (); } } /*****************************************************************************/ /************* Put contextual icons to upload photo of centre ****************/ /*****************************************************************************/ static void Ctr_PutIconToChangePhoto (void) { extern const char *Txt_Change_photo; extern const char *Txt_Upload_photo; char PathPhoto[PATH_MAX + 1]; bool PhotoExists; /***** Link to upload photo of centre *****/ snprintf (PathPhoto,sizeof (PathPhoto), "%s/%02u/%u/%u.jpg", Cfg_PATH_CTR_PUBLIC, (unsigned) (Gbl.Hierarchy.Ctr.CtrCod % 100), (unsigned) Gbl.Hierarchy.Ctr.CtrCod, (unsigned) Gbl.Hierarchy.Ctr.CtrCod); PhotoExists = Fil_CheckIfPathExists (PathPhoto); Lay_PutContextualLinkOnlyIcon (ActReqCtrPho,NULL,NULL, "camera.svg", PhotoExists ? Txt_Change_photo : Txt_Upload_photo); } /*****************************************************************************/ /**************** Number of users in courses of this centre ******************/ /*****************************************************************************/ static void Ctr_ShowNumUsrsInCrssOfCtr (Rol_Role_t Role) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Users_in_courses; extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); fprintf (Gbl.F.Out,"%s:", (Role == Rol_UNK) ? Txt_Users_in_courses : Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN]); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); fprintf (Gbl.F.Out,"%u",Usr_GetNumUsrsInCrssOfCtr (Role,Gbl.Hierarchy.Ctr.CtrCod)); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*************** Show the centres of the current institution *****************/ /*****************************************************************************/ void Ctr_ShowCtrsOfCurrentIns (void) { /***** Trivial check *****/ if (Gbl.Hierarchy.Ins.InsCod <= 0) // No institution selected return; /***** Get parameter with the type of order in the list of centres *****/ Ctr_GetParamCtrOrder (); /***** Get list of centres *****/ Ctr_GetListCentres (Gbl.Hierarchy.Ins.InsCod); /***** Write menu to select country and institution *****/ Hie_WriteMenuHierarchy (); /***** List centres *****/ Ctr_ListCentres (); /***** Free list of centres *****/ Ctr_FreeListCentres (); } /*****************************************************************************/ /******************** List centres in this institution ***********************/ /*****************************************************************************/ static void Ctr_ListCentres (void) { extern const char *Hlp_INSTITUTION_Centres; extern const char *Txt_Centres_of_INSTITUTION_X; extern const char *Txt_No_centres; extern const char *Txt_Create_another_centre; extern const char *Txt_Create_centre; unsigned NumCtr; /***** Begin box *****/ snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Centres_of_INSTITUTION_X, Gbl.Hierarchy.Ins.FullName); Box_BoxBegin (NULL,Gbl.Title,Ctr_PutIconsListingCentres, Hlp_INSTITUTION_Centres,Box_NOT_CLOSABLE); if (Gbl.Hierarchy.Ins.Ctrs.Num) // There are centres in the current institution { /***** Begin table *****/ HTM_TABLE_BeginWideMarginPadding (2); Ctr_PutHeadCentresForSeeing (true); // Order selectable /***** Write all the centres and their nuber of teachers *****/ for (NumCtr = 0; NumCtr < Gbl.Hierarchy.Ins.Ctrs.Num; NumCtr++) Ctr_ListOneCentreForSeeing (&(Gbl.Hierarchy.Ins.Ctrs.Lst[NumCtr]),NumCtr + 1); /***** End table *****/ HTM_TABLE_End (); } else // No centres created in the current institution Ale_ShowAlert (Ale_INFO,Txt_No_centres); /***** Button to create centre *****/ if (Ctr_CheckIfICanCreateCentres ()) { Frm_StartForm (ActEdiCtr); Btn_PutConfirmButton (Gbl.Hierarchy.Ins.Ctrs.Num ? Txt_Create_another_centre : Txt_Create_centre); Frm_EndForm (); } /***** End box *****/ Box_BoxEnd (); } /*****************************************************************************/ /********************** Check if I can create centres ************************/ /*****************************************************************************/ static bool Ctr_CheckIfICanCreateCentres (void) { return (bool) (Gbl.Usrs.Me.Role.Logged >= Rol_GST); } /*****************************************************************************/ /***************** Put contextual icons in list of centres *******************/ /*****************************************************************************/ static void Ctr_PutIconsListingCentres (void) { /***** Put icon to edit centres *****/ if (Ctr_CheckIfICanCreateCentres ()) Ctr_PutIconToEditCentres (); /***** Put icon to view places *****/ Plc_PutIconToViewPlaces (); /***** Put icon to show a figure *****/ Gbl.Figures.FigureType = Fig_HIERARCHY; Fig_PutIconToShowFigure (); } /*****************************************************************************/ /********************** Put link (form) to edit centres **********************/ /*****************************************************************************/ static void Ctr_PutIconToEditCentres (void) { Ico_PutContextualIconToEdit (ActEdiCtr,NULL); } /*****************************************************************************/ /************************* List one centre for seeing ************************/ /*****************************************************************************/ static void Ctr_ListOneCentreForSeeing (struct Centre *Ctr,unsigned NumCtr) { extern const char *Txt_CENTRE_STATUS[Ctr_NUM_STATUS_TXT]; struct Place Plc; const char *TxtClassNormal; const char *TxtClassStrong; const char *BgColor; Ctr_StatusTxt_t StatusTxt; /***** Get data of place of this centre *****/ Plc.PlcCod = Ctr->PlcCod; Plc_GetDataOfPlaceByCod (&Plc); if (Ctr->Status & Ctr_STATUS_BIT_PENDING) { TxtClassNormal = "DAT_LIGHT"; TxtClassStrong = "DAT_LIGHT"; } else { TxtClassNormal = "DAT"; TxtClassStrong = "DAT_N"; } BgColor = (Ctr->CtrCod == Gbl.Hierarchy.Ctr.CtrCod) ? "LIGHT_BLUE" : Gbl.ColorRows[Gbl.RowEvenOdd]; HTM_TR_Begin (NULL); /***** Number of centre in this list *****/ HTM_TD_Begin ("class=\"%s RM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%u",NumCtr); HTM_TD_End (); /***** Centre logo and name *****/ HTM_TD_Begin ("class=\"LM %s\"",BgColor); Ctr_DrawCentreLogoAndNameWithLink (Ctr,ActSeeDeg, TxtClassStrong,"CM"); HTM_TD_End (); /***** Number of users who claim to belong to this centre *****/ HTM_TD_Begin ("class=\"%s RM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%u",Ctr->NumUsrsWhoClaimToBelongToCtr); HTM_TD_End (); /***** Place *****/ HTM_TD_Begin ("class=\"%s LM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%s",Plc.ShrtName); HTM_TD_End (); /***** Number of degrees *****/ HTM_TD_Begin ("class=\"%s RM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%u",Ctr->Degs.Num); HTM_TD_End (); /***** Number of courses *****/ HTM_TD_Begin ("class=\"%s RM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%u",Ctr->NumCrss); HTM_TD_End (); /***** Number of users in courses of this centre *****/ HTM_TD_Begin ("class=\"%s RM %s\"",TxtClassNormal,BgColor); fprintf (Gbl.F.Out,"%u",Ctr->NumUsrs); HTM_TD_End (); /***** Centre status *****/ StatusTxt = Ctr_GetStatusTxtFromStatusBits (Ctr->Status); HTM_TD_Begin ("class=\"%s LM %s\"",TxtClassNormal,BgColor); if (StatusTxt != Ctr_STATUS_ACTIVE) // If active ==> do not show anything fprintf (Gbl.F.Out,"%s",Txt_CENTRE_STATUS[StatusTxt]); HTM_TD_End (); HTM_TR_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /*****************************************************************************/ /********** Get parameter with the type or order in list of centres **********/ /*****************************************************************************/ static void Ctr_GetParamCtrOrder (void) { Gbl.Hierarchy.Ins.Ctrs.SelectedOrder = (Ctr_Order_t) Par_GetParToUnsignedLong ("Order", 0, Ctr_NUM_ORDERS - 1, (unsigned long) Ctr_ORDER_DEFAULT); } /*****************************************************************************/ /************************** Put forms to edit centres ************************/ /*****************************************************************************/ void Ctr_EditCentres (void) { /***** Centre constructor *****/ Ctr_EditingCentreConstructor (); /***** Edit centres *****/ Ctr_EditCentresInternal (); /***** Centre destructor *****/ Ctr_EditingCentreDestructor (); } static void Ctr_EditCentresInternal (void) { extern const char *Hlp_INSTITUTION_Centres; extern const char *Txt_Centres_of_INSTITUTION_X; /***** Get list of places *****/ Gbl.Plcs.SelectedOrder = Plc_ORDER_BY_PLACE; Plc_GetListPlaces (); /***** Get list of centres *****/ Gbl.Hierarchy.Ins.Ctrs.SelectedOrder = Ctr_ORDER_BY_CENTRE; Ctr_GetListCentres (Gbl.Hierarchy.Ins.InsCod); /***** Write menu to select country and institution *****/ Hie_WriteMenuHierarchy (); /***** Begin box *****/ snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Centres_of_INSTITUTION_X, Gbl.Hierarchy.Ins.FullName); Box_BoxBegin (NULL,Gbl.Title,Ctr_PutIconsEditingCentres, Hlp_INSTITUTION_Centres,Box_NOT_CLOSABLE); /***** Put a form to create a new centre *****/ Ctr_PutFormToCreateCentre (); /***** List current centres *****/ if (Gbl.Hierarchy.Ins.Ctrs.Num) Ctr_ListCentresForEdition (); /***** End box *****/ Box_BoxEnd (); /***** Free list of centres *****/ Ctr_FreeListCentres (); /***** Free list of places *****/ Plc_FreeListPlaces (); } /*****************************************************************************/ /**************** Put contextual icons in edition of centres *****************/ /*****************************************************************************/ static void Ctr_PutIconsEditingCentres (void) { /***** Put icon to view centres *****/ Ctr_PutIconToViewCentres (); /***** Put icon to view places *****/ Plc_PutIconToViewPlaces (); /***** Put icon to show a figure *****/ Gbl.Figures.FigureType = Fig_HIERARCHY; Fig_PutIconToShowFigure (); } void Ctr_PutIconToViewCentres (void) { extern const char *Txt_Centres; Lay_PutContextualLinkOnlyIcon (ActSeeCtr,NULL,NULL, "building.svg", Txt_Centres); } /*****************************************************************************/ /***** Get a list with all the centres or with those of an institution *******/ /*****************************************************************************/ // If InsCod <= 0 ==> get all the centres, of any institution // In InsCod > 0 ==> get only the centres of the specified institution void Ctr_GetListCentres (long InsCod) { static const char *OrderBySubQuery[Ctr_NUM_ORDERS] = { "FullName", // Ctr_ORDER_BY_CENTRE "NumUsrs DESC,FullName", // Ctr_ORDER_BY_NUM_TCHS }; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; unsigned NumCtr; struct Centre *Ctr; /***** Get centres from database *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get centres", "(SELECT centres.CtrCod,centres.InsCod,centres.PlcCod," "centres.Status,centres.RequesterUsrCod," "centres.ShortName,centres.FullName,centres.WWW," "COUNT(DISTINCT usr_data.UsrCod) AS NumUsrs" " FROM centres,usr_data" " WHERE centres.InsCod=%ld" " AND centres.CtrCod=usr_data.CtrCod" " GROUP BY centres.CtrCod)" " UNION " "(SELECT CtrCod,InsCod,PlcCod,Status,RequesterUsrCod," "ShortName,FullName,WWW,0 AS NumUsrs" " FROM centres" " WHERE centres.InsCod=%ld" " AND CtrCod NOT IN" " (SELECT DISTINCT CtrCod FROM usr_data))" " ORDER BY %s", InsCod, InsCod, OrderBySubQuery[Gbl.Hierarchy.Ins.Ctrs.SelectedOrder]); if (NumRows) // Centres found... { // NumRows should be equal to Deg->NumCourses Gbl.Hierarchy.Ins.Ctrs.Num = (unsigned) NumRows; /***** Create list with courses in degree *****/ if ((Gbl.Hierarchy.Ins.Ctrs.Lst = (struct Centre *) calloc (NumRows,sizeof (struct Centre))) == NULL) Lay_NotEnoughMemoryExit (); /***** Get the centres *****/ for (NumCtr = 0; NumCtr < Gbl.Hierarchy.Ins.Ctrs.Num; NumCtr++) { Ctr = &(Gbl.Hierarchy.Ins.Ctrs.Lst[NumCtr]); /* Get next centre */ row = mysql_fetch_row (mysql_res); /* Get centre code (row[0]) */ if ((Ctr->CtrCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) Lay_ShowErrorAndExit ("Wrong code of centre."); /* Get institution code (row[1]) */ Ctr->InsCod = Str_ConvertStrCodToLongCod (row[1]); /* Get place code (row[2]) */ Ctr->PlcCod = Str_ConvertStrCodToLongCod (row[2]); /* Get centre status (row[3]) */ if (sscanf (row[3],"%u",&(Ctr->Status)) != 1) Lay_ShowErrorAndExit ("Wrong centre status."); /* Get requester user's code (row[4]) */ Ctr->RequesterUsrCod = Str_ConvertStrCodToLongCod (row[4]); /* Get the short name of the centre (row[5]) */ Str_Copy (Ctr->ShrtName,row[5], Hie_MAX_BYTES_SHRT_NAME); /* Get the full name of the centre (row[6]) */ Str_Copy (Ctr->FullName,row[6], Hie_MAX_BYTES_FULL_NAME); /* Get the URL of the centre (row[7]) */ Str_Copy (Ctr->WWW,row[7], Cns_MAX_BYTES_WWW); /* Get number of users who claim to belong to this centre (row[8]) */ if (sscanf (row[8],"%u",&Ctr->NumUsrsWhoClaimToBelongToCtr) != 1) Ctr->NumUsrsWhoClaimToBelongToCtr = 0; /* Get number of degrees in this centre */ Ctr->Degs.Num = Deg_GetNumDegsInCtr (Ctr->CtrCod); /* Get number of courses in this centre */ Ctr->NumCrss = Crs_GetNumCrssInCtr (Ctr->CtrCod); /* Get number of users in courses of this centre */ Ctr->NumUsrs = Usr_GetNumUsrsInCrssOfCtr (Rol_UNK,Ctr->CtrCod); // Here Rol_UNK means "all users" } } else Gbl.Hierarchy.Ins.Ctrs.Num = 0; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /************************ Get data of centre by code *************************/ /*****************************************************************************/ bool Ctr_GetDataOfCentreByCod (struct Centre *Ctr) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; bool CtrFound = false; /***** Clear data *****/ Ctr->InsCod = -1L; Ctr->PlcCod = -1L; Ctr->Status = (Ctr_Status_t) 0; Ctr->RequesterUsrCod = -1L; Ctr->ShrtName[0] = '\0'; Ctr->FullName[0] = '\0'; Ctr->WWW[0] = '\0'; Ctr->NumUsrsWhoClaimToBelongToCtr = 0; Ctr->Degs.Num = Ctr->NumCrss = 0; Ctr->NumUsrs = 0; /***** Check if centre code is correct *****/ if (Ctr->CtrCod > 0) { /***** Get data of a centre from database *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get data of a centre", "(SELECT centres.InsCod,centres.PlcCod," "centres.Status,centres.RequesterUsrCod," "centres.ShortName,centres.FullName,centres.WWW," "COUNT(DISTINCT usr_data.UsrCod) AS NumUsrs" " FROM centres,usr_data" " WHERE centres.CtrCod=%ld" " AND centres.CtrCod=usr_data.CtrCod" " GROUP BY centres.CtrCod)" " UNION " "(SELECT InsCod,PlcCod," "Status,RequesterUsrCod," "ShortName,FullName,WWW," "0 AS NumUsrs" " FROM centres" " WHERE CtrCod=%ld" " AND CtrCod NOT IN" " (SELECT DISTINCT CtrCod FROM usr_data))", Ctr->CtrCod, Ctr->CtrCod); if (NumRows) // Centre found... { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get the code of the institution (row[0]) */ Ctr->InsCod = Str_ConvertStrCodToLongCod (row[0]); /* Get the code of the place (row[1]) */ Ctr->PlcCod = Str_ConvertStrCodToLongCod (row[1]); /* Get centre status (row[2]) */ if (sscanf (row[2],"%u",&(Ctr->Status)) != 1) Lay_ShowErrorAndExit ("Wrong centre status."); /* Get requester user's code (row[3]) */ Ctr->RequesterUsrCod = Str_ConvertStrCodToLongCod (row[3]); /* Get the short name of the centre (row[4]) */ Str_Copy (Ctr->ShrtName,row[4], Hie_MAX_BYTES_SHRT_NAME); /* Get the full name of the centre (row[5]) */ Str_Copy (Ctr->FullName,row[5], Hie_MAX_BYTES_FULL_NAME); /* Get the URL of the centre (row[6]) */ Str_Copy (Ctr->WWW,row[6], Cns_MAX_BYTES_WWW); /* Get number of users who claim to belong to this centre (row[7]) */ if (sscanf (row[7],"%u",&Ctr->NumUsrsWhoClaimToBelongToCtr) != 1) Ctr->NumUsrsWhoClaimToBelongToCtr = 0; /* Get number of degrees in this centre */ Ctr->Degs.Num = Deg_GetNumDegsInCtr (Ctr->CtrCod); /* Get number of courses in this centre */ Ctr->NumCrss = Crs_GetNumCrssInCtr (Ctr->CtrCod); /* Get number of users in courses of this centre */ Ctr->NumUsrs = Usr_GetNumUsrsInCrssOfCtr (Rol_UNK,Ctr->CtrCod); // Here Rol_UNK means "all users" /* Set return value */ CtrFound = true; } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } return CtrFound; } /*****************************************************************************/ /*********** Get the institution code of a centre from its code **************/ /*****************************************************************************/ long Ctr_GetInsCodOfCentreByCod (long CtrCod) { MYSQL_RES *mysql_res; MYSQL_ROW row; long InsCod = -1L; if (CtrCod > 0) { /***** Get the institution code of a centre from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get the institution of a centre", "SELECT InsCod FROM centres WHERE CtrCod=%ld", CtrCod) == 1) { /***** Get the institution code of this centre *****/ row = mysql_fetch_row (mysql_res); InsCod = Str_ConvertStrCodToLongCod (row[0]); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } return InsCod; } /*****************************************************************************/ /*************** Get the short name of a centre from its code ****************/ /*****************************************************************************/ void Ctr_GetShortNameOfCentreByCod (struct Centre *Ctr) { MYSQL_RES *mysql_res; MYSQL_ROW row; Ctr->ShrtName[0] = '\0'; if (Ctr->CtrCod > 0) { /***** Get the short name of a centre from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get the short name of a centre", "SELECT ShortName FROM centres" " WHERE CtrCod=%ld", Ctr->CtrCod) == 1) { /***** Get the short name of this centre *****/ row = mysql_fetch_row (mysql_res); Str_Copy (Ctr->ShrtName,row[0], Hie_MAX_BYTES_SHRT_NAME); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } } /*****************************************************************************/ /******************* Get photo attribution from database *********************/ /*****************************************************************************/ static void Ctr_GetPhotoAttribution (long CtrCod,char **PhotoAttribution) { MYSQL_RES *mysql_res; MYSQL_ROW row; size_t Length; /***** Free possible former photo attribution *****/ Ctr_FreePhotoAttribution (PhotoAttribution); /***** Get photo attribution from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get photo attribution", "SELECT PhotoAttribution" " FROM centres WHERE CtrCod=%ld", CtrCod)) { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get the attribution of the photo of the centre (row[0]) */ if (row[0]) if (row[0][0]) { Length = strlen (row[0]); if (((*PhotoAttribution) = (char *) malloc (Length + 1)) == NULL) Lay_ShowErrorAndExit ("Error allocating memory for photo attribution."); Str_Copy (*PhotoAttribution,row[0], Length); } } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /****************** Free memory used for photo attribution *******************/ /*****************************************************************************/ static void Ctr_FreePhotoAttribution (char **PhotoAttribution) { if (*PhotoAttribution) { free ((void *) *PhotoAttribution); *PhotoAttribution = NULL; } } /*****************************************************************************/ /**************************** Free list of centres ***************************/ /*****************************************************************************/ void Ctr_FreeListCentres (void) { if (Gbl.Hierarchy.Ins.Ctrs.Lst) { /***** Free memory used by the list of courses in degree *****/ free ((void *) Gbl.Hierarchy.Ins.Ctrs.Lst); Gbl.Hierarchy.Ins.Ctrs.Lst = NULL; Gbl.Hierarchy.Ins.Ctrs.Num = 0; } } /*****************************************************************************/ /************************** Write selector of centre *************************/ /*****************************************************************************/ void Ctr_WriteSelectorOfCentre (void) { extern const char *Txt_Centre; MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCtrs; unsigned NumCtr; long CtrCod; /***** Begin form *****/ Frm_StartFormGoTo (ActSeeDeg); fprintf (Gbl.F.Out,"", Gbl.Form.Id); fprintf (Gbl.F.Out,"",Txt_Another_place); for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) fprintf (Gbl.F.Out,"", Gbl.Plcs.Lst[NumPlc].PlcCod, (Gbl.Plcs.Lst[NumPlc].PlcCod == Ctr->PlcCod) ? " selected=\"selected\"" : "", Gbl.Plcs.Lst[NumPlc].ShrtName); HTM_SELECT_End (); Frm_EndForm (); } else for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) if (Gbl.Plcs.Lst[NumPlc].PlcCod == Ctr->PlcCod) fprintf (Gbl.F.Out,"%s",Gbl.Plcs.Lst[NumPlc].ShrtName); HTM_TD_End (); /* Centre short name */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActRenCtrSho); Ctr_PutParamOtherCtrCod (Ctr->CtrCod); HTM_INPUT_TEXT ("ShortName",Hie_MAX_CHARS_SHRT_NAME,Ctr->ShrtName,true, "class=\"INPUT_SHORT_NAME\""); Frm_EndForm (); } else fprintf (Gbl.F.Out,"%s",Ctr->ShrtName); HTM_TD_End (); /* Centre full name */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActRenCtrFul); Ctr_PutParamOtherCtrCod (Ctr->CtrCod); HTM_INPUT_TEXT ("FullName",Hie_MAX_CHARS_FULL_NAME,Ctr->FullName,true, "class=\"INPUT_FULL_NAME\""); Frm_EndForm (); } else fprintf (Gbl.F.Out,"%s",Ctr->FullName); HTM_TD_End (); /* Centre WWW */ HTM_TD_Begin ("class=\"DAT LM\""); if (ICanEdit) { Frm_StartForm (ActChgCtrWWW); Ctr_PutParamOtherCtrCod (Ctr->CtrCod); HTM_INPUT_URL ("WWW",Ctr->WWW,true, "class=\"INPUT_WWW\""); Frm_EndForm (); } else { Str_Copy (WWW,Ctr->WWW, Cns_MAX_BYTES_WWW); HTM_DIV_Begin ("class=\"EXTERNAL_WWW_SHORT\""); HTM_A_Begin ("href=\"%s\" target=\"_blank\"" " class=\"DAT\" title=\"%s\"",Ctr->WWW,Ctr->WWW); fprintf (Gbl.F.Out,"%s",WWW); HTM_A_End (); HTM_DIV_End (); } HTM_TD_End (); /* Number of users who claim to belong to this centre */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ctr->NumUsrsWhoClaimToBelongToCtr); HTM_TD_End (); /* Number of degrees */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ctr->Degs.Num); HTM_TD_End (); /* Number of users in courses of this centre */ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"%u",Ctr->NumUsrs); HTM_TD_End (); /* Centre requester */ UsrDat.UsrCod = Ctr->RequesterUsrCod; Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS); HTM_TD_Begin ("class=\"DAT INPUT_REQUESTER LT\""); Msg_WriteMsgAuthor (&UsrDat,true,NULL); HTM_TD_End (); /* Centre status */ StatusTxt = Ctr_GetStatusTxtFromStatusBits (Ctr->Status); HTM_TD_Begin ("class=\"DAT LM\""); if (Gbl.Usrs.Me.Role.Logged >= Rol_INS_ADM && StatusTxt == Ctr_STATUS_PENDING) { Frm_StartForm (ActChgCtrSta); Ctr_PutParamOtherCtrCod (Ctr->CtrCod); fprintf (Gbl.F.Out,""); fprintf (Gbl.F.Out,"",Txt_Another_place); for (NumPlc = 0; NumPlc < Gbl.Plcs.Num; NumPlc++) fprintf (Gbl.F.Out,"", Gbl.Plcs.Lst[NumPlc].PlcCod, (Gbl.Plcs.Lst[NumPlc].PlcCod == Ctr_EditingCtr->PlcCod) ? " selected=\"selected\"" : "", Gbl.Plcs.Lst[NumPlc].ShrtName); HTM_SELECT_End (); HTM_TD_End (); /***** Centre short name *****/ HTM_TD_Begin ("class=\"LM\""); HTM_INPUT_TEXT ("ShortName",Hie_MAX_CHARS_SHRT_NAME,Ctr_EditingCtr->ShrtName,false, "class=\"INPUT_SHORT_NAME\" required=\"required\""); HTM_TD_End (); /***** Centre full name *****/ HTM_TD_Begin ("class=\"LM\""); HTM_INPUT_TEXT ("FullName",Hie_MAX_CHARS_FULL_NAME,Ctr_EditingCtr->FullName,false, "class=\"INPUT_FULL_NAME\" required=\"required\""); HTM_TD_End (); /***** Centre WWW *****/ HTM_TD_Begin ("class=\"LM\""); HTM_INPUT_URL ("WWW",Ctr_EditingCtr->WWW,false, "class=\"INPUT_WWW\" required=\"required\""); HTM_TD_End (); /***** Number of users who claim to belong to this centre *****/ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"0"); HTM_TD_End (); /***** Number of degrees *****/ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"0"); HTM_TD_End (); /***** Number of users in courses of this centre *****/ HTM_TD_Begin ("class=\"DAT RM\""); fprintf (Gbl.F.Out,"0"); HTM_TD_End (); /***** Centre requester *****/ HTM_TD_Begin ("class=\"DAT INPUT_REQUESTER LT\""); Msg_WriteMsgAuthor (&Gbl.Usrs.Me.UsrDat,true,NULL); HTM_TD_End (); /***** Centre status *****/ HTM_TD_Begin ("class=\"DAT LM\""); HTM_TD_End (); HTM_TR_End (); /***** End table, send button and end box *****/ Box_EndBoxTableWithButton (Btn_CREATE_BUTTON,Txt_Create_centre); /***** End form *****/ Frm_EndForm (); } /*****************************************************************************/ /******************** Write header with fields of a degree *******************/ /*****************************************************************************/ static void Ctr_PutHeadCentresForSeeing (bool OrderSelectable) { extern const char *Txt_CENTRES_HELP_ORDER[2]; extern const char *Txt_CENTRES_ORDER[2]; extern const char *Txt_Place; extern const char *Txt_Degrees_ABBREVIATION; extern const char *Txt_Courses_ABBREVIATION; extern const char *Txt_ROLES_PLURAL_BRIEF_Abc[Rol_NUM_ROLES]; Ctr_Order_t Order; HTM_TR_Begin (NULL); HTM_TH_Empty (1); for (Order = Ctr_ORDER_BY_CENTRE; Order <= Ctr_ORDER_BY_NUM_TCHS; Order++) { HTM_TH_Begin (1,1,Order == Ctr_ORDER_BY_CENTRE ? "LM" : "RM"); if (OrderSelectable) { Frm_StartForm (ActSeeCtr); Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Order); Frm_LinkFormSubmit (Txt_CENTRES_HELP_ORDER[Order],"TIT_TBL",NULL); if (Order == Gbl.Hierarchy.Ins.Ctrs.SelectedOrder) fprintf (Gbl.F.Out,""); } fprintf (Gbl.F.Out,"%s",Txt_CENTRES_ORDER[Order]); if (OrderSelectable) { if (Order == Gbl.Hierarchy.Ins.Ctrs.SelectedOrder) fprintf (Gbl.F.Out,""); Frm_LinkFormEnd (); Frm_EndForm (); } HTM_TH_End (); } HTM_TH (1,1,"LM",Txt_Place); HTM_TH (1,1,"RM",Txt_Degrees_ABBREVIATION); HTM_TH (1,1,"RM",Txt_Courses_ABBREVIATION); HTM_TH_Begin (1,1,"RM"); fprintf (Gbl.F.Out,"%s+
%s", Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH], Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]); HTM_TH_End (); HTM_TH_Empty (1); HTM_TR_End (); } /*****************************************************************************/ /******************** Write header with fields of a degree *******************/ /*****************************************************************************/ static void Ctr_PutHeadCentresForEdition (void) { extern const char *Txt_Code; extern const char *Txt_Place; extern const char *Txt_Short_name_of_the_centre; extern const char *Txt_Full_name_of_the_centre; extern const char *Txt_WWW; extern const char *Txt_Users; extern const char *Txt_Degrees_ABBREVIATION; extern const char *Txt_ROLES_PLURAL_BRIEF_Abc[Rol_NUM_ROLES]; extern const char *Txt_Requester; HTM_TR_Begin (NULL); HTM_TH_Empty (1); HTM_TH (1,1,"RM",Txt_Code); HTM_TH_Empty (1); HTM_TH (1,1,"LM",Txt_Place); HTM_TH (1,1,"LM",Txt_Short_name_of_the_centre); HTM_TH (1,1,"LM",Txt_Full_name_of_the_centre); HTM_TH (1,1,"LM",Txt_WWW); HTM_TH (1,1,"RM",Txt_Users); HTM_TH (1,1,"RM",Txt_Degrees_ABBREVIATION); HTM_TH_Begin (1,1,"RM"); fprintf (Gbl.F.Out,"%s+
%s", Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH], Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]); HTM_TH_End (); HTM_TH (1,1,"LM",Txt_Requester); HTM_TH_Empty (1); HTM_TR_End (); } /*****************************************************************************/ /****************** Receive form to request a new centre *********************/ /*****************************************************************************/ void Ctr_RecFormReqCtr (void) { /***** Centre constructor *****/ Ctr_EditingCentreConstructor (); /***** Receive form to request a new centre *****/ Ctr_RecFormRequestOrCreateCtr ((unsigned) Ctr_STATUS_BIT_PENDING); } /*****************************************************************************/ /******************* Receive form to create a new centre *********************/ /*****************************************************************************/ void Ctr_RecFormNewCtr (void) { /***** Centre constructor *****/ Ctr_EditingCentreConstructor (); /***** Receive form to create a new centre *****/ Ctr_RecFormRequestOrCreateCtr (0); } /*****************************************************************************/ /************* Receive form to request or create a new centre ****************/ /*****************************************************************************/ static void Ctr_RecFormRequestOrCreateCtr (unsigned Status) { extern const char *Txt_The_centre_X_already_exists; extern const char *Txt_Created_new_centre_X; extern const char *Txt_You_must_specify_the_web_address_of_the_new_centre; extern const char *Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_centre; /***** Get parameters from form *****/ /* Set centre institution */ Ctr_EditingCtr->InsCod = Gbl.Hierarchy.Ins.InsCod; /* Get place */ if ((Ctr_EditingCtr->PlcCod = Plc_GetParamPlcCod ()) < 0) // 0 is reserved for "other place" Ale_ShowAlert (Ale_ERROR,"Wrong place."); /* Get centre short name */ Par_GetParToText ("ShortName",Ctr_EditingCtr->ShrtName,Hie_MAX_BYTES_SHRT_NAME); /* Get centre full name */ Par_GetParToText ("FullName",Ctr_EditingCtr->FullName,Hie_MAX_BYTES_FULL_NAME); /* Get centre WWW */ Par_GetParToText ("WWW",Ctr_EditingCtr->WWW,Cns_MAX_BYTES_WWW); if (Ctr_EditingCtr->ShrtName[0] && Ctr_EditingCtr->FullName[0]) // If there's a centre name { if (Ctr_EditingCtr->WWW[0]) { /***** If name of centre was in database... *****/ if (Ctr_CheckIfCtrNameExistsInIns ("ShortName",Ctr_EditingCtr->ShrtName,-1L,Gbl.Hierarchy.Ins.InsCod)) Ale_CreateAlert (Ale_WARNING,NULL, Txt_The_centre_X_already_exists, Ctr_EditingCtr->ShrtName); else if (Ctr_CheckIfCtrNameExistsInIns ("FullName",Ctr_EditingCtr->FullName,-1L,Gbl.Hierarchy.Ins.InsCod)) Ale_CreateAlert (Ale_WARNING,NULL, Txt_The_centre_X_already_exists, Ctr_EditingCtr->FullName); else // Add new centre to database { Ctr_CreateCentre (Status); Ale_CreateAlert (Ale_SUCCESS,NULL, Txt_Created_new_centre_X, Ctr_EditingCtr->FullName); } } else // If there is not a web Ale_CreateAlert (Ale_WARNING,NULL, Txt_You_must_specify_the_web_address_of_the_new_centre); } else // If there is not a centre name Ale_CreateAlert (Ale_WARNING,NULL, Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_centre); } /*****************************************************************************/ /***************************** Create a new centre ***************************/ /*****************************************************************************/ static void Ctr_CreateCentre (unsigned Status) { /***** Create a new centre *****/ Ctr_EditingCtr->CtrCod = DB_QueryINSERTandReturnCode ("can not create a new centre", "INSERT INTO centres" " (InsCod,PlcCod,Status,RequesterUsrCod," "ShortName,FullName,WWW,PhotoAttribution)" " VALUES" " (%ld,%ld,%u,%ld," "'%s','%s','%s','')", Ctr_EditingCtr->InsCod, Ctr_EditingCtr->PlcCod, Status, Gbl.Usrs.Me.UsrDat.UsrCod, Ctr_EditingCtr->ShrtName, Ctr_EditingCtr->FullName, Ctr_EditingCtr->WWW); } /*****************************************************************************/ /************************** Get number of centres ****************************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsTotal (void) { /***** Get total number of centres from database *****/ return (unsigned) DB_GetNumRowsTable ("centres"); } /*****************************************************************************/ /******************* Get number of centres in a country **********************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsInCty (long CtyCod) { /***** Get number of centres of a country from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of centres in a country", "SELECT COUNT(*) FROM institutions,centres" " WHERE institutions.CtyCod=%ld" " AND institutions.InsCod=centres.InsCod", CtyCod); } /*****************************************************************************/ /**************** Get number of centres in an institution ********************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsInIns (long InsCod) { /***** Get number of centres of an institution from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of centres in an institution", "SELECT COUNT(*) FROM centres" " WHERE InsCod=%ld", InsCod); } /*****************************************************************************/ /******* Get number of centres (of the current institution) in a place *******/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsInPlc (long PlcCod) { /***** Get number of centres (of the current institution) in a place *****/ return (unsigned) DB_QueryCOUNT ("can not get the number of centres in a place", "SELECT COUNT(*) FROM centres" " WHERE InsCod=%ld AND PlcCod=%ld", Gbl.Hierarchy.Ins.InsCod,PlcCod); } /*****************************************************************************/ /********************* Get number of centres with degrees ********************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsWithDegs (const char *SubQuery) { /***** Get number of centres with degrees from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of centres with degrees", "SELECT COUNT(DISTINCT centres.CtrCod)" " FROM institutions,centres,degrees" " WHERE %sinstitutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod", SubQuery); } /*****************************************************************************/ /********************* Get number of centres with courses ********************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsWithCrss (const char *SubQuery) { /***** Get number of centres with courses from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of centres with courses", "SELECT COUNT(DISTINCT centres.CtrCod)" " FROM institutions,centres,degrees,courses" " WHERE %sinstitutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod", SubQuery); } /*****************************************************************************/ /********************* Get number of centres with users **********************/ /*****************************************************************************/ unsigned Ctr_GetNumCtrsWithUsrs (Rol_Role_t Role,const char *SubQuery) { /***** Get number of centres with users from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of centres with users", "SELECT COUNT(DISTINCT centres.CtrCod)" " FROM institutions,centres,degrees,courses,crs_usr" " WHERE %sinstitutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=crs_usr.CrsCod" " AND crs_usr.Role=%u", SubQuery,(unsigned) Role); } /*****************************************************************************/ /****************************** List centres found ***************************/ /*****************************************************************************/ void Ctr_ListCtrsFound (MYSQL_RES **mysql_res,unsigned NumCtrs) { extern const char *Txt_centre; extern const char *Txt_centres; MYSQL_ROW row; unsigned NumCtr; struct Centre Ctr; /***** Query database *****/ if (NumCtrs) { /***** Begin box and table *****/ /* Number of centres found */ snprintf (Gbl.Title,sizeof (Gbl.Title), "%u %s", NumCtrs,(NumCtrs == 1) ? Txt_centre : Txt_centres); Box_StartBoxTable (NULL,Gbl.Title,NULL, NULL,Box_NOT_CLOSABLE,2); /***** Write heading *****/ Ctr_PutHeadCentresForSeeing (false); // Order not selectable /***** List the centres (one row per centre) *****/ for (NumCtr = 1; NumCtr <= NumCtrs; NumCtr++) { /* Get next centre */ row = mysql_fetch_row (*mysql_res); /* Get centre code (row[0]) */ Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[0]); /* Get data of centre */ Ctr_GetDataOfCentreByCod (&Ctr); /* Write data of this centre */ Ctr_ListOneCentreForSeeing (&Ctr,NumCtr); } /***** End table and box *****/ Box_EndBoxTable (); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (mysql_res); } /*****************************************************************************/ /************************ Centre constructor/destructor **********************/ /*****************************************************************************/ static void Ctr_EditingCentreConstructor (void) { /***** Pointer must be NULL *****/ if (Ctr_EditingCtr != NULL) Lay_ShowErrorAndExit ("Error initializing centre."); /***** Allocate memory for centre *****/ if ((Ctr_EditingCtr = (struct Centre *) malloc (sizeof (struct Centre))) == NULL) Lay_ShowErrorAndExit ("Error allocating memory for centre."); /***** Reset centre *****/ Ctr_EditingCtr->CtrCod = -1L; Ctr_EditingCtr->InsCod = -1L; Ctr_EditingCtr->PlcCod = -1L; Ctr_EditingCtr->RequesterUsrCod = -1L; Ctr_EditingCtr->ShrtName[0] = '\0'; Ctr_EditingCtr->FullName[0] = '\0'; Ctr_EditingCtr->WWW[0] = '\0'; Ctr_EditingCtr->Degs.Num = 0; Ctr_EditingCtr->Degs.Lst = NULL; Ctr_EditingCtr->NumCrss = 0; Ctr_EditingCtr->NumUsrs = 0; Ctr_EditingCtr->NumUsrsWhoClaimToBelongToCtr = 0; } static void Ctr_EditingCentreDestructor (void) { /***** Free memory used for centre *****/ if (Ctr_EditingCtr != NULL) { free ((void *) Ctr_EditingCtr); Ctr_EditingCtr = NULL; } }