// swad_country_config.c: configuration of current country /* 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-2024 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 boolean type #include // For NULL #include // For asprintf #include // For free #include // For string functions #include "swad_action_list.h" #include "swad_box.h" #include "swad_country_config.h" #include "swad_country_database.h" #include "swad_database.h" #include "swad_error.h" #include "swad_figure_cache.h" #include "swad_form.h" #include "swad_global.h" #include "swad_help.h" #include "swad_hierarchy.h" #include "swad_hierarchy_config.h" #include "swad_hierarchy_type.h" #include "swad_HTML.h" #include "swad_parameter.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void CtyCfg_Configuration (Vie_ViewType_t ViewType); static void CtyCfg_PutIconToPrint (__attribute__((unused)) void *Args); static void CtyCfg_Title (Hie_PutLink_t PutLink); static void CtyCfg_Map (void); static void CtyCfg_MapImage (Vie_ViewType_t ViewType,Hie_PutLink_t PutLink); static void CtyCfg_Platform (Vie_ViewType_t ViewType); static void CtyCfg_Name (Hie_PutLink_t PutLink); static void CtyCfg_NumUsrs (void); static void CtyCfg_NumInss (void); static void CtyCfg_NumDegs (void); static void CtyCfg_NumCrss (void); static void CtyCfg_GetMapAttr (long CtyCod,char **MapAttribution); static void CtyCfg_FreeMapAttr (char **MapAttribution); /*****************************************************************************/ /***************** Show information of the current country *******************/ /*****************************************************************************/ void CtyCfg_ShowConfiguration (void) { CtyCfg_Configuration (Vie_VIEW); /***** Show help to enrol me *****/ Hlp_ShowHelpWhatWouldYouLikeToDo (); } /*****************************************************************************/ /***************** Print information of the current country ******************/ /*****************************************************************************/ void CtyCfg_PrintConfiguration (void) { CtyCfg_Configuration (Vie_PRINT); } /*****************************************************************************/ /******************** Information of the current country *********************/ /*****************************************************************************/ static void CtyCfg_Configuration (Vie_ViewType_t ViewType) { extern const char *Hlp_COUNTRY_Information; Hie_PutLink_t PutLink; bool MapImageExists; unsigned NumCtrs; unsigned NumCtrsWithMap; /***** Trivial check *****/ if (Gbl.Hierarchy.Node[Hie_CTY].HieCod <= 0) // No country selected return; /***** Initializations *****/ PutLink = (ViewType == Vie_VIEW && Gbl.Hierarchy.Node[Hie_CTY].WWW[0]) ? Hie_PUT_LINK : Hie_DONT_PUT_LINK; /***** Begin box *****/ Box_BoxBegin (NULL, ViewType == Vie_VIEW ? CtyCfg_PutIconToPrint : NULL,NULL, ViewType == Vie_VIEW ? Hlp_COUNTRY_Information : NULL,Box_NOT_CLOSABLE); /***** Title *****/ CtyCfg_Title (PutLink); /**************************** Left part ***********************************/ HTM_DIV_Begin ("class=\"HIE_CFG_LEFT\""); /* Begin table */ HTM_TABLE_BeginPadding (2); /* Platform */ CtyCfg_Platform (ViewType); /* Country name (an link to WWW if exists) */ CtyCfg_Name (PutLink); /* Shortcut to the country */ HieCfg_Shortcut (ViewType,ParCod_Cty,Gbl.Hierarchy.Node[Hie_CTY].HieCod); NumCtrsWithMap = Ctr_GetCachedNumCtrsWithMapInCty (Gbl.Hierarchy.Node[Hie_CTY].HieCod); switch (ViewType) { case Vie_VIEW: NumCtrs = Hie_GetCachedNumNodesInHieLvl (Hie_CTR, // Number of centers... Hie_CTY, // ...in country Gbl.Hierarchy.Node[Hie_CTY].HieCod); /* Number of users who claim to belong to this country, number of institutions, number of centers, number of degrees, number of courses */ CtyCfg_NumUsrs (); CtyCfg_NumInss (); HieCfg_NumCtrs (NumCtrs,Frm_DONT_PUT_FORM); HieCfg_NumCtrsWithMap (NumCtrs,NumCtrsWithMap); CtyCfg_NumDegs (); CtyCfg_NumCrss (); /* Number of users in courses of this country */ HieCfg_NumUsrsInCrss (Hie_CTY,Gbl.Hierarchy.Node[Hie_CTY].HieCod,Rol_TCH); HieCfg_NumUsrsInCrss (Hie_CTY,Gbl.Hierarchy.Node[Hie_CTY].HieCod,Rol_NET); HieCfg_NumUsrsInCrss (Hie_CTY,Gbl.Hierarchy.Node[Hie_CTY].HieCod,Rol_STD); HieCfg_NumUsrsInCrss (Hie_CTY,Gbl.Hierarchy.Node[Hie_CTY].HieCod,Rol_UNK); break; case Vie_PRINT: /* QR code with link to the country */ HieCfg_QR (ParCod_Cty,Gbl.Hierarchy.Node[Hie_CTY].HieCod); break; default: Err_WrongTypeExit (); break; } /* End table */ HTM_TABLE_End (); /* End of left part */ HTM_DIV_End (); /**************************** Right part **********************************/ /* Check country map */ MapImageExists = Cty_CheckIfCountryPhotoExists (&Gbl.Hierarchy.Node[Hie_CTY]); if (NumCtrsWithMap || MapImageExists) { /* Begin container */ HTM_DIV_Begin ("class=\"HIE_CFG_RIGHT\""); /* Country map */ if (NumCtrsWithMap) CtyCfg_Map (); /* Country map image */ if (MapImageExists) CtyCfg_MapImage (ViewType,PutLink); /* End container */ HTM_DIV_End (); } /***** End box *****/ Box_BoxEnd (); } /*****************************************************************************/ /************* Put icon to print the configuration of a country **************/ /*****************************************************************************/ static void CtyCfg_PutIconToPrint (__attribute__((unused)) void *Args) { Ico_PutContextualIconToPrint (ActPrnCtyInf,NULL,NULL); } /*****************************************************************************/ /******************** Show title in country configuration ********************/ /*****************************************************************************/ static void CtyCfg_Title (Hie_PutLink_t PutLink) { /***** Begin container *****/ HTM_DIV_Begin ("class=\"FRAME_TITLE FRAME_TITLE_BIG FRAME_TITLE_%s\"", The_GetSuffix ()); /* Begin link */ if (PutLink == Hie_PUT_LINK) HTM_A_Begin ("href=\"%s\" target=\"_blank\" title=\"%s\"" " class=\"FRAME_TITLE_BIG FRAME_TITLE_%s\"", Gbl.Hierarchy.Node[Hie_CTY].WWW, Gbl.Hierarchy.Node[Hie_CTY].FullName, The_GetSuffix ()); /* Country name */ HTM_Txt (Gbl.Hierarchy.Node[Hie_CTY].FullName); /* End link */ if (PutLink == Hie_PUT_LINK) HTM_A_End (); /***** End container *****/ HTM_DIV_End (); } /*****************************************************************************/ /****************************** Draw country map *****************************/ /*****************************************************************************/ #define CtyCfg_MAP_CONTAINER_ID "cty_mapid" static void CtyCfg_Map (void) { extern bool (*Hie_GetDataByCod[Hie_NUM_LEVELS]) (struct Hie_Node *Node); MYSQL_RES *mysql_res; struct Map_Coordinates CtyAvgCoord; unsigned Zoom; unsigned NumCtrs; unsigned NumCtr; struct Hie_Node Ins; struct Hie_Node Ctr; struct Map_Coordinates Coord; /***** Leaflet CSS *****/ Map_LeafletCSS (); /***** Leaflet script *****/ Map_LeafletScript (); /***** Container for the map *****/ HTM_DIV_Begin ("id=\"%s\"",CtyCfg_MAP_CONTAINER_ID); HTM_DIV_End (); /***** Script to draw the map *****/ HTM_SCRIPT_Begin (NULL,NULL); /* Let's create a map with pretty Mapbox Streets tiles */ Cty_DB_GetAvgCoordAndZoom (&CtyAvgCoord,&Zoom); Map_CreateMap (CtyCfg_MAP_CONTAINER_ID,&CtyAvgCoord,Zoom); /* Add Mapbox Streets tile layer to our map */ Map_AddTileLayer (); /* Get centers which have coordinates in the current country */ NumCtrs = Cty_DB_GetCtrsWithCoordsInCurrentCty (&mysql_res); /* Add a marker and a popup for each center */ for (NumCtr = 0; NumCtr < NumCtrs; NumCtr++) { /* Get next center */ Ctr.HieCod = DB_GetNextCode (mysql_res); /* Get data of center */ Hie_GetDataByCod[Hie_CTR] (&Ctr); /* Get coordinates of center */ Ctr_GetCoordByCod (Ctr.HieCod,&Coord); /* Get data of institution */ Ins.HieCod = Ctr.PrtCod; Hie_GetDataByCod[Hie_INS] (&Ins); /* Add marker */ Map_AddMarker (&Coord); /* Add popup */ Map_AddPopup (Ctr.ShrtName,Ins.ShrtName, false); // Closed } /* Free structure that stores the query result */ DB_FreeMySQLResult (&mysql_res); HTM_SCRIPT_End (); } /*****************************************************************************/ /************* Show country map image in country configuration ***************/ /*****************************************************************************/ static void CtyCfg_MapImage (Vie_ViewType_t ViewType,Hie_PutLink_t PutLink) { char *MapAttribution = NULL; /***** Get map attribution *****/ CtyCfg_GetMapAttr (Gbl.Hierarchy.Node[Hie_CTY].HieCod,&MapAttribution); /***** Map image *****/ HTM_DIV_Begin ("class=\"CM\""); if (PutLink == Hie_PUT_LINK) HTM_A_Begin ("href=\"%s\" target=\"_blank\"", Gbl.Hierarchy.Node[Hie_CTY].WWW); Cty_DrawCountryMap (&Gbl.Hierarchy.Node[Hie_CTY], ViewType == Vie_VIEW ? "COUNTRY_MAP_SHOW" : "COUNTRY_MAP_PRINT"); if (PutLink == Hie_PUT_LINK) HTM_A_End (); HTM_DIV_End (); /***** Map attribution *****/ if (ViewType == Vie_VIEW && Cty_CheckIfICanEditCountries () == Usr_CAN) { HTM_DIV_Begin ("class=\"CM\""); Frm_BeginForm (ActChgCtyMapAtt); HTM_TEXTAREA_Begin ("id=\"AttributionArea\" name=\"Attribution\"" " rows=\"3\"" " onchange=\"this.form.submit();return false;\""); if (MapAttribution) HTM_Txt (MapAttribution); HTM_TEXTAREA_End (); Frm_EndForm (); HTM_DIV_End (); } else if (MapAttribution) { HTM_DIV_Begin ("class=\"ATTRIBUTION\""); HTM_Txt (MapAttribution); HTM_DIV_End (); } /***** Free memory used for map attribution *****/ CtyCfg_FreeMapAttr (&MapAttribution); } /*****************************************************************************/ /****************** Show platform in country configuration *******************/ /*****************************************************************************/ static void CtyCfg_Platform (Vie_ViewType_t ViewType) { extern const char *Txt_HIERARCHY_SINGUL_Abc[Hie_NUM_LEVELS]; /***** Institution *****/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_HIERARCHY_SINGUL_Abc[Hie_SYS]); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LT DAT_%s\"",The_GetSuffix ()); if (ViewType == Vie_VIEW) { Frm_BeginFormGoTo (ActSeeSysInf); HTM_BUTTON_Submit_Begin (Str_BuildGoToTitle (Cfg_PLATFORM_SHORT_NAME), "class=\"LT BT_LINK\""); Str_FreeGoToTitle (); } Ico_PutIcon ("swad64x64.png",Ico_UNCHANGED,Cfg_PLATFORM_FULL_NAME,"ICO20x20"); HTM_NBSP (); HTM_Txt (Cfg_PLATFORM_SHORT_NAME); if (ViewType == Vie_VIEW) { HTM_BUTTON_End (); Frm_EndForm (); } HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /**************** Show country name in country configuration *****************/ /*****************************************************************************/ static void CtyCfg_Name (Hie_PutLink_t PutLink) { extern const char *Txt_HIERARCHY_SINGUL_Abc[Hie_NUM_LEVELS]; /***** Country name *****/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_HIERARCHY_SINGUL_Abc[Hie_CTY]); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LB DAT_STRONG_%s\"",The_GetSuffix ()); if (PutLink == Hie_PUT_LINK) HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"DAT_STRONG_%s\"", Gbl.Hierarchy.Node[Hie_CTY].WWW, The_GetSuffix ()); HTM_Txt (Gbl.Hierarchy.Node[Hie_CTY].FullName); if (PutLink == Hie_PUT_LINK) HTM_A_End (); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*** Show number of users who claim to belong to country in country config. **/ /*****************************************************************************/ static void CtyCfg_NumUsrs (void) { extern const char *Txt_Users_of_the_country; /***** Number of users *****/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_Users_of_the_country); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LB DAT_%s\"",The_GetSuffix ()); HTM_Unsigned (Hie_GetCachedNumUsrsWhoClaimToBelongTo (Hie_CTY, &Gbl.Hierarchy.Node[Hie_CTY])); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*********** Show number of institutions in country configuration ************/ /*****************************************************************************/ static void CtyCfg_NumInss (void) { extern const char *Txt_HIERARCHY_PLURAL_Abc[Hie_NUM_LEVELS]; extern const char *Txt_Institutions_of_COUNTRY_X; char *Title; /***** Number of institutions ******/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_HIERARCHY_PLURAL_Abc[Hie_INS]); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LT DAT_%s\"",The_GetSuffix ()); Frm_BeginFormGoTo (ActSeeIns); ParCod_PutPar (ParCod_Cty,Gbl.Hierarchy.Node[Hie_CTY].HieCod); if (asprintf (&Title,Txt_Institutions_of_COUNTRY_X, Gbl.Hierarchy.Node[Hie_CTY].FullName) < 0) Err_NotEnoughMemoryExit (); HTM_BUTTON_Submit_Begin (Title,"class=\"LT BT_LINK\""); free (Title); HTM_Unsigned (Hie_GetCachedNumNodesInHieLvl (Hie_INS, // Number of institutions... Hie_CTY, // ...in country Gbl.Hierarchy.Node[Hie_CTY].HieCod)); HTM_BUTTON_End (); Frm_EndForm (); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /************* Show number of degrees in country configuration ***************/ /*****************************************************************************/ static void CtyCfg_NumDegs (void) { extern const char *Txt_HIERARCHY_PLURAL_Abc[Hie_NUM_LEVELS]; /***** Number of degrees *****/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_HIERARCHY_PLURAL_Abc[Hie_DEG]); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LB DAT_%s\"",The_GetSuffix ()); HTM_Unsigned (Hie_GetCachedNumNodesInHieLvl (Hie_DEG, // Number of degrees... Hie_CTY, // ...in country Gbl.Hierarchy.Node[Hie_CTY].HieCod)); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /************* Show number of courses in country configuration ***************/ /*****************************************************************************/ static void CtyCfg_NumCrss (void) { extern const char *Txt_HIERARCHY_PLURAL_Abc[Hie_NUM_LEVELS]; /***** Number of courses *****/ HTM_TR_Begin (NULL); /* Label */ Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_HIERARCHY_PLURAL_Abc[Hie_CRS]); /* Data */ HTM_TD_Begin ("class=\"Frm_C2 LB DAT_%s\"",The_GetSuffix ()); HTM_Unsigned (Hie_GetCachedNumNodesInHieLvl (Hie_CRS, // Number of courses... Hie_CTY, // ...in country Gbl.Hierarchy.Node[Hie_CTY].HieCod)); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /******************** Get map attribution from database **********************/ /*****************************************************************************/ static void CtyCfg_GetMapAttr (long CtyCod,char **MapAttribution) { MYSQL_RES *mysql_res; MYSQL_ROW row; size_t Length; /***** Free possible former map attribution *****/ CtyCfg_FreeMapAttr (MapAttribution); /***** Get map attribution from database *****/ if (Cty_DB_GetMapAttr (&mysql_res,CtyCod)) { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get the attribution of the map of the country (row[0]) */ if (row[0]) if (row[0][0]) { Length = strlen (row[0]); if ((*MapAttribution = malloc (Length + 1)) == NULL) Err_NotEnoughMemoryExit (); Str_Copy (*MapAttribution,row[0],Length); } } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /******************* Free memory used for map attribution ********************/ /*****************************************************************************/ static void CtyCfg_FreeMapAttr (char **MapAttribution) { if (*MapAttribution) { free (*MapAttribution); *MapAttribution = NULL; } } /*****************************************************************************/ /*********** Change the attribution of the map of current country ************/ /*****************************************************************************/ void CtyCfg_ChangeCtyMapAttr (void) { char NewMapAttribution[Med_MAX_BYTES_ATTRIBUTION + 1]; /***** Get parameters from form *****/ /* Get the new map attribution for the country */ Par_GetParText ("Attribution",NewMapAttribution,Med_MAX_BYTES_ATTRIBUTION); /***** Change old attribution by new attribution in database *****/ Cty_DB_UpdateCtyMapAttr (NewMapAttribution); /***** Show the country information again *****/ CtyCfg_ShowConfiguration (); }