// swad_project.c: projects (final degree projects, thesis) /* 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 PATH_MAX #include // For NULL #include // For asprintf #include // For calloc #include // For string functions #include "swad_box.h" #include "swad_database.h" #include "swad_form.h" #include "swad_global.h" #include "swad_HTML.h" #include "swad_ID.h" #include "swad_notification.h" #include "swad_pagination.h" #include "swad_parameter.h" #include "swad_photo.h" #include "swad_project.h" #include "swad_role.h" #include "swad_setting.h" #include "swad_string.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /************************* Private constants and types ***********************/ /*****************************************************************************/ /***** Parameters used to filter listing of projects *****/ #define Prj_PARAM_PRE_NON_NAME "PreNon" #define Prj_PARAM_HID_VIS_NAME "HidVis" #define Prj_PARAM_FAULTIN_NAME "Faulti" /***** Type of view when writing one project *****/ typedef enum { Prj_LIST_PROJECTS, Prj_FILE_BROWSER_PROJECT, Prj_PRINT_ONE_PROJECT, Prj_EDIT_ONE_PROJECT, } Prj_ProjectView_t; /***** User roles are shown in this order *****/ static const Prj_RoleInProject_t Prj_RolesToShow[] = { Prj_ROLE_TUT, // Tutor Prj_ROLE_STD, // Student Prj_ROLE_EVL, // Evaluator }; static const unsigned Brw_NUM_ROLES_TO_SHOW = sizeof (Prj_RolesToShow) / sizeof (Prj_RolesToShow[0]); /***** Enum field in database for types of proposal *****/ static const char *Prj_Proposal_DB[Prj_NUM_PROPOSAL_TYPES] = { "new", // Prj_PROPOSAL_NEW "modified", // Prj_PROPOSAL_MODIFIED "unmodified", // Prj_PROPOSAL_UNMODIFIED }; /***** Assigned/non-assigned project *****/ static const char *AssignedNonassigImage[Prj_NUM_ASSIGNED_NONASSIG] = { "user.svg", // Prj_ASSIGNED "user-slash.svg", // Prj_NONASSIG }; /***** Locked/unlocked project edition *****/ static const char *Prj_LockIcons[Prj_NUM_LOCKED_UNLOCKED] = { "lock.svg", // Prj_LOCKED "unlock.svg", // Prj_UNLOCKED }; static const Act_Action_t Prj_LockActions[Prj_NUM_LOCKED_UNLOCKED] = { ActUnlPrj, // Prj_LOCKED ActLckPrj, // Prj_UNLOCKED }; /***** List of users to select one or more members to be added to a project *****/ struct SelectedUsrs Prj_MembersToAdd = { .List = { NULL, // Rol_UNK NULL, // Rol_GST NULL, // Rol_USR NULL, // Rol_STD NULL, // Rol_NET NULL, // Rol_TCH NULL, // Rol_DEG_ADM NULL, // Rol_CTR_ADM NULL, // Rol_INS_ADM NULL, // Rol_SYS_ADM }, .Filled = false, .ParamSuffix = "Member", .Option = Usr_OPTION_UNKNOWN, }; /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ struct Prj_Faults { bool WrongTitle; bool WrongDescription; bool WrongNumStds; bool WrongAssigned; }; /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ static void Prj_ReqUsrsToSelect (void); static void Prj_GetSelectedUsrsAndShowTheirPrjs (void); static void Prj_ShowProjects (void); static void Prj_ShowPrjsInCurrentPage (void); static void Prj_ShowFormToFilterByMy_All (void); static void Prj_ShowFormToFilterByAssign (void); static void Prj_ShowFormToFilterByHidden (void); static void Prj_ShowFormToFilterByWarning (void); static void Prj_ShowFormToFilterByDpt (void); static void Prj_PutCurrentParams (void); static void Prj_PutHiddenParamAssign (unsigned Assign); static void Prj_PutHiddenParamHidden (unsigned Hidden); static void Prj_PutHiddenParamFaulti (unsigned Faulti); static void Prj_PutHiddenParamDptCod (long DptCod); static void Prj_GetHiddenParamPreNon (void); static void Prj_GetHiddenParamHidVis (void); static void Prj_GetHiddenParamFaulti (void); static void Prj_GetHiddenParamDptCod (void); static void Prj_GetParams (void); static void Prj_GetParamWho (void); static void Prj_ShowProjectsHead (Prj_ProjectView_t ProjectView); static void Prj_ShowTableAllProjectsHead (void); static bool Prj_CheckIfICanCreateProjects (void); static void Prj_PutIconsListProjects (void); static void Prj_PutIconToCreateNewPrj (void); static void Prj_PutButtonToCreateNewPrj (void); static void Prj_PutIconToShowAllData (void); static void Prj_ShowOneProject (unsigned NumIndex,struct Project *Prj, Prj_ProjectView_t ProjectView); static bool Prj_CheckIfPrjIsFaulty (long PrjCod,struct Prj_Faults *Faults); static void Prj_PutWarningIcon (void); static void Prj_PutIconToToggleProject (unsigned UniqueId, const char *Icon,const char *Text); static void Prj_ShowTableAllProjectsOneRow (struct Project *Prj); static void Prj_ShowOneProjectDepartment (const struct Project *Prj, Prj_ProjectView_t ProjectView); static void Prj_ShowTableAllProjectsDepartment (const struct Project *Prj); static void Prj_ShowOneProjectTxtField (struct Project *Prj, Prj_ProjectView_t ProjectView, const char *id,unsigned UniqueId, const char *Label,char *TxtField, bool Warning); static void Prj_ShowTableAllProjectsTxtField (struct Project *Prj, char *TxtField); static void Prj_ShowOneProjectURL (const struct Project *Prj, Prj_ProjectView_t ProjectView, const char *id,unsigned UniqueId); static void Prj_ShowTableAllProjectsURL (const struct Project *Prj); static void Prj_ShowOneProjectMembers (struct Project *Prj, Prj_ProjectView_t ProjectView); static void Prj_ShowOneProjectMembersWithARole (const struct Project *Prj, Prj_ProjectView_t ProjectView, Prj_RoleInProject_t RoleInProject); static void Prj_ShowTableAllProjectsMembersWithARole (const struct Project *Prj, Prj_RoleInProject_t RoleInProject); static unsigned Prj_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject); static unsigned Prj_GetUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject, MYSQL_RES **mysql_res); static Prj_RoleInProject_t Prj_ConvertUnsignedStrToRoleInProject (const char *UnsignedStr); static void Prj_ReqAddUsrs (Prj_RoleInProject_t RoleInProject); static void Prj_AddStds (void); static void Prj_AddTuts (void); static void Prj_AddEvls (void); static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject); static void Prj_ReqRemUsrFromPrj (Prj_RoleInProject_t RoleInProject); static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInProject); static void Prj_GetParamPrjOrder (void); static void Prj_PutFormsToRemEditOnePrj (const struct Project *Prj, const char *Anchor, bool ICanViewProjectFiles); static bool Prj_CheckIfICanEditProject (const struct Project *Prj); static void Prj_GetListProjects (void); static void Prj_ResetProject (struct Project *Prj); static void Prj_RequestCreatOrEditPrj (long PrjCod); static void Prj_PutFormProject (struct Project *Prj,bool ItsANewProject); static void Prj_EditOneProjectTxtArea (const char *Id, const char *Label,char *TxtField, unsigned NumRows,bool Required); static void Prj_CreateProject (struct Project *Prj); static void Prj_UpdateProject (struct Project *Prj); static bool Prj_CheckIfICanConfigAllProjects (void); static void Prj_GetConfigPrjFromDB (void); static void Prj_GetConfigFromRow (MYSQL_ROW row); static bool Prj_GetEditableFromForm (void); static void Prj_PutIconsToLockUnlockAllProjects (void); static void Prj_FormLockUnlock (const struct Project *Prj); static void Prj_PutIconOffLockedUnlocked (const struct Project *Prj); static void Prj_LockProjectEditionInDB (long PrjCod); static void Prj_UnlockProjectEditionInDB (long PrjCod); /*****************************************************************************/ /**************************** List users to select ***************************/ /*****************************************************************************/ void Prj_ListUsrsToSelect (void) { /***** Get parameters *****/ Prj_GetParams (); /***** Show list of users to select some of them *****/ Prj_ReqUsrsToSelect (); } static void Prj_ReqUsrsToSelect (void) { extern const char *Hlp_ASSESSMENT_Projects; extern const char *Txt_Projects; extern const char *Txt_View_projects; /***** List users to select some of them *****/ Usr_PutFormToSelectUsrsToGoToAct (&Gbl.Usrs.Selected, ActSeePrj,Prj_PutCurrentParams, Txt_Projects, Hlp_ASSESSMENT_Projects, Txt_View_projects); } /*****************************************************************************/ /******************* Get parameters and show projects ************************/ /*****************************************************************************/ void Prj_SeeProjects (void) { /***** Get parameters *****/ Prj_GetParams (); /***** Show projects *****/ Prj_ShowProjects (); } /*****************************************************************************/ /******************************* Show projects *******************************/ /*****************************************************************************/ static void Prj_ShowProjects (void) { switch (Gbl.Prjs.Filter.Who) { case Usr_WHO_ME: case Usr_WHO_ALL: /* Show my projects / all projects */ Prj_ShowPrjsInCurrentPage (); break; case Usr_WHO_SELECTED: /* Get selected users and show their projects */ Prj_GetSelectedUsrsAndShowTheirPrjs (); break; default: break; } } /*****************************************************************************/ /****** Get and check list of selected users, and show users' projects *******/ /*****************************************************************************/ static void Prj_GetSelectedUsrsAndShowTheirPrjs (void) { Usr_GetSelectedUsrsAndGoToAct (&Gbl.Usrs.Selected, Prj_ShowPrjsInCurrentPage, // when user(s) selected Prj_ReqUsrsToSelect); // when no user selected } /*****************************************************************************/ /********************** Show selected projects in a table ********************/ /*****************************************************************************/ void Prj_ShowTableSelectedPrjs (void) { extern const char *Txt_No_projects; unsigned NumPrj; struct Project Prj; /***** Get parameters *****/ Prj_GetParams (); /***** Get list of projects *****/ Prj_GetListProjects (); if (Gbl.Prjs.Num) { /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Table head *****/ HTM_TABLE_BeginWidePadding (2); Prj_ShowTableAllProjectsHead (); /***** Write all the projects *****/ for (NumPrj = 0; NumPrj < Gbl.Prjs.Num; NumPrj++) { Prj.PrjCod = Gbl.Prjs.LstPrjCods[NumPrj]; Prj_ShowTableAllProjectsOneRow (&Prj); } /***** End table *****/ HTM_TABLE_End (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); } else // No projects created Ale_ShowAlert (Ale_INFO,Txt_No_projects); /***** Free list of projects *****/ Prj_FreeListProjects (); } /*****************************************************************************/ /****************** Show the projects in current page ************************/ /*****************************************************************************/ static void Prj_ShowPrjsInCurrentPage (void) { extern const char *Hlp_ASSESSMENT_Projects; extern const char *Txt_Projects; extern const char *Txt_No_projects; struct Pagination Pagination; unsigned NumPrj; unsigned NumIndex; struct Project Prj; /***** Get list of projects *****/ Prj_GetListProjects (); /***** Compute variables related to pagination *****/ Pagination.NumItems = Gbl.Prjs.Num; Pagination.CurrentPage = (int) Gbl.Prjs.CurrentPage; Pag_CalculatePagination (&Pagination); Gbl.Prjs.CurrentPage = (unsigned) Pagination.CurrentPage; /***** Begin box *****/ Box_BoxBegin ("100%",Txt_Projects,Prj_PutIconsListProjects, Hlp_ASSESSMENT_Projects,Box_NOT_CLOSABLE); /***** Put forms to choice which projects to show *****/ /* 1st. row */ Set_StartSettingsHead (); Prj_ShowFormToFilterByMy_All (); Prj_ShowFormToFilterByAssign (); switch (Gbl.Usrs.Me.Role.Logged) { case Rol_NET: case Rol_TCH: case Rol_SYS_ADM: Prj_ShowFormToFilterByHidden (); break; default: // Students will see only visible projects break; } Prj_ShowFormToFilterByWarning (); Set_EndSettingsHead (); /* 2nd. row */ Prj_ShowFormToFilterByDpt (); if (Gbl.Prjs.Num) { /***** Write links to pages *****/ if (Pagination.MoreThanOnePage) Pag_WriteLinksToPagesCentered (Pag_PROJECTS, 0, &Pagination); /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Table head *****/ HTM_TABLE_BeginWideMarginPadding (2); Prj_ShowProjectsHead (Prj_LIST_PROJECTS); /***** Write all the projects *****/ for (NumPrj = Pagination.FirstItemVisible; NumPrj <= Pagination.LastItemVisible; NumPrj++) { /* Get project data */ Prj.PrjCod = Gbl.Prjs.LstPrjCods[NumPrj - 1]; Prj_GetDataOfProjectByCod (&Prj); /* Number of index */ switch (Gbl.Prjs.SelectedOrder) { case Prj_ORDER_START_TIME: case Prj_ORDER_END_TIME: // NumPrj: 1, 2, 3 ==> NumIndex = 3, 2, 1 NumIndex = Gbl.Prjs.Num + 1 - NumPrj; break; default: // NumPrj: 1, 2, 3 ==> NumIndex = 1, 2, 3 NumIndex = NumPrj; break; } /* Show project */ Prj_ShowOneProject (NumIndex,&Prj,Prj_LIST_PROJECTS); } /***** End table *****/ HTM_TABLE_End (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Write again links to pages *****/ if (Pagination.MoreThanOnePage) Pag_WriteLinksToPagesCentered (Pag_PROJECTS, 0, &Pagination); } else // No projects created Ale_ShowAlert (Ale_INFO,Txt_No_projects); /***** Button to create a new project *****/ if (Prj_CheckIfICanCreateProjects ()) Prj_PutButtonToCreateNewPrj (); /***** End box *****/ Box_BoxEnd (); /***** Free list of projects *****/ Prj_FreeListProjects (); } /*****************************************************************************/ /*** Show form to choice whether to show only my projects or all projects ****/ /*****************************************************************************/ static void Prj_ShowFormToFilterByMy_All (void) { struct Prj_Filter Filter; Usr_Who_t Who; unsigned Mask = 1 << Usr_WHO_ME | 1 << Usr_WHO_SELECTED | 1 << Usr_WHO_ALL; Set_StartOneSettingSelector (); for (Who = (Usr_Who_t) 1; Who <= (Usr_Who_t) (Usr_NUM_WHO - 1); Who++) if (Mask & (1 << Who)) { HTM_DIV_Begin ("class=\"%s\"", (Gbl.Prjs.Filter.Who == Who) ? "PREF_ON" : "PREF_OFF"); Frm_StartForm (Who == Usr_WHO_SELECTED ? ActReqUsrPrj : ActSeePrj); Filter.Who = Who; Filter.Assign = Gbl.Prjs.Filter.Assign; Filter.Hidden = Gbl.Prjs.Filter.Hidden; Filter.Faulti = Gbl.Prjs.Filter.Faulti; Filter.DptCod = Gbl.Prjs.Filter.DptCod; Prj_PutParams (&Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, -1L); Usr_PutWhoIcon (Who); Frm_EndForm (); HTM_DIV_End (); } Set_EndOneSettingSelector (); } /*****************************************************************************/ /*********** Show form to select assigned / non-assigned projects ************/ /*****************************************************************************/ static void Prj_ShowFormToFilterByAssign (void) { extern const char *Txt_PROJECT_ASSIGNED_NONASSIGNED_PLURAL[Prj_NUM_ASSIGNED_NONASSIG]; struct Prj_Filter Filter; Prj_AssignedNonassig_t Assign; Set_StartOneSettingSelector (); for (Assign = (Prj_AssignedNonassig_t) 0; Assign <= (Prj_AssignedNonassig_t) (Prj_NUM_ASSIGNED_NONASSIG - 1); Assign++) { HTM_DIV_Begin ("class=\"%s\"", (Gbl.Prjs.Filter.Assign & (1 << Assign)) ? "PREF_ON" : "PREF_OFF"); Frm_StartForm (ActSeePrj); Filter.Who = Gbl.Prjs.Filter.Who; Filter.Assign = Gbl.Prjs.Filter.Assign ^ (1 << Assign); // Toggle Filter.Hidden = Gbl.Prjs.Filter.Hidden; Filter.Faulti = Gbl.Prjs.Filter.Faulti; Filter.DptCod = Gbl.Prjs.Filter.DptCod; Prj_PutParams (&Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, -1L); Ico_PutSettingIconLink (AssignedNonassigImage[Assign], Txt_PROJECT_ASSIGNED_NONASSIGNED_PLURAL[Assign]); Frm_EndForm (); HTM_DIV_End (); } Set_EndOneSettingSelector (); } /*****************************************************************************/ /************* Show form to select hidden / visible projects *****************/ /*****************************************************************************/ static void Prj_ShowFormToFilterByHidden (void) { extern const char *Txt_PROJECT_HIDDEN_VISIBL_PROJECTS[Prj_NUM_HIDDEN_VISIBL]; struct Prj_Filter Filter; Prj_HiddenVisibl_t HidVis; static const char *HiddenVisiblIcon[Prj_NUM_HIDDEN_VISIBL] = { "eye-slash.svg", // Prj_HIDDEN "eye.svg", // Prj_VISIBL }; Set_StartOneSettingSelector (); for (HidVis = (Prj_HiddenVisibl_t) 0; HidVis <= (Prj_HiddenVisibl_t) (Prj_NUM_HIDDEN_VISIBL - 1); HidVis++) { HTM_DIV_Begin ("class=\"%s\"", (Gbl.Prjs.Filter.Hidden & (1 << HidVis)) ? "PREF_ON" : "PREF_OFF"); Frm_StartForm (ActSeePrj); Filter.Who = Gbl.Prjs.Filter.Who; Filter.Assign = Gbl.Prjs.Filter.Assign; Filter.Hidden = Gbl.Prjs.Filter.Hidden ^ (1 << HidVis); // Toggle Filter.Faulti = Gbl.Prjs.Filter.Faulti; Filter.DptCod = Gbl.Prjs.Filter.DptCod; Prj_PutParams (&Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, -1L); Ico_PutSettingIconLink (HiddenVisiblIcon[HidVis], Txt_PROJECT_HIDDEN_VISIBL_PROJECTS[HidVis]); Frm_EndForm (); HTM_DIV_End (); } Set_EndOneSettingSelector (); } /*****************************************************************************/ /************** Show form to select faulty/faultless projects ****************/ /*****************************************************************************/ static void Prj_ShowFormToFilterByWarning (void) { extern const char *Txt_PROJECT_FAULTY_FAULTLESS_PROJECTS[Prj_NUM_FAULTINESS]; struct Prj_Filter Filter; Prj_Faultiness_t Faultiness; static const char *FaultinessIcon[Prj_NUM_FAULTINESS] = { "exclamation-triangle.svg", // Prj_FAULTY "check-circle.svg", // Prj_FAULTLESS }; Set_StartOneSettingSelector (); for (Faultiness = (Prj_Faultiness_t) 0; Faultiness <= (Prj_Faultiness_t) (Prj_NUM_FAULTINESS - 1); Faultiness++) { HTM_DIV_Begin ("class=\"%s\"", (Gbl.Prjs.Filter.Faulti & (1 << Faultiness)) ? "PREF_ON" : "PREF_OFF"); Frm_StartForm (ActSeePrj); Filter.Who = Gbl.Prjs.Filter.Who; Filter.Assign = Gbl.Prjs.Filter.Assign; Filter.Hidden = Gbl.Prjs.Filter.Hidden; Filter.Faulti = Gbl.Prjs.Filter.Faulti ^ (1 << Faultiness); // Toggle Filter.DptCod = Gbl.Prjs.Filter.DptCod; Prj_PutParams (&Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, -1L); Ico_PutSettingIconLink (FaultinessIcon[Faultiness], Txt_PROJECT_FAULTY_FAULTLESS_PROJECTS[Faultiness]); Frm_EndForm (); HTM_DIV_End (); } Set_EndOneSettingSelector (); } /*****************************************************************************/ /*************** Show form to filter projects by department ******************/ /*****************************************************************************/ static void Prj_ShowFormToFilterByDpt (void) { extern const char *Txt_Any_department; struct Prj_Filter Filter; /***** Begin form *****/ HTM_DIV_Begin (NULL); Frm_StartForm (ActSeePrj); Filter.Who = Gbl.Prjs.Filter.Who; Filter.Assign = Gbl.Prjs.Filter.Assign; Filter.Hidden = Gbl.Prjs.Filter.Hidden; Filter.Faulti = Gbl.Prjs.Filter.Faulti; Filter.DptCod = Prj_FILTER_DPT_DEFAULT; // Do not put department parameter here Prj_PutParams (&Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, -1L); /***** Write selector with departments *****/ Dpt_WriteSelectorDepartment (Gbl.Hierarchy.Ins.InsCod, // Departments in current insitution Gbl.Prjs.Filter.DptCod, // Selected department "PRJ_INPUT", // Selector class -1L, // First option Txt_Any_department, // Text when no department selected true); // Submit on change /***** End form *****/ Frm_EndForm (); HTM_DIV_End (); } /*****************************************************************************/ /********************** Put parameters used in projects **********************/ /*****************************************************************************/ static void Prj_PutCurrentParams (void) { Prj_PutParams (&Gbl.Prjs.Filter, Gbl.Prjs.SelectedOrder, Gbl.Prjs.CurrentPage, Gbl.Prjs.PrjCod); } /* The following function is called when one or more parameters must be passed explicitely. Each parameter is passed only if its value is distinct to default. */ void Prj_PutParams (struct Prj_Filter *Filter, Prj_Order_t Order, unsigned NumPage, long PrjCod) { /***** Put filter parameters (which projects to show) *****/ if (Filter->Who != Prj_FILTER_WHO_DEFAULT) Usr_PutHiddenParamWho (Filter->Who); if (Filter->Assign != ((unsigned) Prj_FILTER_ASSIGNED_DEFAULT | (unsigned) Prj_FILTER_NONASSIG_DEFAULT)) Prj_PutHiddenParamAssign (Filter->Assign); if (Filter->Hidden != ((unsigned) Prj_FILTER_HIDDEN_DEFAULT | (unsigned) Prj_FILTER_VISIBL_DEFAULT)) Prj_PutHiddenParamHidden (Filter->Hidden); if (Filter->Faulti != ((unsigned) Prj_FILTER_FAULTY_DEFAULT | (unsigned) Prj_FILTER_FAULTLESS_DEFAULT)) Prj_PutHiddenParamFaulti (Filter->Faulti); if (Filter->DptCod != Prj_FILTER_DPT_DEFAULT) Prj_PutHiddenParamDptCod (Filter->DptCod); /***** Put order field *****/ if (Order != Prj_ORDER_DEFAULT) Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Order); /***** Put number of page *****/ if (NumPage > 1) Pag_PutHiddenParamPagNum (Pag_PROJECTS,NumPage); /***** Put selected project code *****/ if (PrjCod > 0) Prj_PutParamPrjCod (PrjCod); /***** Put another user's code *****/ if (Gbl.Usrs.Other.UsrDat.UsrCod > 0) Usr_PutParamOtherUsrCodEncrypted (); /***** Put selected users' codes *****/ if (Filter->Who == Usr_WHO_SELECTED) Usr_PutHiddenParSelectedUsrsCods (&Gbl.Usrs.Selected); } /*****************************************************************************/ /*********************** Put hidden params for projects **********************/ /*****************************************************************************/ static void Prj_PutHiddenParamAssign (unsigned Assign) { Par_PutHiddenParamUnsigned (NULL,Prj_PARAM_PRE_NON_NAME,Assign); } static void Prj_PutHiddenParamHidden (unsigned Hidden) { Par_PutHiddenParamUnsigned (NULL,Prj_PARAM_HID_VIS_NAME,Hidden); } static void Prj_PutHiddenParamFaulti (unsigned Faulti) { Par_PutHiddenParamUnsigned (NULL,Prj_PARAM_FAULTIN_NAME,Faulti); } static void Prj_PutHiddenParamDptCod (long DptCod) { Par_PutHiddenParamUnsigned (NULL,Dpt_PARAM_DPT_COD_NAME,DptCod); } /*****************************************************************************/ /*********************** Get hidden params for projects **********************/ /*****************************************************************************/ static void Prj_GetHiddenParamPreNon (void) { Gbl.Prjs.Filter.Assign = (unsigned) Par_GetParToUnsignedLong (Prj_PARAM_PRE_NON_NAME, 0, (1 << Prj_ASSIGNED) | (1 << Prj_NONASSIG), (unsigned) Prj_FILTER_ASSIGNED_DEFAULT | (unsigned) Prj_FILTER_NONASSIG_DEFAULT); } static void Prj_GetHiddenParamHidVis (void) { switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: // Students can view only visible projects Gbl.Prjs.Filter.Hidden = (1 << Prj_VISIBL); // Only visible projects break; case Rol_NET: case Rol_TCH: case Rol_SYS_ADM: Gbl.Prjs.Filter.Hidden = (unsigned) Par_GetParToUnsignedLong (Prj_PARAM_HID_VIS_NAME, 0, (1 << Prj_HIDDEN) | (1 << Prj_VISIBL), (unsigned) Prj_FILTER_HIDDEN_DEFAULT | (unsigned) Prj_FILTER_VISIBL_DEFAULT); break; default: Rol_WrongRoleExit (); break; } } static void Prj_GetHiddenParamFaulti (void) { Gbl.Prjs.Filter.Faulti = (unsigned) Par_GetParToUnsignedLong (Prj_PARAM_FAULTIN_NAME, 0, (1 << Prj_FAULTY) | (1 << Prj_FAULTLESS), (unsigned) Prj_FILTER_FAULTY_DEFAULT | (unsigned) Prj_FILTER_FAULTLESS_DEFAULT); } static void Prj_GetHiddenParamDptCod (void) { Gbl.Prjs.Filter.DptCod = Par_GetParToLong (Dpt_PARAM_DPT_COD_NAME); } /*****************************************************************************/ /***************** Get generic parameters to list projects *******************/ /*****************************************************************************/ static void Prj_GetParams (void) { /***** Get filter (which projects to show) *****/ Prj_GetParamWho (); Prj_GetHiddenParamPreNon (); Prj_GetHiddenParamHidVis (); Prj_GetHiddenParamFaulti (); Prj_GetHiddenParamDptCod (); /***** Get order and page *****/ Prj_GetParamPrjOrder (); Gbl.Prjs.CurrentPage = Pag_GetParamPagNum (Pag_PROJECTS); /***** Get selected users *****/ if (Gbl.Prjs.Filter.Who == Usr_WHO_SELECTED) Usr_GetListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected); } /*****************************************************************************/ /************* Get parameter with whose users' projects to view **************/ /*****************************************************************************/ static void Prj_GetParamWho (void) { /***** Get which users I want to see *****/ Gbl.Prjs.Filter.Who = Usr_GetHiddenParamWho (); /***** If parameter Who is unknown, set it to default *****/ if (Gbl.Prjs.Filter.Who == Usr_WHO_UNKNOWN) Gbl.Prjs.Filter.Who = Prj_FILTER_WHO_DEFAULT; } /*****************************************************************************/ /******************* Write header with fields of a project *******************/ /*****************************************************************************/ static void Prj_ShowProjectsHead (Prj_ProjectView_t ProjectView) { extern const char *Txt_No_INDEX; extern const char *Txt_PROJECT_ORDER_HELP[Prj_NUM_ORDERS]; extern const char *Txt_PROJECT_ORDER[Prj_NUM_ORDERS]; Prj_Order_t Order; HTM_TR_Begin (NULL); /***** Column for number of project *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TH (1,1,"CM",Txt_No_INDEX); break; default: break; } /***** Column for contextual icons *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: case Prj_FILE_BROWSER_PROJECT: HTM_TH (1,1,"CONTEXT_COL",NULL); break; default: break; } /***** Rest of columns *****/ for (Order = (Prj_Order_t) 0; Order <= (Prj_Order_t) (Prj_NUM_ORDERS - 1); Order++) { HTM_TH_Begin (1,1,"CM"); switch (ProjectView) { case Prj_LIST_PROJECTS: case Prj_FILE_BROWSER_PROJECT: Frm_StartForm (ActSeePrj); Prj_PutParams (&Gbl.Prjs.Filter, Order, Gbl.Prjs.CurrentPage, -1L); Frm_LinkFormSubmit (Txt_PROJECT_ORDER_HELP[Order],"TIT_TBL",NULL); if (Order == Gbl.Prjs.SelectedOrder) HTM_U_Begin (); HTM_Txt (Txt_PROJECT_ORDER[Order]); if (Order == Gbl.Prjs.SelectedOrder) HTM_U_End (); Frm_LinkFormEnd (); Frm_EndForm (); break; default: HTM_Txt (Txt_PROJECT_ORDER[Order]); break; } HTM_TH_End (); } } static void Prj_ShowTableAllProjectsHead (void) { extern const char *Txt_PROJECT_ORDER[Prj_NUM_ORDERS]; extern const char *Txt_Assigned_QUESTION; extern const char *Txt_Number_of_students; extern const char *Txt_PROJECT_ROLES_PLURAL_Abc[Prj_NUM_ROLES_IN_PROJECT]; extern const char *Txt_Proposal; extern const char *Txt_Description; extern const char *Txt_Required_knowledge; extern const char *Txt_Required_materials; extern const char *Txt_URL; Prj_Order_t Order; unsigned NumRoleToShow; HTM_TR_Begin (NULL); for (Order = (Prj_Order_t) 0; Order <= (Prj_Order_t) (Prj_NUM_ORDERS - 1); Order++) HTM_TH (1,1,"LT DAT_N",Txt_PROJECT_ORDER[Order]); HTM_TH (1,1,"LT DAT_N",Txt_Assigned_QUESTION); HTM_TH (1,1,"LT DAT_N",Txt_Number_of_students); for (NumRoleToShow = 0; NumRoleToShow < Brw_NUM_ROLES_TO_SHOW; NumRoleToShow++) HTM_TH (1,1,"LT DAT_N",Txt_PROJECT_ROLES_PLURAL_Abc[Prj_RolesToShow[NumRoleToShow]]); HTM_TH (1,1,"LT DAT_N",Txt_Proposal); HTM_TH (1,1,"LT DAT_N",Txt_Description); HTM_TH (1,1,"LT DAT_N",Txt_Required_knowledge); HTM_TH (1,1,"LT DAT_N",Txt_Required_materials); HTM_TH (1,1,"LT DAT_N",Txt_URL); HTM_TR_End (); } /*****************************************************************************/ /********************** Check if I can create projects ***********************/ /*****************************************************************************/ static bool Prj_CheckIfICanCreateProjects (void) { static const bool ICanCreateProjects[Rol_NUM_ROLES] = { false, // Rol_UNK false, // Rol_GST false, // Rol_USR false, // Rol_STD true, // Rol_NET true, // Rol_TCH true, // Rol_DEG_ADM true, // Rol_CTR_ADM true, // Rol_INS_ADM true, // Rol_SYS_ADM }; return ICanCreateProjects[Gbl.Usrs.Me.Role.Logged]; } /*****************************************************************************/ /***************** Put contextual icons in list of projects ******************/ /*****************************************************************************/ static void Prj_PutIconsListProjects (void) { bool ICanConfigAllProjects = Prj_CheckIfICanConfigAllProjects (); /***** Put icon to create a new project *****/ if (Prj_CheckIfICanCreateProjects ()) Prj_PutIconToCreateNewPrj (); if (Gbl.Prjs.Num) { /***** Put icon to show all data in a table *****/ Prj_PutIconToShowAllData (); if (ICanConfigAllProjects) /****** Put icons to request locking/unlocking edition of all selected projects *******/ Prj_PutIconsToLockUnlockAllProjects (); } /***** Put form to go to configuration of projects *****/ if (ICanConfigAllProjects) Ico_PutContextualIconToConfigure (ActCfgPrj,NULL); /***** Put icon to show a figure *****/ Gbl.Figures.FigureType = Fig_PROJECTS; Fig_PutIconToShowFigure (); } /*****************************************************************************/ /********************* Put icon to create a new project **********************/ /*****************************************************************************/ static void Prj_PutIconToCreateNewPrj (void) { extern const char *Txt_New_project; /***** Put form to create a new project *****/ Gbl.Prjs.PrjCod = -1L; Ico_PutContextualIconToAdd (ActFrmNewPrj,NULL,Prj_PutCurrentParams, Txt_New_project); } /*****************************************************************************/ /******************** Put button to create a new project *********************/ /*****************************************************************************/ static void Prj_PutButtonToCreateNewPrj (void) { extern const char *Txt_New_project; Gbl.Prjs.PrjCod = -1L; Frm_StartForm (ActFrmNewPrj); Prj_PutCurrentParams (); Btn_PutConfirmButton (Txt_New_project); Frm_EndForm (); } /*****************************************************************************/ /******************** Put button to create a new project *********************/ /*****************************************************************************/ static void Prj_PutIconToShowAllData (void) { extern const char *Txt_Show_all_data_in_a_table; Lay_PutContextualLinkOnlyIcon (ActSeeTblAllPrj,NULL,Prj_PutCurrentParams, "table.svg", Txt_Show_all_data_in_a_table); } /*****************************************************************************/ /***************** View / edit file browser of one project *******************/ /*****************************************************************************/ void Prj_ShowOneUniqueProject (struct Project *Prj) { /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); /***** Write project head *****/ Prj_ShowProjectsHead (Prj_FILE_BROWSER_PROJECT); /***** Show project *****/ Prj_ShowOneProject (0,Prj,Prj_FILE_BROWSER_PROJECT); /***** End table *****/ HTM_TABLE_End (); } /*****************************************************************************/ /********************** Show print view of one project ***********************/ /*****************************************************************************/ void Prj_PrintOneProject (void) { struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get project data *****/ Prj.PrjCod = Prj_GetParamPrjCod (); Prj_GetDataOfProjectByCod (&Prj); /***** Write header *****/ Lay_WriteHeaderClassPhoto (true,false, Gbl.Hierarchy.Ins.InsCod, Gbl.Hierarchy.Deg.DegCod, Gbl.Hierarchy.Crs.CrsCod); /***** Table head *****/ HTM_TABLE_BeginWideMarginPadding (2); Prj_ShowProjectsHead (Prj_PRINT_ONE_PROJECT); /***** Write project *****/ Prj_ShowOneProject (0,&Prj,Prj_PRINT_ONE_PROJECT); /***** End table *****/ HTM_TABLE_End (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); } /*****************************************************************************/ /***************************** Show one project ******************************/ /*****************************************************************************/ static void Prj_ShowOneProject (unsigned NumIndex,struct Project *Prj, Prj_ProjectView_t ProjectView) { extern const char *Txt_Project_files; extern const char *Txt_Assigned_QUESTION; extern const char *Txt_Yes; extern const char *Txt_No; extern const char *Txt_PROJECT_ASSIGNED_NONASSIGNED_SINGUL[Prj_NUM_ASSIGNED_NONASSIG]; extern const char *Txt_Number_of_students; extern const char *Txt_See_more; extern const char *Txt_See_less; extern const char *Txt_Proposal; extern const char *Txt_PROJECT_STATUS[Prj_NUM_PROPOSAL_TYPES]; extern const char *Txt_Description; extern const char *Txt_Required_knowledge; extern const char *Txt_Required_materials; char *Anchor = NULL; bool ICanViewProjectFiles = Prj_CheckIfICanViewProjectFiles (Prj_GetMyRolesInProject (Prj->PrjCod)); const char *ClassLabel; const char *ClassDate; const char *ClassTitle; const char *ClassData; struct Prj_Faults Faults; bool PrjIsFaulty; static unsigned UniqueId = 0; char *Id; /***** Set CSS classes *****/ ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" : "ASG_LABEL"; ClassDate = (Prj->Hidden == Prj_HIDDEN) ? "DATE_BLUE_LIGHT" : "DATE_BLUE"; ClassTitle = (Prj->Hidden == Prj_HIDDEN) ? "ASG_TITLE_LIGHT" : "ASG_TITLE"; ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Set anchor string *****/ Frm_SetAnchorStr (Prj->PrjCod,&Anchor); /***** Check if project is faulty or faultless *****/ PrjIsFaulty = Prj_CheckIfPrjIsFaulty (Prj->PrjCod,&Faults); /***** Write first row of data of this project *****/ HTM_TR_Begin (NULL); /* Number of project */ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("rowspan=\"3\" class=\"BIG_INDEX RT COLOR%u\"", Gbl.RowEvenOdd); HTM_Unsigned (NumIndex); if (PrjIsFaulty) { HTM_BR (); Prj_PutWarningIcon (); } HTM_TD_End (); break; default: break; } /* Forms to remove/edit this project */ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("rowspan=\"3\" class=\"CONTEXT_COL COLOR%u\"",Gbl.RowEvenOdd); Prj_PutFormsToRemEditOnePrj (Prj,Anchor,ICanViewProjectFiles); HTM_TD_End (); break; case Prj_FILE_BROWSER_PROJECT: HTM_TD_Begin ("rowspan=\"3\" class=\"CONTEXT_COL\""); Prj_PutFormsToRemEditOnePrj (Prj,Anchor,ICanViewProjectFiles); HTM_TD_End (); break; default: break; } /* Creation date/time */ UniqueId++; if (asprintf (&Id,"prj_creat_%u",UniqueId) < 0) Lay_NotEnoughMemoryExit (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"", Id,ClassDate,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"", Id,ClassDate); break; } Dat_WriteLocalDateHMSFromUTC (Id,Prj->CreatTime, Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK, true,true,true,0x7); HTM_TD_End (); free (Id); /* Modification date/time */ UniqueId++; if (asprintf (&Id,"prj_modif_%u",UniqueId) < 0) Lay_NotEnoughMemoryExit (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"", Id,ClassDate,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"", Id,ClassDate); break; } Dat_WriteLocalDateHMSFromUTC (Id,Prj->ModifTime, Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK, true,true,true,0x7); HTM_TD_End (); free (Id); /* Project title */ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("class=\"%s LT COLOR%u\"",ClassTitle,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("class=\"%s LT\"",ClassTitle); break; } HTM_ARTICLE_Begin (Anchor); if (Prj->Title[0]) { if (ICanViewProjectFiles) { Frm_StartForm (ActAdmDocPrj); Prj_PutCurrentParams (); Frm_LinkFormSubmit (Txt_Project_files,ClassTitle,NULL); HTM_Txt (Prj->Title); Frm_LinkFormEnd (); Frm_EndForm (); } else HTM_Txt (Prj->Title); } if (Faults.WrongTitle) Prj_PutWarningIcon (); HTM_ARTICLE_End (); HTM_TD_End (); /* Department */ Prj_ShowOneProjectDepartment (Prj,ProjectView); /***** Assigned? *****/ HTM_TR_Begin (NULL); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"RT %s COLOR%u\"", ClassLabel,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"", ClassLabel); break; } HTM_TxtF ("%s:",Txt_Assigned_QUESTION); HTM_TD_End (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; } HTM_TxtF ("%s ",Prj->Assigned == Prj_ASSIGNED ? Txt_Yes : Txt_No); Ico_PutIconOff (AssignedNonassigImage[Prj->Assigned], Txt_PROJECT_ASSIGNED_NONASSIGNED_SINGUL[Prj->Assigned]); if (Faults.WrongAssigned) Prj_PutWarningIcon (); HTM_TD_End (); HTM_TR_End (); /***** Number of students *****/ HTM_TR_Begin (NULL); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"RT %s COLOR%u\"", ClassLabel,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"", ClassLabel); break; } HTM_TxtF ("%s:",Txt_Number_of_students); HTM_TD_End (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; } HTM_Unsigned (Prj->NumStds); if (Faults.WrongNumStds) Prj_PutWarningIcon (); HTM_TD_End (); HTM_TR_End (); /***** Project members *****/ Prj_ShowOneProjectMembers (Prj,ProjectView); /***** Link to show hidden info *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TR_Begin ("id=\"prj_exp_%u\"",UniqueId); HTM_TD_Begin ("colspan=\"6\" class=\"CM COLOR%u\"",Gbl.RowEvenOdd); Prj_PutIconToToggleProject (UniqueId,"angle-down.svg",Txt_See_more); HTM_TD_End (); HTM_TR_End (); HTM_TR_Begin ("id=\"prj_con_%u\" style=\"display:none;\"",UniqueId); HTM_TD_Begin ("colspan=\"6\" class=\"CM COLOR%u\"",Gbl.RowEvenOdd); Prj_PutIconToToggleProject (UniqueId,"angle-up.svg",Txt_See_less); HTM_TD_End (); HTM_TR_End (); break; case Prj_FILE_BROWSER_PROJECT: HTM_TR_Begin ("id=\"prj_exp_%u\"",UniqueId); HTM_TD_Begin ("colspan=\"5\" class=\"CM\""); Prj_PutIconToToggleProject (UniqueId,"angle-down.svg",Txt_See_more); HTM_TD_End (); HTM_TR_End (); HTM_TR_Begin ("id=\"prj_con_%u\" style=\"display:none;\"",UniqueId); HTM_TD_Begin ("colspan=\"5\" class=\"CM\""); Prj_PutIconToToggleProject (UniqueId,"angle-up.svg",Txt_See_less); HTM_TD_End (); HTM_TR_End (); break; default: break; } /***** Proposal *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TR_Begin ("id=\"prj_pro_%u\" style=\"display:none;\"",UniqueId); HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"", ClassLabel,Gbl.RowEvenOdd); break; case Prj_FILE_BROWSER_PROJECT: HTM_TR_Begin ("id=\"prj_pro_%u\" style=\"display:none;\"",UniqueId); HTM_TD_Begin ("colspan=\"3\" class=\"RT %s\"",ClassLabel); break; default: HTM_TR_Begin (NULL); HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"",ClassLabel); break; } HTM_TxtF ("%s:",Txt_Proposal); HTM_TD_End (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData, Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; } HTM_Txt (Txt_PROJECT_STATUS[Prj->Proposal]); HTM_TD_End (); HTM_TR_End (); /***** Write rows of data of this project *****/ /* Description of the project */ Prj_ShowOneProjectTxtField (Prj,ProjectView,"prj_dsc_",UniqueId, Txt_Description,Prj->Description, Faults.WrongDescription); /* Required knowledge to carry out the project */ Prj_ShowOneProjectTxtField (Prj,ProjectView,"prj_knw_",UniqueId, Txt_Required_knowledge,Prj->Knowledge, false); // No warning /* Required materials to carry out the project */ Prj_ShowOneProjectTxtField (Prj,ProjectView,"prj_mtr_",UniqueId, Txt_Required_materials,Prj->Materials, false); // No warning /* Link to view more info about the project */ Prj_ShowOneProjectURL (Prj,ProjectView,"prj_url_",UniqueId); /***** Free anchor string *****/ Frm_FreeAnchorStr (Anchor); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /*****************************************************************************/ /********************** Check if a project has faults ************************/ /*****************************************************************************/ static bool Prj_CheckIfPrjIsFaulty (long PrjCod,struct Prj_Faults *Faults) { MYSQL_RES *mysql_res; MYSQL_ROW row; long LongNum; bool IsAssigned; bool HasTitle; bool HasDescription; unsigned NumProposedStds; unsigned NumStdsRegisteredInPrj; /***** Reset faults *****/ Faults->WrongTitle = Faults->WrongDescription = Faults->WrongNumStds = Faults->WrongAssigned = false; /***** Get some project date and check faults ****/ if (PrjCod > 0) { /***** Query database *****/ if (DB_QuerySELECT (&mysql_res,"can not get project data", "SELECT Assigned='Y'," // row[0] = 0 / 1 "NumStds," // row[1] = "Title<>''," // row[2] = 0 / 1 "Description<>''" // row[3] = 0 / 1 " FROM projects" " WHERE PrjCod=%ld", PrjCod)) // Project found... { /***** Get some data of project *****/ /* Get row */ row = mysql_fetch_row (mysql_res); /* Get if project is assigned or not (row[0]) */ IsAssigned = (row[0][0] != '0'); /* Get if project is assigned or not (row[1]) */ LongNum = Str_ConvertStrCodToLongCod (row[1]); NumProposedStds = (LongNum > 0) ? (unsigned) LongNum : 0; /* Get the title of the project (row[2]) */ HasTitle = (row[2][0] != '0'); /* Get the description of the project (row[3]) */ HasDescription = (row[3][0] != '0'); /***** Check faults *****/ /* 1. Check title */ Faults->WrongTitle = !HasTitle; /* 2. Check description */ Faults->WrongDescription = !HasDescription; /* 3. Check number of students */ if (NumProposedStds == 0) // The number of proposed students should be > 0 Faults->WrongNumStds = true; else { NumStdsRegisteredInPrj = Prj_GetNumUsrsInPrj (PrjCod,Prj_ROLE_STD); if (IsAssigned) // Assigned // In an assigned project the number of proposed students... // ...should match the number of students registered in it Faults->WrongNumStds = (NumProposedStds != NumStdsRegisteredInPrj); else // Not assigned // A non assigned project should not have students registered in it Faults->WrongAssigned = (NumStdsRegisteredInPrj != 0); } } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } return Faults->WrongTitle || Faults->WrongDescription || Faults->WrongNumStds || Faults->WrongAssigned; } /*****************************************************************************/ /************** Put an icon to warn about a fault in a project ***************/ /*****************************************************************************/ static void Prj_PutWarningIcon (void) { Ico_PutIcon ("warning64x64.gif","","ICO16x16"); } /*****************************************************************************/ /********** Put an icon to toggle on/off some fields of a project ************/ /*****************************************************************************/ static void Prj_PutIconToToggleProject (unsigned UniqueId, const char *Icon,const char *Text) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; /***** Link to toggle on/off some fields of project *****/ HTM_A_Begin ("href=\"\" title=\"%s\" class=\"%s\"" " onclick=\"toggleProject('%u');return false;\"", Text,The_ClassFormInBox[Gbl.Prefs.Theme], UniqueId); Ico_PutIconTextLink (Icon,Text); HTM_A_End (); } /*****************************************************************************/ /***************** Show one row of table with all projects *******************/ /*****************************************************************************/ static void Prj_ShowTableAllProjectsOneRow (struct Project *Prj) { extern const char *Txt_Yes; extern const char *Txt_No; extern const char *Txt_PROJECT_STATUS[Prj_NUM_PROPOSAL_TYPES]; unsigned NumRoleToShow; const char *ClassDate; const char *ClassData; static unsigned UniqueId = 0; char *Id; /***** Get data of this project *****/ Prj_GetDataOfProjectByCod (Prj); /***** Set CSS classes *****/ ClassDate = (Prj->Hidden == Prj_HIDDEN) ? "DATE_BLUE_LIGHT" : "DATE_BLUE"; ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Start row *****/ HTM_TR_Begin (NULL); /***** Start date/time *****/ UniqueId++; if (asprintf (&Id,"prj_creat_%u",UniqueId) < 0) Lay_NotEnoughMemoryExit (); HTM_TD_Begin ("id=\"%s\" class=\"LT %s COLOR%u\"", Id,ClassDate,Gbl.RowEvenOdd); Dat_WriteLocalDateHMSFromUTC (Id,Prj->CreatTime, Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK, true,true,false,0x7); HTM_TD_End (); free (Id); /***** End date/time *****/ UniqueId++; if (asprintf (&Id,"prj_modif_%u",UniqueId) < 0) Lay_NotEnoughMemoryExit (); HTM_TD_Begin ("id=\"%s\" class=\"LT %s COLOR%u\"", Id,ClassDate,Gbl.RowEvenOdd); Dat_WriteLocalDateHMSFromUTC (Id,Prj->ModifTime, Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK, true,true,false,0x7); HTM_TD_End (); free (Id); /***** Project title *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"", ClassData, Gbl.RowEvenOdd); HTM_Txt (Prj->Title); HTM_TD_End (); /***** Department *****/ Prj_ShowTableAllProjectsDepartment (Prj); /***** Assigned? *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Txt ((Prj->Assigned == Prj_ASSIGNED) ? Txt_Yes : Txt_No); HTM_TD_End (); /***** Number of students *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Unsigned (Prj->NumStds); HTM_TD_End (); /***** Project members *****/ for (NumRoleToShow = 0; NumRoleToShow < Brw_NUM_ROLES_TO_SHOW; NumRoleToShow++) Prj_ShowTableAllProjectsMembersWithARole (Prj,Prj_RolesToShow[NumRoleToShow]); /***** Proposal *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Txt (Txt_PROJECT_STATUS[Prj->Proposal]); HTM_TD_End (); /***** Write rows of data of this project *****/ /* Description of the project */ Prj_ShowTableAllProjectsTxtField (Prj,Prj->Description); /* Required knowledge to carry out the project */ Prj_ShowTableAllProjectsTxtField (Prj,Prj->Knowledge); /* Required materials to carry out the project */ Prj_ShowTableAllProjectsTxtField (Prj,Prj->Materials); /* Link to view more info about the project */ Prj_ShowTableAllProjectsURL (Prj); /***** End row *****/ HTM_TR_End (); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } /*****************************************************************************/ /****************** Show department associated to project ********************/ /*****************************************************************************/ static void Prj_ShowOneProjectDepartment (const struct Project *Prj, Prj_ProjectView_t ProjectView) { struct Department Dpt; bool PutLink; const char *ClassData; /***** Set CSS classes *****/ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Get data of department *****/ Dpt.DptCod = Prj->DptCod; Dpt_GetDataOfDepartmentByCod (&Dpt); /***** Show department *****/ PutLink = (Dpt.WWW[0] && (ProjectView == Prj_LIST_PROJECTS || ProjectView == Prj_FILE_BROWSER_PROJECT)); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("class=\"LT %s\"",ClassData); break; } if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\" class=\"%s\"", Dpt.WWW,ClassData); HTM_Txt (Dpt.FullName); if (PutLink) HTM_A_End (); HTM_TD_End (); HTM_TR_End (); } static void Prj_ShowTableAllProjectsDepartment (const struct Project *Prj) { struct Department Dpt; const char *ClassData; /***** Set CSS classes *****/ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Get data of department *****/ Dpt.DptCod = Prj->DptCod; Dpt_GetDataOfDepartmentByCod (&Dpt); /***** Show department *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Txt (Dpt.FullName); HTM_TD_End (); } /*****************************************************************************/ /********************** Show text field about a project **********************/ /*****************************************************************************/ static void Prj_ShowOneProjectTxtField (struct Project *Prj, Prj_ProjectView_t ProjectView, const char *id,unsigned UniqueId, const char *Label,char *TxtField, bool Warning) { const char *ClassLabel; const char *ClassData; /***** Set CSS classes *****/ ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" : "ASG_LABEL"; ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Label *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId); HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",ClassLabel,Gbl.RowEvenOdd); break; case Prj_FILE_BROWSER_PROJECT: HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId); HTM_TD_Begin ("colspan=\"3\" class=\"RT %s\"",ClassLabel); break; case Prj_PRINT_ONE_PROJECT: HTM_TR_Begin (NULL); HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"",ClassLabel); break; default: // Not applicable break; } HTM_TxtF ("%s:",Label); HTM_TD_End (); /***** Change text format *****/ Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, TxtField,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML switch (ProjectView) { case Prj_LIST_PROJECTS: case Prj_FILE_BROWSER_PROJECT: Str_InsertLinks (TxtField,Cns_MAX_BYTES_TEXT,60); // Insert links break; default: break; } /***** Text *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; } HTM_Txt (TxtField); if (Warning) Prj_PutWarningIcon (); HTM_TD_End (); HTM_TR_End (); } static void Prj_ShowTableAllProjectsTxtField (struct Project *Prj, char *TxtField) { const char *ClassData; /***** Set CSS classes *****/ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Change format *****/ Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, TxtField,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML /***** Write text *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Txt (TxtField); HTM_TD_End (); } /*****************************************************************************/ /********************** Show URL associated to project ***********************/ /*****************************************************************************/ static void Prj_ShowOneProjectURL (const struct Project *Prj, Prj_ProjectView_t ProjectView, const char *id,unsigned UniqueId) { extern const char *Txt_URL; const char *ClassLabel; const char *ClassData; bool PutLink = (Prj->URL[0] && (ProjectView == Prj_LIST_PROJECTS || ProjectView == Prj_FILE_BROWSER_PROJECT)); /***** Set CSS classes *****/ ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" : "ASG_LABEL"; ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Write row with label and text *****/ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId); HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"",ClassLabel,Gbl.RowEvenOdd); break; case Prj_FILE_BROWSER_PROJECT: HTM_TR_Begin ("id=\"%s%u\" style=\"display:none;\"",id,UniqueId); HTM_TD_Begin ("colspan=\"3\" class=\"RT %s\"",ClassLabel); break; case Prj_PRINT_ONE_PROJECT: HTM_TR_Begin (NULL); HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"",ClassLabel); break; default: // Not applicable break; } HTM_TxtF ("%s:",Txt_URL); HTM_TD_End (); switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData,Gbl.RowEvenOdd); break; default: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; } if (PutLink) HTM_A_Begin ("href=\"%s\" target=\"_blank\"",Prj->URL); HTM_Txt (Prj->URL); if (PutLink) HTM_A_End (); HTM_TD_End (); HTM_TR_End (); } static void Prj_ShowTableAllProjectsURL (const struct Project *Prj) { const char *ClassData; /***** Set CSS classes *****/ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Show URL *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); HTM_Txt (Prj->URL); HTM_TD_End (); } /*****************************************************************************/ /************** Show projects members when showing one project ***************/ /*****************************************************************************/ static void Prj_ShowOneProjectMembers (struct Project *Prj, Prj_ProjectView_t ProjectView) { unsigned NumRoleToShow; for (NumRoleToShow = 0; NumRoleToShow < Brw_NUM_ROLES_TO_SHOW; NumRoleToShow++) Prj_ShowOneProjectMembersWithARole (Prj,ProjectView, Prj_RolesToShow[NumRoleToShow]); } /*****************************************************************************/ /************************* Show users row in a project ***********************/ /*****************************************************************************/ static void Prj_ShowOneProjectMembersWithARole (const struct Project *Prj, Prj_ProjectView_t ProjectView, Prj_RoleInProject_t RoleInProject) { extern const char *Txt_PROJECT_ROLES_SINGUL_Abc[Prj_NUM_ROLES_IN_PROJECT]; extern const char *Txt_PROJECT_ROLES_PLURAL_Abc[Prj_NUM_ROLES_IN_PROJECT]; extern const char *Txt_Remove; extern const char *Txt_Add_USERS; extern const char *Txt_PROJECT_ROLES_PLURAL_abc[Prj_NUM_ROLES_IN_PROJECT]; MYSQL_RES *mysql_res; MYSQL_ROW row; bool WriteRow; unsigned NumUsr; unsigned NumUsrs; bool ShowPhoto; char PhotoURL[PATH_MAX + 1]; const char *ClassLabel; const char *ClassData; static const Act_Action_t ActionReqRemUsr[Prj_NUM_ROLES_IN_PROJECT] = { ActUnk, // Prj_ROLE_UNK, Unknown ActReqRemStdPrj, // Prj_ROLE_STD, Student ActReqRemTutPrj, // Prj_ROLE_TUT, Tutor ActReqRemEvlPrj, // Prj_ROLE_EVL, Evaluator }; static const Act_Action_t ActionReqAddUsr[Prj_NUM_ROLES_IN_PROJECT] = { ActUnk, // Prj_ROLE_UNK, Unknown ActReqAddStdPrj, // Prj_ROLE_STD, Student ActReqAddTutPrj, // Prj_ROLE_TUT, Tutor ActReqAddEvlPrj, // Prj_ROLE_EVL, Evaluator }; /***** Set CSS classes *****/ ClassLabel = (Prj->Hidden == Prj_HIDDEN) ? "ASG_LABEL_LIGHT" : "ASG_LABEL"; ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Get users in project from database *****/ NumUsrs = Prj_GetUsrsInPrj (Prj->PrjCod,RoleInProject,&mysql_res); WriteRow = (NumUsrs != 0 || ProjectView == Prj_EDIT_ONE_PROJECT); if (WriteRow) { /***** Start row with label and listing of users *****/ HTM_TR_Begin (NULL); /* Column for label */ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"4\" class=\"RT %s COLOR%u\"", ClassLabel,Gbl.RowEvenOdd); HTM_TxtF ("%s:",NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] : Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]); break; case Prj_FILE_BROWSER_PROJECT: HTM_TD_Begin ("colspan=\"3\" class=\"RT %s\"",ClassLabel); HTM_TxtF ("%s:",NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] : Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]); break; case Prj_PRINT_ONE_PROJECT: HTM_TD_Begin ("colspan=\"2\" class=\"RT %s\"",ClassLabel); HTM_TxtF ("%s:",NumUsrs == 1 ? Txt_PROJECT_ROLES_SINGUL_Abc[RoleInProject] : Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]); break; case Prj_EDIT_ONE_PROJECT: HTM_TD_Begin ("class=\"RT ASG_LABEL\""); HTM_TxtF ("%s:",Txt_PROJECT_ROLES_PLURAL_Abc[RoleInProject]); break; } HTM_TD_End (); /* Start column with list of users */ switch (ProjectView) { case Prj_LIST_PROJECTS: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s COLOR%u\"", ClassData,Gbl.RowEvenOdd); break; case Prj_FILE_BROWSER_PROJECT: case Prj_PRINT_ONE_PROJECT: HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"", ClassData); break; case Prj_EDIT_ONE_PROJECT: HTM_TD_Begin ("colspan=\"2\" class=\"LT DAT\""); break; } /***** Begin table with all members with this role *****/ HTM_TABLE_BeginPadding (2); /***** Write users *****/ for (NumUsr = 0; NumUsr < NumUsrs; NumUsr++) { /* Get user's code */ row = mysql_fetch_row (mysql_res); Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]); /* Get user's data */ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS)) { /* Start row for this user */ HTM_TR_Begin (NULL); /* Icon to remove user */ if (ProjectView == Prj_EDIT_ONE_PROJECT) { HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\""); Lay_PutContextualLinkOnlyIcon (ActionReqRemUsr[RoleInProject],NULL, Prj_PutCurrentParams, "trash.svg", Txt_Remove); HTM_TD_End (); } /* Put user's photo */ HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\""); ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (&Gbl.Usrs.Other.UsrDat,PhotoURL); Pho_ShowUsrPhoto (&Gbl.Usrs.Other.UsrDat,ShowPhoto ? PhotoURL : NULL, "PHOTO21x28",Pho_ZOOM,false); HTM_TD_End (); /* Write user's name */ HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\""); HTM_Txt (Gbl.Usrs.Other.UsrDat.FullName); HTM_TD_End (); /* End row for this user */ HTM_TR_End (); } } /***** Row to add a new user *****/ switch (ProjectView) { case Prj_EDIT_ONE_PROJECT: HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"PRJ_MEMBER_ICO\""); Gbl.Prjs.PrjCod = Prj->PrjCod; // Used to pass project code as a parameter snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Add_USERS, Txt_PROJECT_ROLES_PLURAL_abc[RoleInProject]); Ico_PutContextualIconToAdd (ActionReqAddUsr[RoleInProject],NULL, Prj_PutCurrentParams, Gbl.Title); HTM_TD_End (); HTM_TD_Begin ("class=\"PRJ_MEMBER_PHO\""); // Column for photo HTM_TD_End (); HTM_TD_Begin ("class=\"PRJ_MEMBER_NAM\""); // Column for name HTM_TD_End (); HTM_TR_End (); break; default: break; } /***** End table with all members with this role *****/ HTM_TABLE_End (); /***** End row with label and listing of users *****/ HTM_TD_End (); HTM_TR_End (); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } static void Prj_ShowTableAllProjectsMembersWithARole (const struct Project *Prj, Prj_RoleInProject_t RoleInProject) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumUsr; unsigned NumUsrs; const char *ClassData; /***** Set CSS classes *****/ ClassData = (Prj->Hidden == Prj_HIDDEN) ? "DAT_LIGHT" : "DAT"; /***** Get users in project from database *****/ NumUsrs = Prj_GetUsrsInPrj (Prj->PrjCod,RoleInProject,&mysql_res); /***** Start column with list of all members with this role *****/ HTM_TD_Begin ("class=\"LT %s COLOR%u\"",ClassData,Gbl.RowEvenOdd); if (NumUsrs) { /***** Write users *****/ HTM_UL_Begin ("class=\"PRJ_LST_USR\""); for (NumUsr = 0; NumUsr < NumUsrs; NumUsr++) { /* Get user's code */ row = mysql_fetch_row (mysql_res); Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]); /* Get user's data */ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS)) { /* Write user's name in "Surname1 Surname2, FirstName" format */ HTM_LI_Begin (NULL); HTM_Txt (Gbl.Usrs.Other.UsrDat.Surname1); if (Gbl.Usrs.Other.UsrDat.Surname2[0]) HTM_TxtF (" %s",Gbl.Usrs.Other.UsrDat.Surname2); HTM_TxtF (", %s",Gbl.Usrs.Other.UsrDat.FirstName); HTM_LI_End (); } } HTM_UL_End (); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); /***** End column with list of all members with this role *****/ HTM_TD_End (); } /*****************************************************************************/ /*************** Get number of users with a role in a project ****************/ /*****************************************************************************/ static unsigned Prj_GetNumUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject) { /***** Get users in project from database *****/ return (unsigned) DB_QueryCOUNT ("can not get number of users in project", "SELECT COUNT(UsrCod)" " FROM prj_usr" " WHERE PrjCod=%ld AND RoleInProject=%u", PrjCod,(unsigned) RoleInProject); } /*****************************************************************************/ /*************** Get number of users with a role in a project ****************/ /*****************************************************************************/ static unsigned Prj_GetUsrsInPrj (long PrjCod,Prj_RoleInProject_t RoleInProject, MYSQL_RES **mysql_res) { /***** Get users in project from database *****/ return (unsigned) DB_QuerySELECT (mysql_res,"can not get users in project", "SELECT prj_usr.UsrCod," // row[0] "usr_data.Surname1 AS S1," // row[1] "usr_data.Surname2 AS S2," // row[2] "usr_data.FirstName AS FN" // row[3] " FROM prj_usr,usr_data" " WHERE prj_usr.PrjCod=%ld" " AND prj_usr.RoleInProject=%u" " AND prj_usr.UsrCod=usr_data.UsrCod" " ORDER BY S1,S2,FN", PrjCod,(unsigned) RoleInProject); } /*****************************************************************************/ /************************** Get my role in a project *************************/ /*****************************************************************************/ void Prj_FlushCacheMyRolesInProject (void) { Gbl.Cache.MyRolesInProject.PrjCod = -1L; Gbl.Cache.MyRolesInProject.RolesInProject = 0; } unsigned Prj_GetMyRolesInProject (long PrjCod) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumRows; unsigned NumRow; Prj_RoleInProject_t RoleInProject; /***** 1. Fast check: trivial cases *****/ if (Gbl.Usrs.Me.UsrDat.UsrCod <= 0 || PrjCod <= 0) return 0; /***** 2. Fast check: Is my role in project already calculated *****/ if (PrjCod == Gbl.Cache.MyRolesInProject.PrjCod) return Gbl.Cache.MyRolesInProject.RolesInProject; /***** 3. Slow check: Get my role in project from database. The result of the query will have one row or none *****/ Gbl.Cache.MyRolesInProject.PrjCod = PrjCod; Gbl.Cache.MyRolesInProject.RolesInProject = 0; NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get my roles in project", "SELECT RoleInProject FROM prj_usr" " WHERE PrjCod=%ld AND UsrCod=%ld", PrjCod,Gbl.Usrs.Me.UsrDat.UsrCod); for (NumRow = 0; NumRow < NumRows; NumRow++) { row = mysql_fetch_row (mysql_res); RoleInProject = Prj_ConvertUnsignedStrToRoleInProject (row[0]); if (RoleInProject != Prj_ROLE_UNK) Gbl.Cache.MyRolesInProject.RolesInProject |= (1 << RoleInProject); } DB_FreeMySQLResult (&mysql_res); return Gbl.Cache.MyRolesInProject.RolesInProject; } /*****************************************************************************/ /********************** Get role from unsigned string ************************/ /*****************************************************************************/ static Prj_RoleInProject_t Prj_ConvertUnsignedStrToRoleInProject (const char *UnsignedStr) { unsigned UnsignedNum; if (sscanf (UnsignedStr,"%u",&UnsignedNum) == 1) if (UnsignedNum < Prj_NUM_ROLES_IN_PROJECT) return (Prj_RoleInProject_t) UnsignedNum; return Prj_ROLE_UNK; } /*****************************************************************************/ /******************* Request users to be added to project ********************/ /*****************************************************************************/ void Prj_ReqAddStds (void) { Prj_ReqAddUsrs (Prj_ROLE_STD); } void Prj_ReqAddTuts (void) { Prj_ReqAddUsrs (Prj_ROLE_TUT); } void Prj_ReqAddEvls (void) { Prj_ReqAddUsrs (Prj_ROLE_EVL); } static void Prj_ReqAddUsrs (Prj_RoleInProject_t RoleInProject) { extern const char *Hlp_ASSESSMENT_Projects_add_user; extern const char *Txt_Add_USERS; extern const char *Txt_PROJECT_ROLES_PLURAL_abc[Prj_NUM_ROLES_IN_PROJECT]; static Act_Action_t ActionAddUsr[Prj_NUM_ROLES_IN_PROJECT] = { ActUnk, // Prj_ROLE_UNK, Unknown ActAddStdPrj, // Prj_ROLE_STD, Student ActAddTutPrj, // Prj_ROLE_TUT, Tutor ActAddEvlPrj, // Prj_ROLE_EVL, Evaluator }; char TxtButton[Lay_MAX_BYTES_TITLE + 1]; /***** Get project code *****/ if ((Gbl.Prjs.PrjCod = Prj_GetParamPrjCod ()) == -1L) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Put form to select users *****/ snprintf (TxtButton,sizeof (TxtButton), Txt_Add_USERS, Txt_PROJECT_ROLES_PLURAL_abc[RoleInProject]); Usr_PutFormToSelectUsrsToGoToAct (&Prj_MembersToAdd, ActionAddUsr[RoleInProject],Prj_PutCurrentParams, TxtButton, Hlp_ASSESSMENT_Projects_add_user, TxtButton); /***** Put a form to create/edit project *****/ Prj_RequestCreatOrEditPrj (Gbl.Prjs.PrjCod); } /*****************************************************************************/ /******* Get and check list of selected users, and show users' works ********/ /*****************************************************************************/ void Prj_GetSelectedUsrsAndAddStds (void) { Usr_GetSelectedUsrsAndGoToAct (&Prj_MembersToAdd, Prj_AddStds, // when user(s) selected Prj_ReqAddStds); // when no user selected } void Prj_GetSelectedUsrsAndAddTuts (void) { Usr_GetSelectedUsrsAndGoToAct (&Prj_MembersToAdd, Prj_AddTuts, // when user(s) selected Prj_ReqAddTuts); // when no user selected } void Prj_GetSelectedUsrsAndAddEvls (void) { Usr_GetSelectedUsrsAndGoToAct (&Prj_MembersToAdd, Prj_AddEvls, // when user(s) selected Prj_ReqAddEvls); // when no user selected } /*****************************************************************************/ /**************************** Add users to project ***************************/ /*****************************************************************************/ static void Prj_AddStds (void) { Prj_AddUsrsToProject (Prj_ROLE_STD); } static void Prj_AddTuts (void) { Prj_AddUsrsToProject (Prj_ROLE_TUT); } static void Prj_AddEvls (void) { Prj_AddUsrsToProject (Prj_ROLE_EVL); } static void Prj_AddUsrsToProject (Prj_RoleInProject_t RoleInProject) { extern const char *Txt_THE_USER_X_has_been_enroled_as_a_Y_in_the_project; extern const char *Txt_PROJECT_ROLES_SINGUL_abc[Prj_NUM_ROLES_IN_PROJECT][Usr_NUM_SEXS]; long PrjCod; const char *Ptr; bool ItsMe; /***** Get project code *****/ if ((PrjCod = Prj_GetParamPrjCod ()) == -1L) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Add the selected users to project *****/ Ptr = Gbl.Usrs.Selected.List[Rol_UNK]; while (*Ptr) { /* Get next user */ Par_GetNextStrUntilSeparParamMult (&Ptr,Gbl.Usrs.Other.UsrDat.EncryptedUsrCod, Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64); Usr_GetUsrCodFromEncryptedUsrCod (&Gbl.Usrs.Other.UsrDat); /* Get user's data */ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS)) // Get of the database the data of the user { /* Add user to project */ DB_QueryREPLACE ("can not add user to project", "REPLACE INTO prj_usr" " (PrjCod,RoleInProject,UsrCod)" " VALUES" " (%ld,%u,%ld)", PrjCod,(unsigned) RoleInProject, Gbl.Usrs.Other.UsrDat.UsrCod); /* Flush cache */ ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod); if (ItsMe) Prj_FlushCacheMyRolesInProject (); /* Show success alert */ Ale_ShowAlert (Ale_SUCCESS,Txt_THE_USER_X_has_been_enroled_as_a_Y_in_the_project, Gbl.Usrs.Other.UsrDat.FullName, Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex]); } } /***** Put form to edit project again *****/ Prj_RequestCreatOrEditPrj (PrjCod); } /*****************************************************************************/ /************ Request confirmation to remove user from project ***************/ /*****************************************************************************/ void Prj_ReqRemStd (void) { Prj_ReqRemUsrFromPrj (Prj_ROLE_STD); } void Prj_ReqRemTut (void) { Prj_ReqRemUsrFromPrj (Prj_ROLE_TUT); } void Prj_ReqRemEvl (void) { Prj_ReqRemUsrFromPrj (Prj_ROLE_EVL); } static void Prj_ReqRemUsrFromPrj (Prj_RoleInProject_t RoleInProject) { extern const char *Txt_Do_you_really_want_to_be_removed_as_a_X_from_the_project_Y; extern const char *Txt_Do_you_really_want_to_remove_the_following_user_as_a_X_from_the_project_Y; extern const char *Txt_PROJECT_ROLES_SINGUL_abc[Prj_NUM_ROLES_IN_PROJECT][Usr_NUM_SEXS]; extern const char *Txt_Remove_USER_from_this_project; static Act_Action_t ActionRemUsr[Prj_NUM_ROLES_IN_PROJECT] = { ActUnk, // Prj_ROLE_UNK, Unknown ActRemStdPrj, // Prj_ROLE_STD, Student ActRemTutPrj, // Prj_ROLE_TUT, Tutor ActRemEvlPrj, // Prj_ROLE_EVL, Evaluator }; struct Project Prj; bool ItsMe; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); /***** Get user to be removed *****/ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ()) { if (Prj_CheckIfICanEditProject (&Prj)) { ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod); /***** Show question and button to remove user as a role from project *****/ /* Start alert */ Ale_ShowAlertAndButton1 (Ale_QUESTION,ItsMe ? Txt_Do_you_really_want_to_be_removed_as_a_X_from_the_project_Y : Txt_Do_you_really_want_to_remove_the_following_user_as_a_X_from_the_project_Y, Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex], Prj.Title); /* Show user's record */ Rec_ShowSharedRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat); /* Show form to request confirmation */ Frm_StartForm (ActionRemUsr[RoleInProject]); Gbl.Prjs.PrjCod = Prj.PrjCod; Prj_PutCurrentParams (); snprintf (Gbl.Title,sizeof (Gbl.Title), Txt_Remove_USER_from_this_project, Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex]); Btn_PutRemoveButton (Gbl.Title); Frm_EndForm (); /* End alert */ Ale_ShowAlertAndButton2 (ActUnk,NULL,NULL,NULL,Btn_NO_BUTTON,NULL); } else Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (); } else Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Put form to edit project again *****/ Prj_RequestCreatOrEditPrj (Prj.PrjCod); } /*****************************************************************************/ /************************ Remove user from project ***************************/ /*****************************************************************************/ void Prj_RemStd (void) { Prj_RemUsrFromPrj (Prj_ROLE_STD); } void Prj_RemTut (void) { Prj_RemUsrFromPrj (Prj_ROLE_TUT); } void Prj_RemEvl (void) { Prj_RemUsrFromPrj (Prj_ROLE_EVL); } static void Prj_RemUsrFromPrj (Prj_RoleInProject_t RoleInProject) { extern const char *Txt_THE_USER_X_has_been_removed_as_a_Y_from_the_project_Z; extern const char *Txt_PROJECT_ROLES_SINGUL_abc[Prj_NUM_ROLES_IN_PROJECT][Usr_NUM_SEXS]; struct Project Prj; bool ItsMe; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); /***** Get user to be removed *****/ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ()) { if (Prj_CheckIfICanEditProject (&Prj)) { /***** Remove user from the table of project-users *****/ DB_QueryDELETE ("can not remove a user from a project", "DELETE FROM prj_usr" " WHERE PrjCod=%ld AND RoleInProject=%u" " AND UsrCod=%ld", Prj.PrjCod, (unsigned) RoleInProject, Gbl.Usrs.Other.UsrDat.UsrCod); /***** Flush cache *****/ ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod); if (ItsMe) Prj_FlushCacheMyRolesInProject (); /***** Show success alert *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_THE_USER_X_has_been_removed_as_a_Y_from_the_project_Z, Gbl.Usrs.Other.UsrDat.FullName, Txt_PROJECT_ROLES_SINGUL_abc[RoleInProject][Gbl.Usrs.Other.UsrDat.Sex], Prj.Title); } else Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (); } else Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Put form to edit project again *****/ Prj_RequestCreatOrEditPrj (Prj.PrjCod); } /*****************************************************************************/ /********* Get parameter with the type or order in list of projects **********/ /*****************************************************************************/ static void Prj_GetParamPrjOrder (void) { Gbl.Prjs.SelectedOrder = (Prj_Order_t) Par_GetParToUnsignedLong ("Order", 0, Prj_NUM_ORDERS - 1, (unsigned long) Prj_ORDER_DEFAULT); } /*****************************************************************************/ /***** Put a hidden parameter with the type of order in list of projects *****/ /*****************************************************************************/ void Prj_PutHiddenParamPrjOrder (void) { Par_PutHiddenParamUnsigned (NULL,"Order",(unsigned) Gbl.Prjs.SelectedOrder); } /*****************************************************************************/ /****************** Put a link (form) to edit one project ********************/ /*****************************************************************************/ static void Prj_PutFormsToRemEditOnePrj (const struct Project *Prj, const char *Anchor, bool ICanViewProjectFiles) { Gbl.Prjs.PrjCod = Prj->PrjCod; // Used as parameter in contextual links if (Prj_CheckIfICanEditProject (Prj)) { /***** Put form to remove project *****/ Ico_PutContextualIconToRemove (ActReqRemPrj,Prj_PutCurrentParams); /***** Put form to hide/show project *****/ switch (Prj->Hidden) { case Prj_HIDDEN: Ico_PutContextualIconToUnhide (ActShoPrj,Anchor,Prj_PutCurrentParams); break; case Prj_VISIBL: Ico_PutContextualIconToHide (ActHidPrj,Anchor,Prj_PutCurrentParams); break; } /***** Put form to edit project *****/ Ico_PutContextualIconToEdit (ActEdiOnePrj,Prj_PutCurrentParams); } /***** Put form to admin project documents *****/ if (ICanViewProjectFiles) Ico_PutContextualIconToViewFiles (ActAdmDocPrj,Prj_PutCurrentParams); /***** Put form to print project *****/ Ico_PutContextualIconToPrint (ActPrnOnePrj,Prj_PutCurrentParams); /***** Locked/unlocked project edition *****/ if (Prj_CheckIfICanConfigAllProjects ()) { /* Put form to lock/unlock project edition */ HTM_DIV_Begin ("id=\"prj_lck_%ld\"",Prj->PrjCod); Prj_FormLockUnlock (Prj); HTM_DIV_End (); } else /* Put icon toinform about locked/unlocked project edition */ Prj_PutIconOffLockedUnlocked (Prj); } /*****************************************************************************/ /******************** Can I view files of a given project? *******************/ /*****************************************************************************/ bool Prj_CheckIfICanViewProjectFiles (unsigned MyRolesInProject) { switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: case Rol_NET: case Rol_TCH: return (MyRolesInProject != 0); // Am I a member? case Rol_SYS_ADM: return true; default: return false; } } /*****************************************************************************/ /************************ Can I edit a given project? ************************/ /*****************************************************************************/ static bool Prj_CheckIfICanEditProject (const struct Project *Prj) { switch (Gbl.Usrs.Me.Role.Logged) { case Rol_NET: if (Prj->Locked == Prj_LOCKED) // Locked edition return false; return (Prj_GetMyRolesInProject (Prj->PrjCod) & (1 << Prj_ROLE_TUT)) != 0; // Am I a tutor? case Rol_TCH: case Rol_SYS_ADM: return true; default: return false; } } /*****************************************************************************/ /************************** List all the projects ****************************/ /*****************************************************************************/ static void Prj_GetListProjects (void) { char *PreNonSubQuery; char *HidVisSubQuery; char *DptCodSubQuery; static const char *OrderBySubQuery[Prj_NUM_ORDERS] = { "projects.CreatTime DESC," // Prj_ORDER_START_TIME "projects.ModifTime DESC," "projects.Title", "projects.ModifTime DESC," // Prj_ORDER_END_TIME "projects.CreatTime DESC," "projects.Title", "projects.Title," // Prj_ORDER_TITLE "projects.CreatTime DESC," "projects.ModifTime DESC", "departments.FullName," // Prj_ORDER_DEPARTMENT "projects.CreatTime DESC," "projects.ModifTime DESC," "projects.Title", }; MYSQL_RES *mysql_res = NULL; // Initialized to avoid freeing when not assigned MYSQL_ROW row; unsigned NumUsrsInList; long *LstSelectedUsrCods; char *SubQueryUsrs; unsigned long NumRows = 0; // Initialized to avoid warning unsigned NumPrjsFromDB; unsigned NumPrjsAfterFilter = 0; unsigned NumPrj; struct Prj_Faults Faults; long PrjCod; /***** Get list of projects from database *****/ if (Gbl.Prjs.LstIsRead) Prj_FreeListProjects (); if (Gbl.Prjs.Filter.Assign && // Any selector is on Gbl.Prjs.Filter.Hidden && // Any selector is on Gbl.Prjs.Filter.Faulti) // Any selector is on { /* Assigned subquery */ switch (Gbl.Prjs.Filter.Assign) { case (1 << Prj_ASSIGNED): // Assigned projects if (asprintf (&PreNonSubQuery," AND projects.Assigned='Y'") < 0) Lay_NotEnoughMemoryExit (); break; case (1 << Prj_NONASSIG): // Non-assigned projects if (asprintf (&PreNonSubQuery," AND projects.Assigned='N'") < 0) Lay_NotEnoughMemoryExit (); break; default: // All projects if (asprintf (&PreNonSubQuery,"%s","") < 0) Lay_NotEnoughMemoryExit (); break; } /* Hidden subquery */ switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: // Students can view only visible projects if (asprintf (&HidVisSubQuery," AND projects.Hidden='N'") < 0) Lay_NotEnoughMemoryExit (); break; case Rol_NET: case Rol_TCH: case Rol_SYS_ADM: switch (Gbl.Prjs.Filter.Hidden) { case (1 << Prj_HIDDEN): // Hidden projects if (asprintf (&HidVisSubQuery," AND projects.Hidden='Y'") < 0) Lay_NotEnoughMemoryExit (); break; case (1 << Prj_VISIBL): // Visible projects if (asprintf (&HidVisSubQuery," AND projects.Hidden='N'") < 0) Lay_NotEnoughMemoryExit (); break; default: // All projects if (asprintf (&HidVisSubQuery,"%s","") < 0) Lay_NotEnoughMemoryExit (); break; } break; default: Rol_WrongRoleExit (); break; } /* Department subquery */ if (Gbl.Prjs.Filter.DptCod >= 0) { if (asprintf (&DptCodSubQuery," AND projects.DptCod=%ld", Gbl.Prjs.Filter.DptCod) < 0) Lay_NotEnoughMemoryExit (); } else // Any department { if (asprintf (&DptCodSubQuery,"%s","") < 0) Lay_NotEnoughMemoryExit (); } /* Query */ switch (Gbl.Prjs.Filter.Who) { case Usr_WHO_ME: /* Get list of projects */ switch (Gbl.Prjs.SelectedOrder) { case Prj_ORDER_START_TIME: case Prj_ORDER_END_TIME: case Prj_ORDER_TITLE: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM projects,prj_usr" " WHERE projects.CrsCod=%ld" "%s%s%s" " AND projects.PrjCod=prj_usr.PrjCod" " AND prj_usr.UsrCod=%ld" " GROUP BY projects.PrjCod" // To not repeat projects (DISTINCT can not be used) " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, Gbl.Usrs.Me.UsrDat.UsrCod, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; case Prj_ORDER_DEPARTMENT: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM prj_usr,projects LEFT JOIN departments" " ON projects.DptCod=departments.DptCod" " WHERE projects.CrsCod=%ld" "%s%s%s" " AND projects.PrjCod=prj_usr.PrjCod" " AND prj_usr.UsrCod=%ld" " GROUP BY projects.PrjCod" // To not repeat projects (DISTINCT can not be used) " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, Gbl.Usrs.Me.UsrDat.UsrCod, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; } break; case Usr_WHO_SELECTED: /* Count number of valid users in list of encrypted user codes */ NumUsrsInList = Usr_CountNumUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected); if (NumUsrsInList) { /* Get list of users selected to show their projects */ Usr_GetListSelectedUsrCods (&Gbl.Usrs.Selected,NumUsrsInList,&LstSelectedUsrCods); /* Create subquery string */ Usr_CreateSubqueryUsrCods (LstSelectedUsrCods,NumUsrsInList, &SubQueryUsrs); /* Get list of projects */ switch (Gbl.Prjs.SelectedOrder) { case Prj_ORDER_START_TIME: case Prj_ORDER_END_TIME: case Prj_ORDER_TITLE: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM projects,prj_usr" " WHERE projects.CrsCod=%ld" "%s%s%s" " AND projects.PrjCod=prj_usr.PrjCod" " AND prj_usr.UsrCod IN (%s)" " GROUP BY projects.PrjCod" // To not repeat projects (DISTINCT can not be used) " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, SubQueryUsrs, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; case Prj_ORDER_DEPARTMENT: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM prj_usr,projects LEFT JOIN departments" " ON projects.DptCod=departments.DptCod" " WHERE projects.CrsCod=%ld" "%s%s%s" " AND projects.PrjCod=prj_usr.PrjCod" " AND prj_usr.UsrCod IN (%s)" " GROUP BY projects.PrjCod" // To not repeat projects (DISTINCT can not be used) " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, SubQueryUsrs, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; } /* Free memory for subquery string */ Usr_FreeSubqueryUsrCods (SubQueryUsrs); /* Free list of user codes */ Usr_FreeListSelectedUsrCods (LstSelectedUsrCods); } else NumRows = 0; break; case Usr_WHO_ALL: /* Get list of projects */ switch (Gbl.Prjs.SelectedOrder) { case Prj_ORDER_START_TIME: case Prj_ORDER_END_TIME: case Prj_ORDER_TITLE: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM projects" " WHERE projects.CrsCod=%ld" "%s%s%s" " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; case Prj_ORDER_DEPARTMENT: NumRows = DB_QuerySELECT (&mysql_res,"can not get projects", "SELECT projects.PrjCod" " FROM projects LEFT JOIN departments" " ON projects.DptCod=departments.DptCod" " WHERE projects.CrsCod=%ld" "%s%s%s" " ORDER BY %s", Gbl.Hierarchy.Crs.CrsCod, PreNonSubQuery,HidVisSubQuery,DptCodSubQuery, OrderBySubQuery[Gbl.Prjs.SelectedOrder]); break; } break; default: Lay_ShowErrorAndExit ("Wrong parameter which users."); break; } /* Free allocated memory for subqueries */ free (PreNonSubQuery); free (HidVisSubQuery); free (DptCodSubQuery); if (NumRows) // Projects found... { /***** Initialize number of projects *****/ NumPrjsFromDB = (unsigned) NumRows; /***** Create list of projects *****/ if ((Gbl.Prjs.LstPrjCods = (long *) calloc (NumRows,sizeof (long))) == NULL) Lay_NotEnoughMemoryExit (); /***** Get the projects codes *****/ for (NumPrj = 0; NumPrj < NumPrjsFromDB; NumPrj++) { /* Get next project code */ row = mysql_fetch_row (mysql_res); if ((PrjCod = Str_ConvertStrCodToLongCod (row[0])) < 0) Lay_ShowErrorAndExit ("Error: wrong project code."); /* Filter projects depending on faultiness */ switch (Gbl.Prjs.Filter.Faulti) { case (1 << Prj_FAULTY): // Faulty projects if (Prj_CheckIfPrjIsFaulty (PrjCod,&Faults)) Gbl.Prjs.LstPrjCods[NumPrjsAfterFilter++] = PrjCod; break; case (1 << Prj_FAULTLESS): // Faultless projects if (!Prj_CheckIfPrjIsFaulty (PrjCod,&Faults)) Gbl.Prjs.LstPrjCods[NumPrjsAfterFilter++] = PrjCod; break; default: // All projects Gbl.Prjs.LstPrjCods[NumPrjsAfterFilter++] = PrjCod; break; } } } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } Gbl.Prjs.Num = NumPrjsAfterFilter; Gbl.Prjs.LstIsRead = true; } /*****************************************************************************/ /****************** Check if a project exists in a course ********************/ /*****************************************************************************/ long Prj_GetCourseOfProject (long PrjCod) { MYSQL_RES *mysql_res; MYSQL_ROW row; long CrsCod = -1L; if (PrjCod > 0) { /***** Get course code from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get project course", "SELECT CrsCod FROM projects WHERE PrjCod=%ld", PrjCod)) // Project found... { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get code of the course (row[0]) */ CrsCod = Str_ConvertStrCodToLongCod (row[0]); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } return CrsCod; } /*****************************************************************************/ /********************* Get project data using its code ***********************/ /*****************************************************************************/ void Prj_GetDataOfProjectByCod (struct Project *Prj) { MYSQL_RES *mysql_res; MYSQL_ROW row; long LongNum; Prj_Proposal_t Proposal; if (Prj->PrjCod > 0) { /***** Clear all project data *****/ Prj_ResetProject (Prj); /***** Get data of project *****/ if (DB_QuerySELECT (&mysql_res,"can not get project data", "SELECT PrjCod," // row[ 0] "CrsCod," // row[ 1] "DptCod," // row[ 2] "Locked," // row[ 3] "Hidden," // row[ 4] "Assigned," // row[ 5] "NumStds," // row[ 6] "Proposal," // row[ 7] "UNIX_TIMESTAMP(CreatTime)," // row[ 8] "UNIX_TIMESTAMP(ModifTime)," // row[ 9] "Title," // row[10] "Description," // row[11] "Knowledge," // row[12] "Materials," // row[13] "URL" // row[14] " FROM projects" " WHERE PrjCod=%ld AND CrsCod=%ld", Prj->PrjCod, Gbl.Hierarchy.Crs.CrsCod)) // Project found... { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get code of the project (row[0]) */ Prj->PrjCod = Str_ConvertStrCodToLongCod (row[0]); /* Get code of the course (row[1]) */ Prj->CrsCod = Str_ConvertStrCodToLongCod (row[1]); /* Get code of the department (row[2]) */ Prj->DptCod = Str_ConvertStrCodToLongCod (row[2]); /* Get whether the project is locked or not (row[3]) */ Prj->Locked = (row[3][0] == 'Y') ? Prj_LOCKED : Prj_UNLOCKED; /* Get whether the project is hidden or not (row[4]) */ Prj->Hidden = (row[4][0] == 'Y') ? Prj_HIDDEN : Prj_VISIBL; /* Get if project is assigned or not (row[5]) */ Prj->Assigned = (row[5][0] == 'Y') ? Prj_ASSIGNED : Prj_NONASSIG; /* Get number of students (row[6]) */ LongNum = Str_ConvertStrCodToLongCod (row[6]); Prj->NumStds = (LongNum > 0) ? (unsigned) LongNum : 0; /* Get project status (row[7]) */ Prj->Proposal = Prj_PROPOSAL_DEFAULT; for (Proposal = (Prj_Proposal_t) 0; Proposal <= (Prj_Proposal_t) (Prj_NUM_PROPOSAL_TYPES - 1); Proposal++) if (!strcmp (Prj_Proposal_DB[Proposal],row[7])) { Prj->Proposal = Proposal; break; } /* Get creation date/time (row[8] holds the creation UTC time) */ Prj->CreatTime = Dat_GetUNIXTimeFromStr (row[8]); /* Get modification date/time (row[9] holds the modification UTC time) */ Prj->ModifTime = Dat_GetUNIXTimeFromStr (row[9]); /* Get the title of the project (row[10]) */ Str_Copy (Prj->Title,row[10], Prj_MAX_BYTES_PROJECT_TITLE); /* Get the description of the project (row[11]) */ Str_Copy (Prj->Description,row[11], Cns_MAX_BYTES_TEXT); /* Get the required knowledge for the project (row[12]) */ Str_Copy (Prj->Knowledge,row[12], Cns_MAX_BYTES_TEXT); /* Get the required materials for the project (row[13]) */ Str_Copy (Prj->Materials,row[13], Cns_MAX_BYTES_TEXT); /* Get the URL of the project (row[14]) */ Str_Copy (Prj->URL,row[14], Cns_MAX_BYTES_WWW); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } else { /***** Clear all project data *****/ Prj->PrjCod = -1L; Prj_ResetProject (Prj); } } /*****************************************************************************/ /************************** Clear all project data ***************************/ /*****************************************************************************/ static void Prj_ResetProject (struct Project *Prj) { if (Prj->PrjCod <= 0) // If > 0 ==> keep value Prj->PrjCod = -1L; Prj->CrsCod = -1L; Prj->Locked = Prj_UNLOCKED; Prj->Hidden = Prj_NEW_PRJ_HIDDEN_VISIBL_DEFAULT; Prj->Assigned = Prj_NEW_PRJ_ASSIGNED_NONASSIG_DEFAULT; Prj->NumStds = 1; Prj->Proposal = Prj_PROPOSAL_DEFAULT; Prj->CreatTime = Prj->ModifTime = (time_t) 0; Prj->Title[0] = '\0'; Prj->DptCod = -1L; // Unknown department Prj->Description[0] = '\0'; Prj->Knowledge[0] = '\0'; Prj->Materials[0] = '\0'; Prj->URL[0] = '\0'; } /*****************************************************************************/ /*************************** Free list of projects ***************************/ /*****************************************************************************/ void Prj_FreeListProjects (void) { if (Gbl.Prjs.LstIsRead && Gbl.Prjs.LstPrjCods) { /***** Free memory used by the list of projects *****/ free (Gbl.Prjs.LstPrjCods); Gbl.Prjs.LstPrjCods = NULL; Gbl.Prjs.Num = 0; Gbl.Prjs.LstIsRead = false; } } /*****************************************************************************/ /******************* Write parameter with code of project ********************/ /*****************************************************************************/ void Prj_PutParamPrjCod (long PrjCod) { Par_PutHiddenParamLong (NULL,"PrjCod",PrjCod); } /*****************************************************************************/ /******************** Get parameter with code of project *********************/ /*****************************************************************************/ long Prj_GetParamPrjCod (void) { /***** Get code of project *****/ return Par_GetParToLong ("PrjCod"); } /*****************************************************************************/ /**************** Ask for confirmation of removing a project *****************/ /*****************************************************************************/ void Prj_ReqRemProject (void) { extern const char *Txt_Do_you_really_want_to_remove_the_project_X; extern const char *Txt_Remove_project; struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); if (Prj_CheckIfICanEditProject (&Prj)) { /***** Show question and button to remove the project *****/ Gbl.Prjs.PrjCod = Prj.PrjCod; Ale_ShowAlertAndButton (ActRemPrj,NULL,NULL,Prj_PutCurrentParams, Btn_REMOVE_BUTTON,Txt_Remove_project, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_project_X, Prj.Title); } else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /***************************** Remove a project ******************************/ /*****************************************************************************/ void Prj_RemoveProject (void) { extern const char *Txt_Project_X_removed; struct Project Prj; char PathRelPrj[PATH_MAX + 1]; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); // Inside this function, the course is checked to be the current one if (Prj_CheckIfICanEditProject (&Prj)) { /***** Remove users in project *****/ DB_QueryDELETE ("can not remove project", "DELETE FROM prj_usr USING projects,prj_usr" " WHERE projects.PrjCod=%ld AND projects.CrsCod=%ld" " AND projects.PrjCod=prj_usr.PrjCod", Prj.PrjCod,Gbl.Hierarchy.Crs.CrsCod); /***** Flush cache *****/ Prj_FlushCacheMyRolesInProject (); /***** Remove project *****/ DB_QueryDELETE ("can not remove project", "DELETE FROM projects" " WHERE PrjCod=%ld AND CrsCod=%ld", Prj.PrjCod,Gbl.Hierarchy.Crs.CrsCod); /***** Remove information related to files in project *****/ Brw_RemovePrjFilesFromDB (Prj.PrjCod); /***** Remove directory of the project *****/ snprintf (PathRelPrj,sizeof (PathRelPrj), "%s/%ld/%s/%02u/%ld", Cfg_PATH_CRS_PRIVATE,Prj.CrsCod,Cfg_FOLDER_PRJ, (unsigned) (Prj.PrjCod % 100),Prj.PrjCod); Fil_RemoveTree (PathRelPrj); /***** Write message to show the change made *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_Project_X_removed, Prj.Title); } else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /****************************** Hide a project *******************************/ /*****************************************************************************/ void Prj_HideProject (void) { struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); if (Prj_CheckIfICanEditProject (&Prj)) /***** Hide project *****/ DB_QueryUPDATE ("can not hide project", "UPDATE projects SET Hidden='Y'" " WHERE PrjCod=%ld AND CrsCod=%ld", Prj.PrjCod,Gbl.Hierarchy.Crs.CrsCod); else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /****************************** Unhide a project *****************************/ /*****************************************************************************/ void Prj_UnhideProject (void) { struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); if (Prj_CheckIfICanEditProject (&Prj)) /***** Show project *****/ DB_QueryUPDATE ("can not show project", "UPDATE projects SET Hidden='N'" " WHERE PrjCod=%ld AND CrsCod=%ld", Prj.PrjCod,Gbl.Hierarchy.Crs.CrsCod); else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /********************* Put a form to create/edit project *********************/ /*****************************************************************************/ void Prj_RequestCreatePrj (void) { /***** Form to create project *****/ Prj_RequestCreatOrEditPrj (-1L); // It's a new, non existing, project } void Prj_RequestEditPrj (void) { long PrjCod; /***** Get project code *****/ if ((PrjCod = Prj_GetParamPrjCod ()) == -1L) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Form to edit project *****/ Prj_RequestCreatOrEditPrj (PrjCod); } static void Prj_RequestCreatOrEditPrj (long PrjCod) { struct Project Prj; bool ItsANewProject; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); ItsANewProject = ((Prj.PrjCod = PrjCod) < 0); /***** Get from the database the data of the project *****/ if (ItsANewProject) { /* Initialize to empty project */ Prj_ResetProject (&Prj); Prj.CreatTime = Gbl.StartExecutionTimeUTC; Prj.ModifTime = Gbl.StartExecutionTimeUTC; Prj.DptCod = Gbl.Usrs.Me.UsrDat.Tch.DptCod; // Default: my department } else /* Get data of the project from database */ Prj_GetDataOfProjectByCod (&Prj); /***** Put form to edit project *****/ Prj_PutFormProject (&Prj,ItsANewProject); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); /***** Show projects again *****/ Prj_ShowProjects (); } static void Prj_PutFormProject (struct Project *Prj,bool ItsANewProject) { extern const char *Hlp_ASSESSMENT_Projects_new_project; extern const char *Hlp_ASSESSMENT_Projects_edit_project; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_New_project; extern const char *Txt_Edit_project; extern const char *Txt_Data; extern const char *Txt_Title; extern const char *Txt_Department; extern const char *Txt_Another_department; extern const char *Txt_Assigned_QUESTION; extern const char *Txt_Number_of_students; extern const char *Txt_Proposal; extern const char *Txt_PROJECT_STATUS[Prj_NUM_PROPOSAL_TYPES]; extern const char *Txt_Description; extern const char *Txt_Required_knowledge; extern const char *Txt_Required_materials; extern const char *Txt_URL; extern const char *Txt_No; extern const char *Txt_Yes; extern const char *Txt_Create_project; extern const char *Txt_Save_changes; extern const char *Txt_Members; Prj_Proposal_t Proposal; unsigned ProposalUnsigned; unsigned NumRoleToShow; /***** Start project box *****/ if (ItsANewProject) { Gbl.Prjs.PrjCod = -1L; Box_BoxBegin (NULL,Txt_New_project,NULL, Hlp_ASSESSMENT_Projects_new_project,Box_NOT_CLOSABLE); } else { Gbl.Prjs.PrjCod = Prj->PrjCod; Box_BoxBegin (NULL, Prj->Title[0] ? Prj->Title : Txt_Edit_project, NULL, Hlp_ASSESSMENT_Projects_edit_project,Box_NOT_CLOSABLE); } /***** 1. Project members *****/ if (!ItsANewProject) // Existing project { Box_StartBoxTable (NULL,Txt_Members,NULL, NULL,Box_NOT_CLOSABLE,2); for (NumRoleToShow = 0; NumRoleToShow < Brw_NUM_ROLES_TO_SHOW; NumRoleToShow++) Prj_ShowOneProjectMembersWithARole (Prj,Prj_EDIT_ONE_PROJECT, Prj_RolesToShow[NumRoleToShow]); Box_EndBoxTable (); } /***** 2. Project data *****/ /* Start data form */ Frm_StartForm (ItsANewProject ? ActNewPrj : ActChgPrj); Prj_PutCurrentParams (); /* Begin box and table */ Box_StartBoxTable (NULL,Txt_Data,NULL, NULL,Box_NOT_CLOSABLE,2); /* Project title */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"Title\" class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Title); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); HTM_INPUT_TEXT ("Title",Prj_MAX_CHARS_PROJECT_TITLE,Prj->Title,false, "id=\"Title\" size=\"45\" required=\"required\""); HTM_TD_End (); HTM_TR_End (); /* Department */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"%s\" class=\"%s\"", Dpt_PARAM_DPT_COD_NAME, The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Department); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); Dpt_WriteSelectorDepartment (Gbl.Hierarchy.Ins.InsCod, // Departments in current institution Prj->DptCod, // Selected department "PRJ_INPUT", // Selector class 0, // First option Txt_Another_department, // Text when no department selected false); // Don't submit on change HTM_TD_End (); HTM_TR_End (); /* Assigned? */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Assigned_QUESTION); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); HTM_SELECT_Begin (false, "name=\"Assigned\""); HTM_OPTION (HTM_Type_STRING,"Y",Prj->Assigned == Prj_ASSIGNED,false, "%s",Txt_Yes); HTM_OPTION (HTM_Type_STRING,"N",Prj->Assigned == Prj_NONASSIG,false, "%s",Txt_No); HTM_SELECT_End (); HTM_TD_End (); HTM_TR_End (); /* Number of students */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Number_of_students); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); HTM_INPUT_NUMBER ("NumStds",(long) 0,(long) UINT_MAX,(long) Prj->NumStds,false, NULL); HTM_TD_End (); HTM_TR_End (); /* Proposal */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RM\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Proposal); HTM_TD_End (); HTM_TD_Begin ("class=\"LM\""); HTM_SELECT_Begin (false, "name=\"Proposal\""); for (Proposal = (Prj_Proposal_t) 0; Proposal <= (Prj_Proposal_t) (Prj_NUM_PROPOSAL_TYPES - 1); Proposal++) { ProposalUnsigned = (unsigned) Proposal; HTM_OPTION (HTM_Type_UNSIGNED,&ProposalUnsigned, Prj->Proposal == Proposal,false, "%s",Txt_PROJECT_STATUS[Proposal]); } HTM_SELECT_End (); HTM_TD_End (); HTM_TR_End (); /* Description of the project */ Prj_EditOneProjectTxtArea ("Description",Txt_Description, Prj->Description,12, true); // Required /* Required knowledge to carry out the project */ Prj_EditOneProjectTxtArea ("Knowledge",Txt_Required_knowledge, Prj->Knowledge,4, false); // Not required /* Required materials to carry out the project */ Prj_EditOneProjectTxtArea ("Materials",Txt_Required_materials, Prj->Materials,4, false); // Not required /* URL for additional info */ HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RM\""); HTM_LABEL_Begin ("for=\"WWW\" class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_URL); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"DAT LM\""); HTM_INPUT_URL ("URL",Prj->URL,false, "size=\"45\""); HTM_TD_End (); HTM_TR_End (); /* End table, send button and end box */ if (ItsANewProject) Box_EndBoxTableWithButton (Btn_CREATE_BUTTON,Txt_Create_project); else Box_EndBoxTableWithButton (Btn_CONFIRM_BUTTON,Txt_Save_changes); /* End data form */ Frm_EndForm (); /***** End project box *****/ Box_BoxEnd (); } /*****************************************************************************/ /************************ Show text row about a project **********************/ /*****************************************************************************/ static void Prj_EditOneProjectTxtArea (const char *Id, const char *Label,char *TxtField, unsigned NumRows,bool Required) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"RT\""); HTM_LABEL_Begin ("for=\"%s\" class=\"%s\"",Id,The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Label); HTM_LABEL_End (); HTM_TD_End (); HTM_TD_Begin ("class=\"LT\""); HTM_TEXTAREA_Begin ("id=\"%s\" name=\"%s\" cols=\"60\" rows=\"%u\"%s", Id,Id,NumRows,Required ? " required=\"required\"" : ""); HTM_Txt (TxtField); HTM_TEXTAREA_End (); HTM_TD_End (); HTM_TR_End (); } /*****************************************************************************/ /*** Allocate memory for those parameters of a project with a lot of text ****/ /*****************************************************************************/ void Prj_AllocMemProject (struct Project *Prj) { if ((Prj->Description = (char *) malloc (Cns_MAX_BYTES_TEXT + 1)) == NULL) Lay_NotEnoughMemoryExit (); if ((Prj->Knowledge = (char *) malloc (Cns_MAX_BYTES_TEXT + 1)) == NULL) Lay_NotEnoughMemoryExit (); if ((Prj->Materials = (char *) malloc (Cns_MAX_BYTES_TEXT + 1)) == NULL) Lay_NotEnoughMemoryExit (); } /*****************************************************************************/ /****** Free memory of those parameters of a project with a lot of text ******/ /*****************************************************************************/ void Prj_FreeMemProject (struct Project *Prj) { if (Prj->Description) { free (Prj->Description); Prj->Description = NULL; } if (Prj->Knowledge) { free (Prj->Knowledge); Prj->Knowledge = NULL; } if (Prj->Materials) { free (Prj->Materials); Prj->Materials = NULL; } } /*****************************************************************************/ /******************** Receive form to create a new project *******************/ /*****************************************************************************/ void Prj_RecFormProject (void) { extern const char *Txt_You_must_specify_the_title_of_the_project; extern const char *Txt_Created_new_project_X; extern const char *Txt_The_project_has_been_modified; struct Project Prj; // Project data received from form bool ItsANewProject; bool ICanEditProject; bool NewProjectIsCorrect = true; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); ItsANewProject = ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0); if (ItsANewProject) { /* Reset project data */ Prj_ResetProject (&Prj); ICanEditProject = true; } else { /* Get data of the project from database */ Prj_GetDataOfProjectByCod (&Prj); ICanEditProject = Prj_CheckIfICanEditProject (&Prj); } if (ICanEditProject) { /* Get project title */ Par_GetParToText ("Title",Prj.Title,Prj_MAX_BYTES_PROJECT_TITLE); /* Get department */ Prj.DptCod = Par_GetParToLong (Dpt_PARAM_DPT_COD_NAME); /* Get whether the project is assigned */ Prj.Assigned = (Par_GetParToBool ("Assigned")) ? Prj_ASSIGNED : Prj_NONASSIG; /* Get number of students */ Prj.NumStds = (unsigned) Par_GetParToUnsignedLong ("NumStds", 0, UINT_MAX, 1); /* Get status */ Prj.Proposal = (Prj_Proposal_t) Par_GetParToUnsignedLong ("Proposal", 0, Prj_NUM_PROPOSAL_TYPES - 1, (unsigned long) Prj_PROPOSAL_DEFAULT); /* Get project description, required knowledge and required materials */ Par_GetParToHTML ("Description",Prj.Description,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) Par_GetParToHTML ("Knowledge" ,Prj.Knowledge ,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) Par_GetParToHTML ("Materials" ,Prj.Materials ,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) /* Get degree WWW */ Par_GetParToText ("URL",Prj.URL,Cns_MAX_BYTES_WWW); /***** Check if title is correct *****/ if (!Prj.Title[0]) // If there is not a project title { NewProjectIsCorrect = false; Ale_ShowAlert (Ale_WARNING,Txt_You_must_specify_the_title_of_the_project); } /***** Create a new project or update an existing one *****/ if (NewProjectIsCorrect) { if (ItsANewProject) { /* Create project */ Prj_CreateProject (&Prj); // Add new project to database /* Write success message */ Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_project_X, Prj.Title); } else if (NewProjectIsCorrect) { /* Update project */ Prj_UpdateProject (&Prj); /* Write success message */ Ale_ShowAlert (Ale_SUCCESS,Txt_The_project_has_been_modified); } } else Prj_PutFormProject (&Prj,ItsANewProject); /***** Show again form to edit project *****/ Prj_RequestCreatOrEditPrj (Prj.PrjCod); } else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); } /*****************************************************************************/ /************************** Create a new project *****************************/ /*****************************************************************************/ static void Prj_CreateProject (struct Project *Prj) { /***** Set dates to now *****/ Prj->CreatTime = Prj->ModifTime = Gbl.StartExecutionTimeUTC; /***** Create a new project *****/ Prj->PrjCod = DB_QueryINSERTandReturnCode ("can not create new project", "INSERT INTO projects" " (CrsCod,DptCod,Hidden,Assigned,NumStds,Proposal," "CreatTime,ModifTime," "Title,Description,Knowledge,Materials,URL)" " VALUES" " (%ld,%ld,'%c','%c',%u,'%s'," "FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld)," "'%s','%s','%s','%s','%s')", Gbl.Hierarchy.Crs.CrsCod, Prj->DptCod, Prj->Hidden == Prj_HIDDEN ? 'Y' : 'N', Prj->Assigned == Prj_ASSIGNED ? 'Y' : 'N', Prj->NumStds, Prj_Proposal_DB[Prj->Proposal], Prj->CreatTime, Prj->ModifTime, Prj->Title, Prj->Description, Prj->Knowledge, Prj->Materials, Prj->URL); /***** Insert creator as first tutor *****/ DB_QueryINSERT ("can not add tutor", "INSERT INTO prj_usr" " (PrjCod,RoleInProject,UsrCod)" " VALUES" " (%ld,%u,%ld)", Prj->PrjCod, (unsigned) Prj_ROLE_TUT, Gbl.Usrs.Me.UsrDat.UsrCod); /***** Flush cache *****/ Prj_FlushCacheMyRolesInProject (); } /*****************************************************************************/ /*********************** Update an existing project **************************/ /*****************************************************************************/ static void Prj_UpdateProject (struct Project *Prj) { /***** Adjust date of last edition to now *****/ Prj->ModifTime = Gbl.StartExecutionTimeUTC; /***** Update the data of the project *****/ DB_QueryUPDATE ("can not update project", "UPDATE projects" " SET DptCod=%ld," "Hidden='%c'," "Assigned='%c'," "NumStds=%u," "Proposal='%s'," "ModifTime=FROM_UNIXTIME(%ld)," "Title='%s'," "Description='%s'," "Knowledge='%s'," "Materials='%s'," "URL='%s'" " WHERE PrjCod=%ld AND CrsCod=%ld", Prj->DptCod, Prj->Hidden == Prj_HIDDEN ? 'Y' : 'N', Prj->Assigned == Prj_ASSIGNED ? 'Y' : 'N', Prj->NumStds, Prj_Proposal_DB[Prj->Proposal], Prj->ModifTime, Prj->Title, Prj->Description, Prj->Knowledge, Prj->Materials, Prj->URL, Prj->PrjCod,Gbl.Hierarchy.Crs.CrsCod); } /*****************************************************************************/ /************************ Can I configure all projects? **********************/ /*****************************************************************************/ static bool Prj_CheckIfICanConfigAllProjects (void) { switch (Gbl.Usrs.Me.Role.Logged) { case Rol_TCH: case Rol_SYS_ADM: return true; default: return false; } } /*****************************************************************************/ /********************** Configuration of all projects ************************/ /*****************************************************************************/ void Prj_ShowFormConfig (void) { extern const char *Hlp_ASSESSMENT_Projects; extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Configure_projects; extern const char *Txt_Editable; extern const char *Txt_Editable_by_non_editing_teachers; extern const char *Txt_Save_changes; /***** Read projects configuration from database *****/ Prj_GetConfigPrjFromDB (); /***** Begin box *****/ Box_BoxBegin (NULL,Txt_Configure_projects,Prj_PutIconsListProjects, Hlp_ASSESSMENT_Projects,Box_NOT_CLOSABLE); /***** Begin form *****/ Frm_StartForm (ActRcvCfgPrj); /***** Projects are editable by non-editing teachers? *****/ HTM_TABLE_BeginCenterPadding (2); HTM_TR_Begin (NULL); HTM_TD_Begin ("class=\"%s RT\"",The_ClassFormInBox[Gbl.Prefs.Theme]); HTM_TxtF ("%s:",Txt_Editable); HTM_TD_End (); HTM_TD_Begin ("class=\"LT\""); HTM_LABEL_Begin (NULL); HTM_INPUT_CHECKBOX ("Editable",false, "id=\"Editable\" value=\"Y\"%s", Gbl.Prjs.Config.Editable ? " checked=\"checked\"" : ""); HTM_Txt (Txt_Editable_by_non_editing_teachers); HTM_LABEL_End (); HTM_TD_End (); HTM_TR_End (); HTM_TABLE_End (); /***** Send button *****/ Btn_PutConfirmButton (Txt_Save_changes); /***** End form *****/ Frm_EndForm (); /***** End box *****/ Box_BoxEnd (); } /*****************************************************************************/ /************** Get configuration of projects for current course *************/ /*****************************************************************************/ static void Prj_GetConfigPrjFromDB (void) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; /***** Get configuration of projects for current course from database *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get configuration of test", "SELECT Editable" // row[0] " FROM prj_config WHERE CrsCod=%ld", Gbl.Hierarchy.Crs.CrsCod); if (NumRows == 0) Gbl.Prjs.Config.Editable = Prj_EDITABLE_DEFAULT; else // NumRows == 1 { /***** Get configuration *****/ row = mysql_fetch_row (mysql_res); Prj_GetConfigFromRow (row); } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ /************ Get configuration values from a database table row *************/ /*****************************************************************************/ static void Prj_GetConfigFromRow (MYSQL_ROW row) { /***** Get whether project are visible via plugins or not *****/ Gbl.Prjs.Config.Editable = (row[0][0] == 'Y'); } /*****************************************************************************/ /************ Receive configuration of projects for current course ***********/ /*****************************************************************************/ void Prj_ReceiveConfigPrj (void) { extern const char *Txt_The_configuration_of_the_projects_has_been_updated; /***** Get whether projects are editable by non-editing teachers or not *****/ Gbl.Prjs.Config.Editable = Prj_GetEditableFromForm (); /***** Update database *****/ DB_QueryREPLACE ("can not save configuration of projects", "REPLACE INTO prj_config" " (CrsCod,Editable)" " VALUES" " (%ld,'%c')", Gbl.Hierarchy.Crs.CrsCod, Gbl.Prjs.Config.Editable ? 'Y' : 'N'); /***** Show confirmation message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_The_configuration_of_the_projects_has_been_updated); /***** Show again the form to configure projects *****/ Prj_ShowFormConfig (); } /*****************************************************************************/ /****** Get if projects are editable by non-editing teachers from form *******/ /*****************************************************************************/ static bool Prj_GetEditableFromForm (void) { return Par_GetParToBool ("Editable"); } /*****************************************************************************/ /****** Put icons to request locking/unlocking edition of all projects *******/ /*****************************************************************************/ static void Prj_PutIconsToLockUnlockAllProjects (void) { extern const char *Txt_Lock_editing; extern const char *Txt_Unlock_editing; /***** Put icon to lock all projects *****/ Lay_PutContextualLinkOnlyIcon (ActReqLckAllPrj,NULL,Prj_PutCurrentParams, "lock.svg", Txt_Lock_editing); /***** Put icon to unlock all projects *****/ Lay_PutContextualLinkOnlyIcon (ActReqUnlAllPrj,NULL,Prj_PutCurrentParams, "unlock.svg", Txt_Unlock_editing); } /*****************************************************************************/ /********** Request locking/unlocking edition of selected projects ***********/ /*****************************************************************************/ void Prj_ReqLockSelectedPrjsEdition (void) { extern const char *Txt_Lock_editing; extern const char *Txt_Do_you_want_to_lock_the_editing_of_the_X_selected_projects; extern const char *Txt_No_projects; /***** Get parameters *****/ Prj_GetParams (); /***** Show question and button to lock all selected projects *****/ if (Prj_CheckIfICanConfigAllProjects ()) { /* Get list of projects */ Prj_GetListProjects (); /* Show question and button */ if (Gbl.Prjs.Num) Ale_ShowAlertAndButton (ActLckAllPrj,NULL,NULL,Prj_PutCurrentParams, Btn_REMOVE_BUTTON,Txt_Lock_editing, Ale_QUESTION,Txt_Do_you_want_to_lock_the_editing_of_the_X_selected_projects, Gbl.Prjs.Num); else // No projects found Ale_ShowAlert (Ale_INFO,Txt_No_projects); /* Free list of projects */ Prj_FreeListProjects (); } else Lay_NoPermissionExit (); /***** Show projects again *****/ Prj_ShowProjects (); } void Prj_ReqUnloSelectedPrjsEdition (void) { extern const char *Txt_Unlock_editing; extern const char *Txt_Do_you_want_to_unlock_the_editing_of_the_X_selected_projects; extern const char *Txt_No_projects; /***** Get parameters *****/ Prj_GetParams (); /***** Show question and button to unlock all selected projects *****/ if (Prj_CheckIfICanConfigAllProjects ()) { /* Get list of projects */ Prj_GetListProjects (); /* Show question and button */ if (Gbl.Prjs.Num) Ale_ShowAlertAndButton (ActUnlAllPrj,NULL,NULL,Prj_PutCurrentParams, Btn_CREATE_BUTTON,Txt_Unlock_editing, Ale_QUESTION,Txt_Do_you_want_to_unlock_the_editing_of_the_X_selected_projects, Gbl.Prjs.Num); else // No projects found Ale_ShowAlert (Ale_INFO,Txt_No_projects); /* Free list of projects */ Prj_FreeListProjects (); } else Lay_NoPermissionExit (); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /***************** Lock/unlock edition of selected projects ******************/ /*****************************************************************************/ void Prj_LockSelectedPrjsEdition (void) { extern const char *Txt_No_projects; unsigned NumPrj; /***** Get parameters *****/ Prj_GetParams (); /***** Lock all selected projects *****/ if (Prj_CheckIfICanConfigAllProjects ()) { /* Get list of projects */ Prj_GetListProjects (); /* Lock projects */ if (Gbl.Prjs.Num) for (NumPrj = 0; NumPrj < Gbl.Prjs.Num; NumPrj++) Prj_LockProjectEditionInDB (Gbl.Prjs.LstPrjCods[NumPrj]); else // No projects found Ale_ShowAlert (Ale_INFO,Txt_No_projects); /* Free list of projects */ Prj_FreeListProjects (); } else Lay_NoPermissionExit (); /***** Show projects again *****/ Prj_ShowProjects (); } void Prj_UnloSelectedPrjsEdition (void) { extern const char *Txt_No_projects; unsigned NumPrj; /***** Get parameters *****/ Prj_GetParams (); /***** Unlock all selected projects *****/ if (Prj_CheckIfICanConfigAllProjects ()) { /* Get list of projects */ Prj_GetListProjects (); /* Unlock projects */ if (Gbl.Prjs.Num) for (NumPrj = 0; NumPrj < Gbl.Prjs.Num; NumPrj++) Prj_UnlockProjectEditionInDB (Gbl.Prjs.LstPrjCods[NumPrj]); else // No projects found Ale_ShowAlert (Ale_INFO,Txt_No_projects); /* Free list of projects */ Prj_FreeListProjects (); } else Lay_NoPermissionExit (); /***** Show projects again *****/ Prj_ShowProjects (); } /*****************************************************************************/ /******************** Form to lock/unlock project edition ********************/ /*****************************************************************************/ static void Prj_FormLockUnlock (const struct Project *Prj) { extern const char *Txt_LOCKED_UNLOCKED[Prj_NUM_LOCKED_UNLOCKED]; char *OnSubmit; /* +---------------------+ | div (parent of form)| | +-----------------+ | | | this form | | | | +-------------+ | | | | | icon | | | | | +-------------+ | | | +-----------------+ | +---------------------+ */ /***** Form and icon to lock/unlock project edition *****/ /* Form with icon */ if (asprintf (&OnSubmit,"updateDivLockUnlockProject(this," "'act=%ld&ses=%s&PrjCod=%ld');" " return false;", // return false is necessary to not submit form Act_GetActCod (Prj_LockActions[Prj->Locked]), Gbl.Session.Id, Prj->PrjCod) < 0) Lay_NotEnoughMemoryExit (); Frm_StartFormOnSubmit (ActUnk,OnSubmit); Ico_PutIconLink (Prj_LockIcons[Prj->Locked],Txt_LOCKED_UNLOCKED[Prj->Locked]); Frm_EndForm (); /* Free allocated memory for subquery */ free (OnSubmit); } /*****************************************************************************/ /********* Put icon to inform about locked/unlocked project edition **********/ /*****************************************************************************/ static void Prj_PutIconOffLockedUnlocked (const struct Project *Prj) { extern const char *Txt_LOCKED_UNLOCKED[Prj_NUM_LOCKED_UNLOCKED]; /***** Icon to inform about locked/unlocked project edition *****/ Ico_PutIconOff (Prj_LockIcons[Prj->Locked],Txt_LOCKED_UNLOCKED[Prj->Locked]); } /*****************************************************************************/ /************************** Lock edition of a project ************************/ /*****************************************************************************/ void Prj_LockProjectEdition (void) { struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); if (Prj_CheckIfICanEditProject (&Prj)) { /***** Lock project edition *****/ Prj_LockProjectEditionInDB (Prj.PrjCod); Prj.Locked = Prj_LOCKED; /***** Show updated form and icon *****/ Prj_FormLockUnlock (&Prj); } else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); } static void Prj_LockProjectEditionInDB (long PrjCod) { DB_QueryUPDATE ("can not lock project edition", "UPDATE projects SET Locked='Y'" " WHERE PrjCod=%ld AND CrsCod=%ld", PrjCod,Gbl.Hierarchy.Crs.CrsCod); } /*****************************************************************************/ /************************* Unlock edition of a project ***********************/ /*****************************************************************************/ void Prj_UnloProjectEdition (void) { struct Project Prj; /***** Allocate memory for the project *****/ Prj_AllocMemProject (&Prj); /***** Get parameters *****/ Prj_GetParams (); if ((Prj.PrjCod = Prj_GetParamPrjCod ()) < 0) Lay_ShowErrorAndExit ("Code of project is missing."); /***** Get data of the project from database *****/ Prj_GetDataOfProjectByCod (&Prj); if (Prj_CheckIfICanEditProject (&Prj)) { /***** Unlock project edition *****/ Prj_UnlockProjectEditionInDB (Prj.PrjCod); Prj.Locked = Prj_UNLOCKED; /***** Show updated form and icon *****/ Prj_FormLockUnlock (&Prj); } else Lay_NoPermissionExit (); /***** Free memory of the project *****/ Prj_FreeMemProject (&Prj); } static void Prj_UnlockProjectEditionInDB (long PrjCod) { DB_QueryUPDATE ("can not lock project edition", "UPDATE projects SET Locked='N'" " WHERE PrjCod=%ld AND CrsCod=%ld", PrjCod,Gbl.Hierarchy.Crs.CrsCod); } /*****************************************************************************/ /******************** Remove all the projects in a course ********************/ /*****************************************************************************/ void Prj_RemoveCrsProjects (long CrsCod) { /***** Remove users in projects of the course *****/ DB_QueryDELETE ("can not remove all the projects of a course", "DELETE FROM prj_usr USING projects,prj_usr" " WHERE projects.CrsCod=%ld" " AND projects.PrjCod=prj_usr.PrjCod", CrsCod); /***** Flush cache *****/ Prj_FlushCacheMyRolesInProject (); /***** Remove configuration of projects in the course *****/ DB_QueryDELETE ("can not remove configuration of projects of a course", "DELETE FROM prj_config WHERE CrsCod=%ld", CrsCod); /***** Remove projects *****/ DB_QueryDELETE ("can not remove all the projects of a course", "DELETE FROM projects WHERE CrsCod=%ld", CrsCod); } /*****************************************************************************/ /******************* Remove user from all his/her projects *******************/ /*****************************************************************************/ void Prj_RemoveUsrFromProjects (long UsrCod) { bool ItsMe; /***** Remove user from projects *****/ DB_QueryDELETE ("can not remove user from projects", "DELETE FROM prj_usr WHERE UsrCod=%ld", UsrCod); /***** Flush cache *****/ ItsMe = Usr_ItsMe (UsrCod); if (ItsMe) Prj_FlushCacheMyRolesInProject (); } /*****************************************************************************/ /******************** Get number of courses with projects ********************/ /*****************************************************************************/ // Returns the number of courses with projects // in this location (all the platform, current degree or current course) unsigned Prj_GetNumCoursesWithProjects (Hie_Level_t Scope) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumCourses; /***** Get number of courses with projects from database *****/ switch (Scope) { case Hie_SYS: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT CrsCod)" " FROM projects" " WHERE CrsCod>0"); break; case Hie_CTY: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT projects.CrsCod)" " FROM institutions,centres,degrees,courses,projects" " WHERE institutions.CtyCod=%ld" " AND institutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Cty.CtyCod); break; case Hie_INS: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT projects.CrsCod)" " FROM centres,degrees,courses,projects" " WHERE centres.InsCod=%ld" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Ins.InsCod); break; case Hie_CTR: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT projects.CrsCod)" " FROM degrees,courses,projects" " WHERE degrees.CtrCod=%ld" " AND degrees.DegCod=courses.DegCod" " AND courses.Status=0" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Ctr.CtrCod); break; case Hie_DEG: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT projects.CrsCod)" " FROM courses,projects" " WHERE courses.DegCod=%ld" " AND courses.Status=0" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Deg.DegCod); break; case Hie_CRS: DB_QuerySELECT (&mysql_res,"can not get number of courses with projects", "SELECT COUNT(DISTINCT CrsCod)" " FROM projects" " WHERE CrsCod=%ld", Gbl.Hierarchy.Crs.CrsCod); break; default: Lay_WrongScopeExit (); break; } /***** Get number of courses *****/ row = mysql_fetch_row (mysql_res); if (sscanf (row[0],"%u",&NumCourses) != 1) Lay_ShowErrorAndExit ("Error when getting number of courses with projects."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return NumCourses; } /*****************************************************************************/ /************************** Get number of projects ***************************/ /*****************************************************************************/ // Returns the number of projects in this location unsigned Prj_GetNumProjects (Hie_Level_t Scope) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned NumProjects; /***** Get number of projects from database *****/ switch (Scope) { case Hie_SYS: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM projects" " WHERE CrsCod>0"); break; case Hie_CTY: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM institutions,centres,degrees,courses,projects" " WHERE institutions.CtyCod=%ld" " AND institutions.InsCod=centres.InsCod" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Cty.CtyCod); break; case Hie_INS: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM centres,degrees,courses,projects" " WHERE centres.InsCod=%ld" " AND centres.CtrCod=degrees.CtrCod" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Ins.InsCod); break; case Hie_CTR: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM degrees,courses,projects" " WHERE degrees.CtrCod=%ld" " AND degrees.DegCod=courses.DegCod" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Ctr.CtrCod); break; case Hie_DEG: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM courses,projects" " WHERE courses.DegCod=%ld" " AND courses.CrsCod=projects.CrsCod", Gbl.Hierarchy.Deg.DegCod); break; case Hie_CRS: DB_QuerySELECT (&mysql_res,"can not get number of projects", "SELECT COUNT(*)" " FROM projects" " WHERE CrsCod=%ld", Gbl.Hierarchy.Crs.CrsCod); break; default: Lay_WrongScopeExit (); break; } /***** Get number of projects *****/ row = mysql_fetch_row (mysql_res); if (sscanf (row[0],"%u",&NumProjects) != 1) Lay_ShowErrorAndExit ("Error when getting number of projects."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return NumProjects; }