From 52bdf295891b700d9f558f8a4b2155094b5f1f0c Mon Sep 17 00:00:00 2001 From: acanas Date: Wed, 22 Apr 2020 03:19:27 +0200 Subject: [PATCH] Version19.192 --- swad_building.c | 975 ++++++++++++++++++++++++++++++++++++++++++++++++ swad_building.h | 104 ++++++ 2 files changed, 1079 insertions(+) create mode 100644 swad_building.c create mode 100644 swad_building.h diff --git a/swad_building.c b/swad_building.c new file mode 100644 index 00000000..be572144 --- /dev/null +++ b/swad_building.c @@ -0,0 +1,975 @@ +// swad_building.c: buildings in a centre + +/* + 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-2020 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 calloc, free +#include // For NULL +#include // For string functions + +#include "swad_box.h" +#include "swad_building.h" +#include "swad_database.h" +#include "swad_form.h" +#include "swad_global.h" +#include "swad_HTML.h" + +/*****************************************************************************/ +/************** External global variables from others modules ****************/ +/*****************************************************************************/ + +extern struct Globals Gbl; + +/*****************************************************************************/ +/***************************** Private constants *****************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/******************************* Private types *******************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/***************************** Private variables *****************************/ +/*****************************************************************************/ + +static struct Bld_Building *Bld_EditingBuilding = NULL; // Static variable to keep the building being edited + +/*****************************************************************************/ +/***************************** Private prototypes ****************************/ +/*****************************************************************************/ + +static Bld_Order_t Bld_GetParamBuildingOrder (void); +static bool Bld_CheckIfICanCreateBuildings (void); +static void Bld_PutIconsListingBuildings (__attribute__((unused)) void *Args); +static void Bld_PutIconToEditBuildings (void); +static void Bld_PutIconsEditingBuildings (__attribute__((unused)) void *Args); + +static void Bld_EditBuildingsInternal (void); + +static void Bld_ListBuildingsForEdition (const struct Bld_Buildings *Buildings); +static void Bld_PutParamBldCod (long BldCod); + +static void Bld_RenameBuilding (Cns_ShrtOrFullName_t ShrtOrFullName); +static bool Bld_CheckIfBuildingNameExists (const char *FieldName,const char *Name,long BldCod); +static void Bld_UpdateBuildingNameDB (long BldCod,const char *FieldName,const char *NewBuildingName); + +static void Bld_PutFormToCreateBuilding (void); +static void Bld_PutHeadBuildings (void); +static void Bld_CreateBuilding (struct Bld_Building *Building); + +static void Bld_EditingBuildingConstructor (void); +static void Bld_EditingBuildingDestructor (void); + +/*****************************************************************************/ +/************************** Reset buildings context **************************/ +/*****************************************************************************/ + +void Bld_ResetBuildings (struct Bld_Buildings *Buildings) + { + Buildings->Num = 0; // Number of buildings + Buildings->Lst = NULL; // List of buildings + Buildings->SelectedOrder = Bld_ORDER_DEFAULT; + } + +/*****************************************************************************/ +/************************** List all the buildings ***************************/ +/*****************************************************************************/ + +void Bld_SeeBuildings (void) + { + extern const char *Hlp_CENTRE_Buildings; + extern const char *Txt_Buildings; + extern const char *Txt_BUILDINGS_HELP_ORDER[Bld_NUM_ORDERS]; + extern const char *Txt_BUILDINGS_ORDER[Bld_NUM_ORDERS]; + extern const char *Txt_New_building; + struct Bld_Buildings Buildings; + Bld_Order_t Order; + unsigned NumBuilding; + unsigned RowEvenOdd; + + /***** Trivial check *****/ + if (Gbl.Hierarchy.Ctr.CtrCod <= 0) // No centre selected + return; + + /***** Reset buildings context *****/ + Bld_ResetBuildings (&Buildings); + + /***** Get parameter with the type of order in the list of buildings *****/ + Buildings.SelectedOrder = Bld_GetParamBuildingOrder (); + + /***** Get list of buildings *****/ + Bld_GetListBuildings (&Buildings,Bld_ALL_DATA); + + /***** Table head *****/ + Box_BoxBegin (NULL,Txt_Buildings, + Bld_PutIconsListingBuildings,NULL, + Hlp_CENTRE_Buildings,Box_NOT_CLOSABLE); + HTM_TABLE_BeginWideMarginPadding (2); + HTM_TR_Begin (NULL); + for (Order = (Bld_Order_t) 0; + Order <= (Bld_Order_t) (Bld_NUM_ORDERS - 1); + Order++) + { + HTM_TH_Begin (1,1,"LM"); + Frm_StartForm (ActSeeBld); + Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Order); + HTM_BUTTON_SUBMIT_Begin (Txt_BUILDINGS_HELP_ORDER[Order],"BT_LINK TIT_TBL",NULL); + if (Order == Buildings.SelectedOrder) + HTM_U_Begin (); + HTM_Txt (Txt_BUILDINGS_ORDER[Order]); + if (Order == Buildings.SelectedOrder) + HTM_U_End (); + HTM_BUTTON_End (); + Frm_EndForm (); + HTM_TH_End (); + } + HTM_TR_End (); + + /***** Write list of buildings *****/ + for (NumBuilding = 0, RowEvenOdd = 1; + NumBuilding < Buildings.Num; + NumBuilding++, RowEvenOdd = 1 - RowEvenOdd) + { + HTM_TR_Begin (NULL); + + /* Short name */ + HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]); + HTM_Txt (Buildings.Lst[NumBuilding].ShrtName); + HTM_TD_End (); + + /* Full name */ + HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]); + HTM_Txt (Buildings.Lst[NumBuilding].FullName); + HTM_TD_End (); + + /* Location */ + HTM_TD_Begin ("class=\"DAT LM %s\"",Gbl.ColorRows[RowEvenOdd]); + HTM_Txt (Buildings.Lst[NumBuilding].Location); + HTM_TD_End (); + + HTM_TR_End (); + } + + /***** End table *****/ + HTM_TABLE_End (); + + /***** Button to create building *****/ + if (Bld_CheckIfICanCreateBuildings ()) + { + Frm_StartForm (ActEdiBld); + Btn_PutConfirmButton (Txt_New_building); + Frm_EndForm (); + } + + /***** End box *****/ + Box_BoxEnd (); + + /***** Free list of buildings *****/ + Bld_FreeListBuildings (&Buildings); + } + +/*****************************************************************************/ +/********* Get parameter with the type or order in list of buildings *********/ +/*****************************************************************************/ + +static Bld_Order_t Bld_GetParamBuildingOrder (void) + { + return (Bld_Order_t) Par_GetParToUnsignedLong ("Order", + 0, + Bld_NUM_ORDERS - 1, + (unsigned long) Bld_ORDER_DEFAULT); + } + +/*****************************************************************************/ +/********************* Check if I can create buildings ***********************/ +/*****************************************************************************/ + +static bool Bld_CheckIfICanCreateBuildings (void) + { + return (bool) (Gbl.Usrs.Me.Role.Logged >= Rol_CTR_ADM); + } + +/*****************************************************************************/ +/**************** Put contextual icons in list of buildings ******************/ +/*****************************************************************************/ + +static void Bld_PutIconsListingBuildings (__attribute__((unused)) void *Args) + { + /***** Put icon to edit buildings *****/ + if (Bld_CheckIfICanCreateBuildings ()) + Bld_PutIconToEditBuildings (); + } + +/*****************************************************************************/ +/******************** Put a link (form) to edit buildings ********************/ +/*****************************************************************************/ + +static void Bld_PutIconToEditBuildings (void) + { + Ico_PutContextualIconToEdit (ActEdiBld,NULL, + NULL,NULL); + } + +/*****************************************************************************/ +/************************* Put forms to edit buildings ***********************/ +/*****************************************************************************/ + +void Bld_EditBuildings (void) + { + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Edit buildings *****/ + Bld_EditBuildingsInternal (); + + /***** Building destructor *****/ + Bld_EditingBuildingDestructor (); + } + +static void Bld_EditBuildingsInternal (void) + { + extern const char *Hlp_CENTRE_Buildings_edit; + extern const char *Txt_Buildings; + struct Bld_Buildings Buildings; + + /***** Reset buildings context *****/ + Bld_ResetBuildings (&Buildings); + + /***** Get list of buildings *****/ + Bld_GetListBuildings (&Buildings,Bld_ALL_DATA); + + /***** Begin box *****/ + Box_BoxBegin (NULL,Txt_Buildings, + Bld_PutIconsEditingBuildings,NULL, + Hlp_CENTRE_Buildings_edit,Box_NOT_CLOSABLE); + + /***** Put a form to create a new building *****/ + Bld_PutFormToCreateBuilding (); + + /***** Forms to edit current buildings *****/ + if (Buildings.Num) + Bld_ListBuildingsForEdition (&Buildings); + + /***** End box *****/ + Box_BoxEnd (); + + /***** Free list of buildings *****/ + Bld_FreeListBuildings (&Buildings); + } + +/*****************************************************************************/ +/*************** Put contextual icons in edition of buildings ****************/ +/*****************************************************************************/ + +static void Bld_PutIconsEditingBuildings (__attribute__((unused)) void *Args) + { + /***** Put icon to view buildings *****/ + Bld_PutIconToViewBuildings (); + } + +/*****************************************************************************/ +/************************ Put icon to view buildings *************************/ +/*****************************************************************************/ + +void Bld_PutIconToViewBuildings (void) + { + extern const char *Txt_Buildings; + + Lay_PutContextualLinkOnlyIcon (ActSeeBld,NULL, + NULL,NULL, + "building.svg", + Txt_Buildings); + } + +/*****************************************************************************/ +/************************** List all the buildings ***************************/ +/*****************************************************************************/ + +void Bld_GetListBuildings (struct Bld_Buildings *Buildings, + Bld_WhichData_t WhichData) + { + static const char *OrderBySubQuery[Bld_NUM_ORDERS] = + { + [Bld_ORDER_BY_SHRT_NAME] = "ShortName", + [Bld_ORDER_BY_FULL_NAME] = "FullName", + [Bld_ORDER_BY_LOCATION ] = "Location,ShortName", + }; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned long NumRows; + unsigned NumBuilding; + struct Bld_Building *Building; + + /***** Get buildings from database *****/ + switch (WhichData) + { + case Bld_ALL_DATA: + NumRows = DB_QuerySELECT (&mysql_res,"can not get buildings", + "SELECT BldCod," + "ShortName," + "FullName," + "Location" + " FROM buildings" + " WHERE CtrCod=%ld" + " ORDER BY %s", + Gbl.Hierarchy.Ctr.CtrCod, + OrderBySubQuery[Buildings->SelectedOrder]); + break; + case Bld_ONLY_SHRT_NAME: + default: + NumRows = DB_QuerySELECT (&mysql_res,"can not get buildings", + "SELECT BldCod," + "ShortName" + " FROM buildings" + " WHERE CtrCod=%ld" + " ORDER BY ShortName", + Gbl.Hierarchy.Ctr.CtrCod); + break; + } + + /***** Count number of rows in result *****/ + if (NumRows) // Buildings found... + { + Buildings->Num = (unsigned) NumRows; + + /***** Create list with courses in centre *****/ + if ((Buildings->Lst = (struct Bld_Building *) + calloc (NumRows, + sizeof (struct Bld_Building))) == NULL) + Lay_NotEnoughMemoryExit (); + + /***** Get the buildings *****/ + for (NumBuilding = 0; + NumBuilding < Buildings->Num; + NumBuilding++) + { + Building = &Buildings->Lst[NumBuilding]; + + /* Get next building */ + row = mysql_fetch_row (mysql_res); + + /* Get building code (row[0]) */ + if ((Building->BldCod = Str_ConvertStrCodToLongCod (row[0])) < 0) + Lay_ShowErrorAndExit ("Wrong code of building."); + + /* Get the short name of the building (row[1]) */ + Str_Copy (Building->ShrtName,row[1], + Bld_MAX_BYTES_SHRT_NAME); + + if (WhichData == Bld_ALL_DATA) + { + /* Get the full name of the building (row[2]) */ + Str_Copy (Building->FullName,row[2], + Bld_MAX_BYTES_FULL_NAME); + + /* Get the full name of the building (row[3]) */ + Str_Copy (Building->Location,row[3], + Bld_MAX_BYTES_LOCATION); + } + } + } + else + Buildings->Num = 0; + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + } + +/*****************************************************************************/ +/*************************** Get building full name **************************/ +/*****************************************************************************/ + +void Bld_GetDataOfBuildingByCod (struct Bld_Building *Building) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned long NumRows; + + /***** Clear data *****/ + Building->ShrtName[0] = '\0'; + Building->FullName[0] = '\0'; + Building->Location[0] = '\0'; + + /***** Check if building code is correct *****/ + if (Building->BldCod > 0) + { + /***** Get data of a building from database *****/ + NumRows = DB_QuerySELECT (&mysql_res,"can not get data of a building", + "SELECT ShortName," // row[0] + "FullName," // row[1] + "Location" // row[2] + " FROM buildings" + " WHERE BldCod=%ld", + Building->BldCod); + + /***** Count number of rows in result *****/ + if (NumRows) // Building found... + { + /* Get row */ + row = mysql_fetch_row (mysql_res); + + /* Get the short name of the building (row[0]) */ + Str_Copy (Building->ShrtName,row[0], + Bld_MAX_BYTES_SHRT_NAME); + + /* Get the full name of the building (row[1]) */ + Str_Copy (Building->FullName,row[1], + Bld_MAX_BYTES_FULL_NAME); + + /* Get the location of the building (row[2]) */ + Str_Copy (Building->Location,row[2], + Bld_MAX_BYTES_LOCATION); + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + } + } + +/*****************************************************************************/ +/************************** Free list of buildings ***************************/ +/*****************************************************************************/ + +void Bld_FreeListBuildings (struct Bld_Buildings *Buildings) + { + if (Buildings->Lst) + { + /***** Free memory used by the list of buildings in institution *****/ + free (Buildings->Lst); + Buildings->Lst = NULL; + Buildings->Num = 0; + } + } + +/*****************************************************************************/ +/************************* List all the buildings ****************************/ +/*****************************************************************************/ + +static void Bld_ListBuildingsForEdition (const struct Bld_Buildings *Buildings) + { + unsigned NumBld; + struct Bld_Building *Building; + char *Anchor = NULL; + + /***** Write heading *****/ + HTM_TABLE_BeginWidePadding (2); + Bld_PutHeadBuildings (); + + /***** Write all the buildings *****/ + for (NumBld = 0; + NumBld < Buildings->Num; + NumBld++) + { + Building = &Buildings->Lst[NumBld]; + + /* Build anchor string */ + Frm_SetAnchorStr (Building->BldCod,&Anchor); + + HTM_TR_Begin (NULL); + + /* Put icon to remove building */ + HTM_TD_Begin ("class=\"BM\""); + Frm_StartForm (ActRemBld); + Bld_PutParamBldCod (Building->BldCod); + Ico_PutIconRemove (); + Frm_EndForm (); + HTM_TD_End (); + + /* Building code */ + HTM_TD_Begin ("class=\"DAT RM\""); + HTM_ARTICLE_Begin (Anchor); + HTM_Long (Building->BldCod); + HTM_ARTICLE_End (); + HTM_TD_End (); + + /* Building short name */ + HTM_TD_Begin ("class=\"LM\""); + Frm_StartFormAnchor (ActRenBldSho,Anchor); + Bld_PutParamBldCod (Building->BldCod); + HTM_INPUT_TEXT ("ShortName",Bld_MAX_CHARS_SHRT_NAME,Building->ShrtName,true, + "size=\"10\" class=\"INPUT_SHORT_NAME\""); + Frm_EndForm (); + HTM_TD_End (); + + /* Building full name */ + HTM_TD_Begin ("class=\"LM\""); + Frm_StartFormAnchor (ActRenBldFul,Anchor); + Bld_PutParamBldCod (Building->BldCod); + HTM_INPUT_TEXT ("FullName",Bld_MAX_CHARS_FULL_NAME,Building->FullName,true, + "size=\"20\" class=\"INPUT_FULL_NAME\""); + Frm_EndForm (); + HTM_TD_End (); + + /* Building location */ + HTM_TD_Begin ("class=\"LM\""); + Frm_StartFormAnchor (ActRenBldLoc,Anchor); + Bld_PutParamBldCod (Building->BldCod); + HTM_INPUT_TEXT ("Location",Bld_MAX_CHARS_LOCATION,Building->Location,true, + "size=\"15\" class=\"INPUT_FULL_NAME\""); + Frm_EndForm (); + HTM_TD_End (); + + HTM_TR_End (); + } + + /***** End table *****/ + HTM_TABLE_End (); + } + +/*****************************************************************************/ +/******************* Write parameter with code of building *******************/ +/*****************************************************************************/ + +static void Bld_PutParamBldCod (long BldCod) + { + Par_PutHiddenParamLong (NULL,"BldCod",BldCod); + } + +/*****************************************************************************/ +/******************** Get parameter with code of building ********************/ +/*****************************************************************************/ + +long Bld_GetParamBldCod (void) + { + /***** Get code of building *****/ + return Par_GetParToLong ("BldCod"); + } + +/*****************************************************************************/ +/****************************** Remove a building ****************************/ +/*****************************************************************************/ + +void Bld_RemoveBuilding (void) + { + extern const char *Txt_Building_X_removed; + + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Get building code *****/ + if ((Bld_EditingBuilding->BldCod = Bld_GetParamBldCod ()) == -1L) + Lay_ShowErrorAndExit ("Code of building is missing."); + + /***** Get data of the building from database *****/ + Bld_GetDataOfBuildingByCod (Bld_EditingBuilding); + + /***** Update rooms assigned to this building *****/ + /* TODO: Uncomment when rooms be associated to building + DB_QueryUPDATE ("can not update building in groups", + "UPDATE rooms SET BldCod=0" // 0 means another building + " WHERE BldCod=%ld", + Bld_EditingBuilding->BldCod); + */ + + /***** Remove building *****/ + DB_QueryDELETE ("can not remove a building", + "DELETE FROM buildings WHERE BldCod=%ld", + Bld_EditingBuilding->BldCod); + + /***** Create message to show the change made *****/ + Ale_CreateAlert (Ale_SUCCESS,NULL, + Txt_Building_X_removed, + Bld_EditingBuilding->FullName); + } + +/*****************************************************************************/ +/******************** Remove all buildings in a centre ***********************/ +/*****************************************************************************/ + +void Bld_RemoveAllBuildingsInCtr (long CtrCod) + { + /***** Remove all buildings in centre *****/ + DB_QueryDELETE ("can not remove buildings", + "DELETE FROM buildings" + " WHERE CtrCod=%ld", + CtrCod); + } + +/*****************************************************************************/ +/******************** Change the short name of a building ********************/ +/*****************************************************************************/ + +void Bld_RenameBuildingShort (void) + { + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Rename building *****/ + Bld_RenameBuilding (Cns_SHRT_NAME); + } + +/*****************************************************************************/ +/******************** Change the full name of a building *********************/ +/*****************************************************************************/ + +void Bld_RenameBuildingFull (void) + { + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Rename building *****/ + Bld_RenameBuilding (Cns_FULL_NAME); + } + +/*****************************************************************************/ +/*********************** Change the name of a building ***********************/ +/*****************************************************************************/ + +static void Bld_RenameBuilding (Cns_ShrtOrFullName_t ShrtOrFullName) + { + extern const char *Txt_The_building_X_already_exists; + extern const char *Txt_The_building_X_has_been_renamed_as_Y; + extern const char *Txt_The_name_of_the_building_X_has_not_changed; + const char *ParamName = NULL; // Initialized to avoid warning + const char *FieldName = NULL; // Initialized to avoid warning + unsigned MaxBytes = 0; // Initialized to avoid warning + char *CurrentClaName = NULL; // Initialized to avoid warning + char NewClaName[Bld_MAX_BYTES_FULL_NAME + 1]; + + switch (ShrtOrFullName) + { + case Cns_SHRT_NAME: + ParamName = "ShortName"; + FieldName = "ShortName"; + MaxBytes = Bld_MAX_BYTES_SHRT_NAME; + CurrentClaName = Bld_EditingBuilding->ShrtName; + break; + case Cns_FULL_NAME: + ParamName = "FullName"; + FieldName = "FullName"; + MaxBytes = Bld_MAX_BYTES_FULL_NAME; + CurrentClaName = Bld_EditingBuilding->FullName; + break; + } + + /***** Get parameters from form *****/ + /* Get the code of the building */ + if ((Bld_EditingBuilding->BldCod = Bld_GetParamBldCod ()) == -1L) + Lay_ShowErrorAndExit ("Code of building is missing."); + + /* Get the new name for the building */ + Par_GetParToText (ParamName,NewClaName,MaxBytes); + + /***** Get from the database the old names of the building *****/ + Bld_GetDataOfBuildingByCod (Bld_EditingBuilding); + + /***** Check if new name is empty *****/ + if (NewClaName[0]) + { + /***** Check if old and new names are the same + (this happens when return is pressed without changes) *****/ + if (strcmp (CurrentClaName,NewClaName)) // Different names + { + /***** If building was in database... *****/ + if (Bld_CheckIfBuildingNameExists (ParamName,NewClaName,Bld_EditingBuilding->BldCod)) + Ale_CreateAlert (Ale_WARNING,NULL, + Txt_The_building_X_already_exists, + NewClaName); + else + { + /* Update the table changing old name by new name */ + Bld_UpdateBuildingNameDB (Bld_EditingBuilding->BldCod,FieldName,NewClaName); + + /* Write message to show the change made */ + Ale_CreateAlert (Ale_SUCCESS,NULL, + Txt_The_building_X_has_been_renamed_as_Y, + CurrentClaName,NewClaName); + } + } + else // The same name + Ale_CreateAlert (Ale_INFO,NULL, + Txt_The_name_of_the_building_X_has_not_changed, + CurrentClaName); + } + else + Ale_CreateAlertYouCanNotLeaveFieldEmpty (); + + /***** Update building name *****/ + Str_Copy (CurrentClaName,NewClaName, + MaxBytes); + } + +/*****************************************************************************/ +/******************** Check if the name of building exists *******************/ +/*****************************************************************************/ + +static bool Bld_CheckIfBuildingNameExists (const char *FieldName,const char *Name,long BldCod) + { + /***** Get number of buildings with a name from database *****/ + return (DB_QueryCOUNT ("can not check if the name of a building" + " already existed", + "SELECT COUNT(*) FROM buildings" + " WHERE CtrCod=%ld" + " AND %s='%s' AND BldCod<>%ld", + Gbl.Hierarchy.Ctr.CtrCod, + FieldName,Name,BldCod) != 0); + } + +/*****************************************************************************/ +/****************** Update building name in table of buildings *******************/ +/*****************************************************************************/ + +static void Bld_UpdateBuildingNameDB (long BldCod,const char *FieldName,const char *NewBuildingName) + { + /***** Update building changing old name by new name */ + DB_QueryUPDATE ("can not update the name of a building", + "UPDATE buildings SET %s='%s' WHERE BldCod=%ld", + FieldName,NewBuildingName,BldCod); + } + +/*****************************************************************************/ +/******************** Change the location of a building **********************/ +/*****************************************************************************/ + +void Bld_ChangeBuildingLocation (void) + { + extern const char *Txt_The_location_of_the_building_X_has_changed_to_Y; + extern const char *Txt_The_location_of_the_building_X_has_not_changed; + char NewLocation[Bld_MAX_BYTES_FULL_NAME + 1]; + + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Get parameters from form *****/ + /* Get the code of the building */ + if ((Bld_EditingBuilding->BldCod = Bld_GetParamBldCod ()) == -1L) + Lay_ShowErrorAndExit ("Code of building is missing."); + + /* Get the new location for the building */ + Par_GetParToText ("Location",NewLocation,Bld_MAX_BYTES_LOCATION); + + /***** Get from the database the old location of the building *****/ + Bld_GetDataOfBuildingByCod (Bld_EditingBuilding); + + /***** Check if old and new locations are the same + (this happens when return is pressed without changes) *****/ + if (strcmp (Bld_EditingBuilding->Location,NewLocation)) // Different locations + { + /* Update the table changing old name by new name */ + Bld_UpdateBuildingNameDB (Bld_EditingBuilding->BldCod,"Location",NewLocation); + Str_Copy (Bld_EditingBuilding->Location,NewLocation, + Bld_MAX_BYTES_LOCATION); + + /* Write message to show the change made */ + Ale_CreateAlert (Ale_SUCCESS,NULL, + Txt_The_location_of_the_building_X_has_changed_to_Y, + Bld_EditingBuilding->FullName,NewLocation); + } + else // The same location + Ale_CreateAlert (Ale_INFO,NULL, + Txt_The_location_of_the_building_X_has_not_changed, + Bld_EditingBuilding->FullName); + } + +/*****************************************************************************/ +/******* Show alerts after changing a building and continue editing **********/ +/*****************************************************************************/ + +void Bld_ContEditAfterChgBuilding (void) + { + /***** Write message to show the change made *****/ + Ale_ShowAlerts (NULL); + + /***** Show the form again *****/ + Bld_EditBuildingsInternal (); + + /***** Building destructor *****/ + Bld_EditingBuildingDestructor (); + } + +/*****************************************************************************/ +/******************** Put a form to create a new building ********************/ +/*****************************************************************************/ + +static void Bld_PutFormToCreateBuilding (void) + { + extern const char *Txt_New_building; + extern const char *Txt_Create_building; + + /***** Begin form *****/ + Frm_StartForm (ActNewBld); + + /***** Begin box and table *****/ + Box_BoxTableBegin (NULL,Txt_New_building, + NULL,NULL, + NULL,Box_NOT_CLOSABLE,2); + + /***** Write heading *****/ + Bld_PutHeadBuildings (); + + HTM_TR_Begin (NULL); + + /***** Column to remove building, disabled here *****/ + HTM_TD_Begin ("class=\"BM\""); + HTM_TD_End (); + + /***** Building code *****/ + HTM_TD_Begin ("class=\"CODE\""); + HTM_TD_End (); + + /***** Building short name *****/ + HTM_TD_Begin ("class=\"LM\""); + HTM_INPUT_TEXT ("ShortName",Bld_MAX_CHARS_SHRT_NAME,Bld_EditingBuilding->ShrtName,false, + "size=\"10\" class=\"INPUT_SHORT_NAME\" required=\"required\""); + HTM_TD_End (); + + /***** Building full name *****/ + HTM_TD_Begin ("class=\"LM\""); + HTM_INPUT_TEXT ("FullName",Bld_MAX_CHARS_FULL_NAME,Bld_EditingBuilding->FullName,false, + "size=\"20\" class=\"INPUT_FULL_NAME\" required=\"required\""); + HTM_TD_End (); + + /***** Building location *****/ + HTM_TD_Begin ("class=\"LM\""); + HTM_INPUT_TEXT ("Location",Bld_MAX_CHARS_LOCATION,Bld_EditingBuilding->Location,false, + "size=\"15\" class=\"INPUT_FULL_NAME\""); + HTM_TD_End (); + + HTM_TR_End (); + + /***** End table, send button and end box *****/ + Box_BoxTableWithButtonEnd (Btn_CREATE_BUTTON,Txt_Create_building); + + /***** End form *****/ + Frm_EndForm (); + } + +/*****************************************************************************/ +/****************** Write header with fields of a building *******************/ +/*****************************************************************************/ + +static void Bld_PutHeadBuildings (void) + { + extern const char *Txt_Code; + extern const char *Txt_Short_name; + extern const char *Txt_Full_name; + extern const char *Txt_Location; + + HTM_TR_Begin (NULL); + + HTM_TH (1,1,"BM",NULL); + HTM_TH (1,1,"RM",Txt_Code); + HTM_TH (1,1,"LM",Txt_Short_name); + HTM_TH (1,1,"LM",Txt_Full_name); + HTM_TH (1,1,"LM",Txt_Location); + + HTM_TR_End (); + } + +/*****************************************************************************/ +/***************** Receive form to create a new building *********************/ +/*****************************************************************************/ + +void Bld_RecFormNewBuilding (void) + { + extern const char *Txt_The_building_X_already_exists; + extern const char *Txt_Created_new_building_X; + extern const char *Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_building; + + /***** Building constructor *****/ + Bld_EditingBuildingConstructor (); + + /***** Get parameters from form *****/ + /* Get building short name */ + Par_GetParToText ("ShortName",Bld_EditingBuilding->ShrtName,Bld_MAX_BYTES_SHRT_NAME); + + /* Get building full name */ + Par_GetParToText ("FullName",Bld_EditingBuilding->FullName,Bld_MAX_BYTES_FULL_NAME); + + /* Get building location */ + Par_GetParToText ("Location",Bld_EditingBuilding->Location,Bld_MAX_BYTES_LOCATION); + + if (Bld_EditingBuilding->ShrtName[0] && + Bld_EditingBuilding->FullName[0]) // If there's a building name + { + /***** If name of building was in database... *****/ + if (Bld_CheckIfBuildingNameExists ("ShortName",Bld_EditingBuilding->ShrtName,-1L)) + Ale_CreateAlert (Ale_WARNING,NULL, + Txt_The_building_X_already_exists, + Bld_EditingBuilding->ShrtName); + else if (Bld_CheckIfBuildingNameExists ("FullName",Bld_EditingBuilding->FullName,-1L)) + Ale_CreateAlert (Ale_WARNING,NULL, + Txt_The_building_X_already_exists, + Bld_EditingBuilding->FullName); + else // Add new building to database + { + Bld_CreateBuilding (Bld_EditingBuilding); + Ale_CreateAlert (Ale_SUCCESS,NULL, + Txt_Created_new_building_X, + Bld_EditingBuilding->FullName); + } + } + else // If there is not a building name + Ale_CreateAlert (Ale_WARNING,NULL, + Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_building); + } + +/*****************************************************************************/ +/************************** Create a new building ****************************/ +/*****************************************************************************/ + +static void Bld_CreateBuilding (struct Bld_Building *Building) + { + /***** Create a new building *****/ + DB_QueryINSERT ("can not create building", + "INSERT INTO buildings" + " (CtrCod,ShortName,FullName,Location)" + " VALUES" + " (%ld,'%s','%s','%s')", + Gbl.Hierarchy.Ctr.CtrCod, + Building->ShrtName,Building->FullName,Building->Location); + } + +/*****************************************************************************/ +/************************ Building constructor/destructor ********************/ +/*****************************************************************************/ + +static void Bld_EditingBuildingConstructor (void) + { + /***** Pointer must be NULL *****/ + if (Bld_EditingBuilding != NULL) + Lay_ShowErrorAndExit ("Error initializing building."); + + /***** Allocate memory for building *****/ + if ((Bld_EditingBuilding = (struct Bld_Building *) malloc (sizeof (struct Bld_Building))) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for building."); + + /***** Reset building *****/ + Bld_EditingBuilding->BldCod = -1L; + Bld_EditingBuilding->InsCod = -1L; + Bld_EditingBuilding->ShrtName[0] = '\0'; + Bld_EditingBuilding->FullName[0] = '\0'; + Bld_EditingBuilding->Location[0] = '\0'; + } + +static void Bld_EditingBuildingDestructor (void) + { + /***** Free memory used for building *****/ + if (Bld_EditingBuilding != NULL) + { + free (Bld_EditingBuilding); + Bld_EditingBuilding = NULL; + } + } diff --git a/swad_building.h b/swad_building.h new file mode 100644 index 00000000..754d0b36 --- /dev/null +++ b/swad_building.h @@ -0,0 +1,104 @@ +// swad_building.h: buildings in a centre + +#ifndef _SWAD_BLD +#define _SWAD_BLD +/* + SWAD (Shared Workspace At a Distance in Spanish), + 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-2020 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 "swad_string.h" + +/*****************************************************************************/ +/************************** Public types and constants ***********************/ +/*****************************************************************************/ + +#define Bld_MAX_CHARS_SHRT_NAME (32 - 1) // 31 +#define Bld_MAX_BYTES_SHRT_NAME ((Bld_MAX_CHARS_SHRT_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 511 + +#define Bld_MAX_CHARS_FULL_NAME (128 - 1) // 127 +#define Bld_MAX_BYTES_FULL_NAME ((Bld_MAX_CHARS_FULL_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047 + +#define Bld_MAX_CHARS_LOCATION (128 - 1) // 127 +#define Bld_MAX_BYTES_LOCATION ((Bld_MAX_CHARS_LOCATION + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047 + +struct Bld_Building + { + long BldCod; + long InsCod; + char ShrtName[Bld_MAX_BYTES_SHRT_NAME + 1]; + char FullName[Bld_MAX_BYTES_FULL_NAME + 1]; + char Location[Bld_MAX_BYTES_LOCATION + 1]; // Examples: Campus North, City centre + }; + +#define Bld_NUM_ORDERS 3 +typedef enum + { + Bld_ORDER_BY_SHRT_NAME = 0, + Bld_ORDER_BY_FULL_NAME = 1, + Bld_ORDER_BY_LOCATION = 2, + } Bld_Order_t; +#define Bld_ORDER_DEFAULT Bld_ORDER_BY_SHRT_NAME + +/***** Get all data or only short name *****/ +typedef enum + { + Bld_ALL_DATA, + Bld_ONLY_SHRT_NAME, + } Bld_WhichData_t; + +struct Bld_Buildings + { + unsigned Num; // Number of buildings + struct Bld_Building *Lst; // List of buildings + Bld_Order_t SelectedOrder; + }; + +/*****************************************************************************/ +/***************************** Public prototypes *****************************/ +/*****************************************************************************/ + +void Bld_ResetBuildings (struct Bld_Buildings *Buildings); + +void Bld_SeeBuildings (void); +void Bld_EditBuildings (void); +void Bld_PutIconToViewBuildings (void); +void Bld_GetListBuildings (struct Bld_Buildings *Buildings, + Bld_WhichData_t WhichData); +void Bld_FreeListBuildings (struct Bld_Buildings *Buildings); + +void Bld_GetListBuildingsInThisCtr (void); + +void Bld_GetDataOfBuildingByCod (struct Bld_Building *Roo); +long Bld_GetParamBldCod (void); + +void Bld_RemoveBuilding (void); +void Bld_RemoveAllBuildingsInCtr (long CtrCod); +void Bld_RenameBuildingShort (void); +void Bld_RenameBuildingFull (void); +void Bld_ChangeBuildingLocation (void); +void Bld_ContEditAfterChgBuilding (void); + +void Bld_RecFormNewBuilding (void); + +#endif