From c9b9f480cc92b34968505014833d2f18536f6d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Tue, 3 Mar 2020 00:56:22 +0100 Subject: [PATCH] Version19.140 --- css/swad19.136.css | 2 +- swad_action.c | 10 +- swad_action.h | 2 +- swad_changelog.h | 3 +- swad_date.c | 2 +- swad_date.h | 2 +- swad_program.c | 480 ++++++++++++++++++++++++++++++--------------- swad_program.h | 9 +- swad_text_action.c | 2 +- 9 files changed, 333 insertions(+), 179 deletions(-) diff --git a/css/swad19.136.css b/css/swad19.136.css index bc0e0f7da..4ee383691 100644 --- a/css/swad19.136.css +++ b/css/swad19.136.css @@ -1588,7 +1588,7 @@ a:hover img.CENTRE_PHOTO_SHOW .PRG_COL1 { box-sizing:border-box; - width:64px; + width:86px; } /********************************** Notice ***********************************/ diff --git a/swad_action.c b/swad_action.c index b240e8a5e..f7329f859 100644 --- a/swad_action.c +++ b/swad_action.c @@ -398,10 +398,10 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] = [ActChgCrsYeaCfg ] = {1573,-1,TabUnk,ActSeeCrsInf ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,CrsCfg_ChangeCrsYear ,CrsCfg_ContEditAfterChgCrs ,NULL}, [ActEdiCrsInf ] = { 848,-1,TabUnk,ActSeeCrsInf ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Inf_FormsToSelSendInfo ,NULL}, - [ActFrmNewPrgItm ] = {1822,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RequestCreatOrEditPrgItem ,NULL}, - [ActEdiOnePrgItm ] = {1823,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RequestCreatOrEditPrgItem ,NULL}, - [ActNewPrgItm ] = {1825,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RecFormPrgItem ,NULL}, - [ActChgPrgItm ] = {1826,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RecFormPrgItem ,NULL}, + [ActFrmNewPrgItm ] = {1822,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RequestCreatePrgItem ,NULL}, + [ActFrmChgPrgItm ] = {1823,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RequestChangePrgItem ,NULL}, + [ActNewPrgItm ] = {1825,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RecFormNewPrgItem ,NULL}, + [ActChgPrgItm ] = {1826,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RecFormChgPrgItem ,NULL}, [ActReqRemPrgItm ] = {1827,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_ReqRemPrgItem ,NULL}, [ActRemPrgItm ] = {1828,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_RemovePrgItem ,NULL}, [ActHidPrgItm ] = {1829,-1,TabUnk,ActSeePrg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prg_HidePrgItem ,NULL}, @@ -3552,7 +3552,7 @@ Act_Action_t Act_FromActCodToAction[1 + Act_MAX_ACTION_COD] = // Do not reuse un ActMtn, // #1820 ActSeePrg, // #1821 ActFrmNewPrgItm, // #1822 - ActEdiOnePrgItm, // #1823 + ActFrmChgPrgItm, // #1823 -1, // #1824 ActNewPrgItm, // #1825 ActChgPrgItm, // #1826 diff --git a/swad_action.h b/swad_action.h index 834363111..0944c3ccb 100644 --- a/swad_action.h +++ b/swad_action.h @@ -385,7 +385,7 @@ typedef signed int Act_Action_t; // Must be a signed type, because -1 is used to #define ActChgCrsYeaCfg (ActChgCrsSta + 14) #define ActEdiCrsInf (ActChgCrsSta + 15) #define ActFrmNewPrgItm (ActChgCrsSta + 16) -#define ActEdiOnePrgItm (ActChgCrsSta + 17) +#define ActFrmChgPrgItm (ActChgCrsSta + 17) #define ActNewPrgItm (ActChgCrsSta + 18) #define ActChgPrgItm (ActChgCrsSta + 19) #define ActReqRemPrgItm (ActChgCrsSta + 20) diff --git a/swad_changelog.h b/swad_changelog.h index 41556ced5..d5b665dd3 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -497,7 +497,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.139 (2020-03-02)" +#define Log_PLATFORM_VERSION "SWAD 19.140 (2020-03-03)" #define CSS_FILE "swad19.136.css" #define JS_FILE "swad19.91.1.js" /* @@ -523,6 +523,7 @@ Param // TODO: Miguel Damas: por defecto, marcar "Permitir que los profesores..." en los test (que ya esté marcado en lugar de desmarcado) // TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo + Version 19.140: Mar 03, 2020 New action to add a new item inside a item inside another one. (282375 lines) Version 19.139: Mar 02, 2020 Changes in course program. (282252 lines) Version 19.138.1: Feb 29, 2020 Fixed bugs in course program. (282252 lines) Version 19.138: Feb 29, 2020 Move subtrees up and down in course program. (282230 lines) diff --git a/swad_date.c b/swad_date.c index 21d582ee4..010ff481c 100644 --- a/swad_date.c +++ b/swad_date.c @@ -480,7 +480,7 @@ void Dat_PutFormStartEndClientLocalDateTimesWithYesterdayToday (const Dat_SetHMS /************* Show forms to enter initial and ending date-times *************/ /*****************************************************************************/ -void Dat_PutFormStartEndClientLocalDateTimes (time_t TimeUTC[2], +void Dat_PutFormStartEndClientLocalDateTimes (const time_t TimeUTC[Dat_NUM_START_END_TIME], Dat_FormSeconds FormSeconds, const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME]) { diff --git a/swad_date.h b/swad_date.h index d87bf9c62..00bf04f01 100644 --- a/swad_date.h +++ b/swad_date.h @@ -144,7 +144,7 @@ struct tm *Dat_GetLocalTimeFromClock (const time_t *timep); void Dat_ConvDateToDateStr (struct Date *Date,char StrDate[Cns_MAX_BYTES_DATE + 1]); void Dat_PutFormStartEndClientLocalDateTimesWithYesterdayToday (const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME]); -void Dat_PutFormStartEndClientLocalDateTimes (time_t TimeUTC[2], +void Dat_PutFormStartEndClientLocalDateTimes (const time_t TimeUTC[Dat_NUM_START_END_TIME], Dat_FormSeconds FormSeconds, const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME]); diff --git a/swad_program.c b/swad_program.c index 7543d11b6..e59870cf7 100644 --- a/swad_program.c +++ b/swad_program.c @@ -98,10 +98,12 @@ static long Prg_GetCurrentItmCod (void); static void Prg_PutParams (void); static void Prg_GetListPrgItems (void); +static void Prg_GetDataOfItemByCod (struct ProgramItem *Item); static void Prg_GetDataOfItem (struct ProgramItem *Item, MYSQL_RES **mysql_res, unsigned long NumRows); static void Prg_ResetItem (struct ProgramItem *Item); +static void Prg_FreeListItems (void); static void Prg_GetPrgItemTxtFromDB (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); static void Prg_PutParamItmCod (long ItmCod); static long Prg_GetParamItmCod (void); @@ -109,18 +111,24 @@ static long Prg_GetParamItmCod (void); static unsigned Prg_GetNumItemFromItmCod (unsigned ItmCod); static unsigned Prg_GetMaxItemLevel (void); -static unsigned Prg_GetMaxItemIndex (void); static int Prg_GetPrevBrother (int NumItem); static int Prg_GetNextBrother (int NumItem); -static int Prg_GetLastChild (int NumItem); +static unsigned Prg_GetLastChild (int NumItem); static void Prg_ExchangeItems (int NumItemTop,int NumItemBottom); static void Prg_MoveItemAndChildrenLeft (unsigned NumItem); static void Prg_MoveItemAndChildrenRight (unsigned NumItem); static bool Prg_CheckIfSimilarPrgItemExists (const char *Field,const char *Value,long ItmCod); +static void Prg_ShowFormToCreatePrgItem (void); +static void Prg_ShowFormToChangePrgItem (void); +static void Prg_ShowFormToPrgItem (const struct ProgramItem *Item, + const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME], + const char *Txt); static void Prg_ShowLstGrpsToEditPrgItem (long ItmCod); -static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt); +static void Prg_InsertPrgItem (struct ProgramItem *ParentItem, + struct ProgramItem *Item,const char *Txt); +static long Prg_InsertPrgItemIntoDB (struct ProgramItem *Item,const char *Txt); static void Prg_UpdatePrgItem (struct ProgramItem *Item,const char *Txt); static bool Prg_CheckIfItemIsAssociatedToGrps (long ItmCod); static void Prg_RemoveAllTheGrpsAssociatedToAnItem (long ItmCod); @@ -462,6 +470,7 @@ static void Prg_WriteNumItem (unsigned Level) static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,const char *Anchor) { + extern const char *Txt_New_item; extern const char *Txt_Move_up_X; extern const char *Txt_Move_down_X; extern const char *Txt_Increase_level_of_X; @@ -490,7 +499,10 @@ static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,const char *Anchor Ico_PutContextualIconToHide (ActHidPrgItm,Anchor,Prg_PutParams); /***** Put form to edit program item *****/ - Ico_PutContextualIconToEdit (ActEdiOnePrgItm,Prg_PutParams); + Ico_PutContextualIconToEdit (ActFrmChgPrgItm,Prg_PutParams); + + /***** Put form to add a new child item inside this item *****/ + Ico_PutContextualIconToAdd (ActFrmNewPrgItm,Anchor,Prg_PutParams,Txt_New_item); HTM_BR (); @@ -518,8 +530,6 @@ static void Prg_PutFormsToRemEditOnePrgItem (unsigned NumItem,const char *Anchor else Ico_PutIconOff ("arrow-down.svg",Txt_Movement_not_allowed); - HTM_BR (); - /***** Icon to move left item (increase level) *****/ if (Prg_CheckIfMoveLeftIsAllowed (NumItem)) { @@ -752,7 +762,7 @@ static void Prg_GetListPrgItems (void) /****************** Get program item data using its code *********************/ /*****************************************************************************/ -void Prg_GetDataOfItemByCod (struct ProgramItem *Item) +static void Prg_GetDataOfItemByCod (struct ProgramItem *Item) { MYSQL_RES *mysql_res; unsigned long NumRows; @@ -797,7 +807,7 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item, Prg_ResetItem (Item); /***** Get data of program item from database *****/ - if (NumRows) // Schedule item found... + if (NumRows) // Item found... { /* Get row */ row = mysql_fetch_row (*mysql_res); @@ -857,7 +867,7 @@ static void Prg_ResetItem (struct ProgramItem *Item) { Item->Hierarchy.ItmCod = -1L; Item->Hierarchy.Index = 0; - Item->Hierarchy.Level = 1; + Item->Hierarchy.Level = 0; Item->Hidden = false; Item->UsrCod = -1L; Item->TimeUTC[Dat_START_TIME] = @@ -871,7 +881,7 @@ static void Prg_ResetItem (struct ProgramItem *Item) /************************ Free list of program items *************************/ /*****************************************************************************/ -void Prg_FreeListItems (void) +static void Prg_FreeListItems (void) { if (Gbl.Prg.LstIsRead && Gbl.Prg.LstItems) { @@ -1209,35 +1219,6 @@ static unsigned Prg_GetMaxItemLevel (void) return MaxLevel; } -/*****************************************************************************/ -/**************** Get maximum item index in a course program *****************/ -/*****************************************************************************/ -// Question index can be 1, 2, 3... -// Return 0 if no items - -static unsigned Prg_GetMaxItemIndex (void) - { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - unsigned MaxIndex = 0; - - /***** Get maximum item index in a course program from database *****/ - DB_QuerySELECT (&mysql_res,"can not get last item index", - "SELECT MAX(ItmInd)" - " FROM prg_items" - " WHERE CrsCod=%ld", - Gbl.Hierarchy.Crs.CrsCod); - row = mysql_fetch_row (mysql_res); - if (row[0]) // There are items - if (sscanf (row[0],"%u",&MaxIndex) != 1) - Lay_ShowErrorAndExit ("Error when getting last item index."); - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return MaxIndex; - } - /*****************************************************************************/ /******** Get previous brother item to a given item in current course ********/ /*****************************************************************************/ @@ -1303,7 +1284,7 @@ static int Prg_GetNextBrother (int NumItem) /*****************************************************************************/ // Return the same index if no children -static int Prg_GetLastChild (int NumItem) +static unsigned Prg_GetLastChild (int NumItem) { unsigned Level; int i; @@ -1311,7 +1292,7 @@ static int Prg_GetLastChild (int NumItem) /***** Trivial check: if item is wrong, there are no children *****/ if (NumItem < 0 || NumItem >= (int) Gbl.Prg.Num) - return -1; + Lay_ShowErrorAndExit ("Wrong number of item."); /***** Get next brother after item *****/ // 0 <= NumItem < Gbl.Prg.Num @@ -1497,23 +1478,39 @@ static bool Prg_CheckIfSimilarPrgItemExists (const char *Field,const char *Value Field,Value,ItmCod) != 0); } +/*****************************************************************************/ +/******* Put a form to create/edit program item and show current items *******/ +/*****************************************************************************/ + +void Prg_RequestCreatePrgItem (void) + { + /***** Show form to create item *****/ + Prg_ShowFormToCreatePrgItem (); + + /***** Show current program items, if any *****/ + Prg_ShowAllItems (); + } + +void Prg_RequestChangePrgItem (void) + { + /***** Show form to change item *****/ + Prg_ShowFormToChangePrgItem (); + + /***** Show current program items, if any *****/ + Prg_ShowAllItems (); + } + /*****************************************************************************/ /***************** Put a form to create a new program item *******************/ /*****************************************************************************/ -void Prg_RequestCreatOrEditPrgItem (void) +static void Prg_ShowFormToCreatePrgItem (void) { extern const char *Hlp_COURSE_Program_new_item; - extern const char *Hlp_COURSE_Program_edit_item; extern const char *Txt_New_item; - extern const char *Txt_Edit_item; - extern const char *Txt_Title; - extern const char *Txt_Description; extern const char *Txt_Create_item; - extern const char *Txt_Save_changes; + struct ProgramItem ParentItem; // Parent item struct ProgramItem Item; - bool ItsANewItem; - char Txt[Cns_MAX_BYTES_TEXT + 1]; static const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME] = { Dat_HMS_TO_000000, @@ -1523,53 +1520,99 @@ void Prg_RequestCreatOrEditPrgItem (void) /***** Get parameters *****/ Grp_GetParamWhichGrps (); - /***** Get the code of the program item *****/ - ItsANewItem = ((Item.Hierarchy.ItmCod = Prg_GetParamItmCod ()) == -1L); + /***** Get the code of the parent program item *****/ + ParentItem.Hierarchy.ItmCod = Prg_GetParamItmCod (); + Prg_GetDataOfItemByCod (&ParentItem); - /***** Get from the database the data of the program item *****/ - if (ItsANewItem) - { - /* Initialize to empty program item */ - Prg_ResetItem (&Item); - Item.TimeUTC[Dat_START_TIME] = Gbl.StartExecutionTimeUTC; - Item.TimeUTC[Dat_END_TIME ] = Gbl.StartExecutionTimeUTC + (2 * 60 * 60); // +2 hours - Item.Open = true; - } - else - { - /* Get data of the program item from database */ - Prg_GetDataOfItemByCod (&Item); - - /* Get text of the program item from database */ - Prg_GetPrgItemTxtFromDB (Item.Hierarchy.ItmCod,Txt); - } + /***** Initialize to empty program item *****/ + Prg_ResetItem (&Item); + Item.TimeUTC[Dat_START_TIME] = Gbl.StartExecutionTimeUTC; + Item.TimeUTC[Dat_END_TIME ] = Gbl.StartExecutionTimeUTC + (2 * 60 * 60); // +2 hours + Item.Open = true; /***** Begin form *****/ - if (ItsANewItem) - { - Frm_StartForm (ActNewPrgItm); - Prg_SetCurrentItmCod (-1L); - } - else - { - Frm_StartForm (ActChgPrgItm); - Prg_SetCurrentItmCod (Item.Hierarchy.ItmCod); - } + Frm_StartForm (ActNewPrgItm); + Prg_SetCurrentItmCod (ParentItem.Hierarchy.ItmCod); Prg_PutParams (); /***** Begin box and table *****/ - if (ItsANewItem) - Box_BoxTableBegin (NULL,Txt_New_item,NULL, - Hlp_COURSE_Program_new_item,Box_NOT_CLOSABLE,2); - else - Box_BoxTableBegin (NULL, - Item.Title[0] ? Item.Title : - Txt_Edit_item, - NULL, - Hlp_COURSE_Program_edit_item,Box_NOT_CLOSABLE,2); + Box_BoxTableBegin (NULL,Txt_New_item,NULL, + Hlp_COURSE_Program_new_item,Box_NOT_CLOSABLE,2); + /***** Show form *****/ + Prg_ShowFormToPrgItem (&Item,SetHMS,NULL); - /***** Schedule item title *****/ + /***** End table, send button and end box *****/ + Box_BoxTableWithButtonEnd (Btn_CREATE_BUTTON,Txt_Create_item); + + /***** End form *****/ + Frm_EndForm (); + } + +/*****************************************************************************/ +/***************** Put a form to create a new program item *******************/ +/*****************************************************************************/ + +static void Prg_ShowFormToChangePrgItem (void) + { + extern const char *Hlp_COURSE_Program_edit_item; + extern const char *Txt_Edit_item; + extern const char *Txt_Save_changes; + struct ProgramItem Item; + char Txt[Cns_MAX_BYTES_TEXT + 1]; + static const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME] = + { + Dat_HMS_DO_NOT_SET, + Dat_HMS_DO_NOT_SET + }; + + /***** Get parameters *****/ + Grp_GetParamWhichGrps (); + + /***** Get the code of the program item *****/ + Item.Hierarchy.ItmCod = Prg_GetParamItmCod (); + + /***** Get from the database the data of the program item *****/ + /* Get data of the program item from database */ + Prg_GetDataOfItemByCod (&Item); + + /* Get text of the program item from database */ + Prg_GetPrgItemTxtFromDB (Item.Hierarchy.ItmCod,Txt); + + /***** Begin form *****/ + Frm_StartForm (ActChgPrgItm); + Prg_SetCurrentItmCod (Item.Hierarchy.ItmCod); + Prg_PutParams (); + + /***** Begin box and table *****/ + Box_BoxTableBegin (NULL, + Item.Title[0] ? Item.Title : + Txt_Edit_item, + NULL, + Hlp_COURSE_Program_edit_item,Box_NOT_CLOSABLE,2); + + /***** Show form *****/ + Prg_ShowFormToPrgItem (&Item,SetHMS,Txt); + + /***** End table, send button and end box *****/ + Box_BoxTableWithButtonEnd (Btn_CONFIRM_BUTTON,Txt_Save_changes); + + /***** End form *****/ + Frm_EndForm (); + } + +/*****************************************************************************/ +/***************** Put a form to create a new program item *******************/ +/*****************************************************************************/ + +static void Prg_ShowFormToPrgItem (const struct ProgramItem *Item, + const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME], + const char *Txt) + { + extern const char *Txt_Title; + extern const char *Txt_Description; + + /***** Item title *****/ HTM_TR_Begin (NULL); /* Label */ @@ -1577,7 +1620,7 @@ void Prg_RequestCreatOrEditPrgItem (void) /* Data */ HTM_TD_Begin ("class=\"LM\""); - HTM_INPUT_TEXT ("Title",Prg_MAX_CHARS_PROGRAM_ITEM_TITLE,Item.Title,false, + HTM_INPUT_TEXT ("Title",Prg_MAX_CHARS_PROGRAM_ITEM_TITLE,Item->Title,false, "id=\"Title\" required=\"required\"" " class=\"TITLE_DESCRIPTION_WIDTH\""); HTM_TD_End (); @@ -1585,7 +1628,7 @@ void Prg_RequestCreatOrEditPrgItem (void) HTM_TR_End (); /***** Program item start and end dates *****/ - Dat_PutFormStartEndClientLocalDateTimes (Item.TimeUTC, + Dat_PutFormStartEndClientLocalDateTimes (Item->TimeUTC, Dat_FORM_SECONDS_ON, SetHMS); @@ -1599,27 +1642,16 @@ void Prg_RequestCreatOrEditPrgItem (void) HTM_TD_Begin ("class=\"LT\""); HTM_TEXTAREA_Begin ("id=\"Txt\" name=\"Txt\" rows=\"10\"" " class=\"TITLE_DESCRIPTION_WIDTH\""); - if (!ItsANewItem) - HTM_Txt (Txt); + if (Txt) + if (Txt[0]) + HTM_Txt (Txt); HTM_TEXTAREA_End (); HTM_TD_End (); HTM_TR_End (); /***** Groups *****/ - Prg_ShowLstGrpsToEditPrgItem (Item.Hierarchy.ItmCod); - - /***** End table, send button and end box *****/ - if (ItsANewItem) - Box_BoxTableWithButtonEnd (Btn_CREATE_BUTTON,Txt_Create_item); - else - Box_BoxTableWithButtonEnd (Btn_CONFIRM_BUTTON,Txt_Save_changes); - - /***** End form *****/ - Frm_EndForm (); - - /***** Show current program items, if any *****/ - Prg_ShowAllItems (); + Prg_ShowLstGrpsToEditPrgItem (Item->Hierarchy.ItmCod); } /*****************************************************************************/ @@ -1689,31 +1721,23 @@ static void Prg_ShowLstGrpsToEditPrgItem (long ItmCod) /***************** Receive form to create a new program item *****************/ /*****************************************************************************/ -void Prg_RecFormPrgItem (void) +void Prg_RecFormNewPrgItem (void) { extern const char *Txt_Already_existed_an_item_with_the_title_X; extern const char *Txt_You_must_specify_the_title_of_the_item; extern const char *Txt_Created_new_item_X; - extern const char *Txt_The_item_has_been_modified; - struct ProgramItem OldItem; // Current program item data in database - struct ProgramItem NewItem; // Schedule item data received from form - bool ItsANewItem; + struct ProgramItem ParentItem; // Parent item + struct ProgramItem NewItem; // Item data received from form bool NewItemIsCorrect = true; char Description[Cns_MAX_BYTES_TEXT + 1]; - /***** Get the code of the program item *****/ - NewItem.Hierarchy.ItmCod = Prg_GetParamItmCod (); - ItsANewItem = (NewItem.Hierarchy.ItmCod < 0); + /***** Get the code of the parent program item *****/ + ParentItem.Hierarchy.ItmCod = Prg_GetParamItmCod (); + Prg_GetDataOfItemByCod (&ParentItem); - if (ItsANewItem) - /***** Reset old (current, not existing) program item data *****/ - Prg_ResetItem (&OldItem); - else - { - /***** Get data of the old (current) program item from database *****/ - OldItem.Hierarchy.ItmCod = NewItem.Hierarchy.ItmCod; - Prg_GetDataOfItemByCod (&OldItem); - } + /***** Set new item code *****/ + NewItem.Hierarchy.ItmCod = -1L; + NewItem.Hierarchy.Level = ParentItem.Hierarchy.Level + 1; // Create as child /***** Get start/end date-times *****/ NewItem.TimeUTC[Dat_START_TIME] = Dat_GetTimeUTCFromForm ("StartTimeUTC"); @@ -1755,65 +1779,170 @@ void Prg_RecFormPrgItem (void) /* Get groups for this program items */ Grp_GetParCodsSeveralGrps (); - if (ItsANewItem) - { - Prg_CreatePrgItem (&NewItem,Description); // Add new program item to database - - /***** Write success message *****/ - Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_item_X, - NewItem.Title); - } - else - { - Prg_UpdatePrgItem (&NewItem,Description); - - /***** Write success message *****/ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_item_has_been_modified); - } + /* Add new program item to database */ + Prg_InsertPrgItem (&ParentItem,&NewItem,Description); /* Free memory for list of selected groups */ Grp_FreeListCodSelectedGrps (); - /***** Show program items again *****/ - Prg_SeeCourseProgram (); + /* Write success message */ + Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_item_X, + NewItem.Title); } else + /***** Show form to create item *****/ // TODO: The form should be filled with partial data, now is always empty - Prg_RequestCreatOrEditPrgItem (); + Prg_ShowFormToCreatePrgItem (); + + /***** Show program items again *****/ + Prg_SeeCourseProgram (); } /*****************************************************************************/ -/************************ Create a new program item **************************/ +/************* Receive form to change an existing program item ***************/ /*****************************************************************************/ -static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt) +void Prg_RecFormChgPrgItem (void) { - unsigned MaxIndex; + extern const char *Txt_Already_existed_an_item_with_the_title_X; + extern const char *Txt_You_must_specify_the_title_of_the_item; + extern const char *Txt_Created_new_item_X; + extern const char *Txt_The_item_has_been_modified; + struct ProgramItem OldItem; // Current program item data in database + struct ProgramItem NewItem; // Item data received from form + bool NewItemIsCorrect = true; + char Description[Cns_MAX_BYTES_TEXT + 1]; + + /***** Get the code of the program item *****/ + NewItem.Hierarchy.ItmCod = Prg_GetParamItmCod (); + + /***** Get data of the old (current) program item from database *****/ + OldItem.Hierarchy.ItmCod = NewItem.Hierarchy.ItmCod; + Prg_GetDataOfItemByCod (&OldItem); + + /***** Get start/end date-times *****/ + NewItem.TimeUTC[Dat_START_TIME] = Dat_GetTimeUTCFromForm ("StartTimeUTC"); + NewItem.TimeUTC[Dat_END_TIME ] = Dat_GetTimeUTCFromForm ("EndTimeUTC" ); + + /***** Get program item title *****/ + Par_GetParToText ("Title",NewItem.Title,Prg_MAX_BYTES_PROGRAM_ITEM_TITLE); + + /***** Get program item text *****/ + Par_GetParToHTML ("Txt",Description,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous) + + /***** Adjust dates *****/ + if (NewItem.TimeUTC[Dat_START_TIME] == 0) + NewItem.TimeUTC[Dat_START_TIME] = Gbl.StartExecutionTimeUTC; + if (NewItem.TimeUTC[Dat_END_TIME] == 0) + NewItem.TimeUTC[Dat_END_TIME] = NewItem.TimeUTC[Dat_START_TIME] + 2 * 60 * 60; // +2 hours + + /***** Check if title is correct *****/ + if (NewItem.Title[0]) // If there's a program item title + { + /* If title of program item was in database... */ + if (Prg_CheckIfSimilarPrgItemExists ("Title",NewItem.Title,NewItem.Hierarchy.ItmCod)) + { + NewItemIsCorrect = false; + + Ale_ShowAlert (Ale_WARNING,Txt_Already_existed_an_item_with_the_title_X, + NewItem.Title); + } + } + else // If there is not a program item title + { + NewItemIsCorrect = false; + Ale_ShowAlert (Ale_WARNING,Txt_You_must_specify_the_title_of_the_item); + } + + /***** Update existing item *****/ + if (NewItemIsCorrect) + { + /* Get groups for this program items */ + Grp_GetParCodsSeveralGrps (); + + /* Update program item */ + Prg_UpdatePrgItem (&NewItem,Description); + + /* Free memory for list of selected groups */ + Grp_FreeListCodSelectedGrps (); + + /* Write success message */ + Ale_ShowAlert (Ale_SUCCESS,Txt_The_item_has_been_modified); + } + else + /***** Show form to change item *****/ + // TODO: The form should be filled with partial data, now is always empty + Prg_ShowFormToChangePrgItem (); + + /***** Show program items again *****/ + Prg_SeeCourseProgram (); + } + +/*****************************************************************************/ +/*********** Insert a new program item as a child of a parent item ***********/ +/*****************************************************************************/ + +static void Prg_InsertPrgItem (struct ProgramItem *ParentItem, + struct ProgramItem *Item,const char *Txt) + { + unsigned NumItemParent; + unsigned NumItemLastChild; /***** Lock table to create program item *****/ DB_Query ("can not lock tables to create program item", "LOCK TABLES prg_items WRITE"); Gbl.DB.LockedTables = true; - /***** Get maximum item index *****/ - MaxIndex = Prg_GetMaxItemIndex (); + /***** Get list of program items *****/ + Prg_GetListPrgItems (); + if (Gbl.Prg.Num) // There are items + { + if (ParentItem->Hierarchy.ItmCod > 0) // Parent specified + { + /***** Calculate where to insert *****/ + NumItemParent = Prg_GetNumItemFromItmCod (ParentItem->Hierarchy.ItmCod); + NumItemLastChild = Prg_GetLastChild (NumItemParent); + if (NumItemLastChild < Gbl.Prg.Num - 1) + { + /***** New program item will be inserted after last child of parent *****/ + Item->Hierarchy.Index = Gbl.Prg.LstItems[NumItemLastChild + 1].Index; - /***** Create a new program item *****/ - Item->Hierarchy.Index = MaxIndex + 1; - Item->Hierarchy.ItmCod = - DB_QueryINSERTandReturnCode ("can not create new program item", - "INSERT INTO prg_items" - " (ItmInd,CrsCod,UsrCod,StartTime,EndTime,Title,Txt)" - " VALUES" - " (%u,%ld,%ld,FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld)," - "'%s','%s')", - Item->Hierarchy.Index, - Gbl.Hierarchy.Crs.CrsCod, - Gbl.Usrs.Me.UsrDat.UsrCod, - Item->TimeUTC[Dat_START_TIME], - Item->TimeUTC[Dat_END_TIME ], - Item->Title, - Txt); + /***** Move down all indexes of after last child of parent *****/ + DB_QueryUPDATE ("can not move down items", + "UPDATE prg_items SET ItmInd=ItmInd+1" + " WHERE CrsCod=%ld" + " AND ItmInd>=%u" + " ORDER BY ItmInd DESC", // Necessary to not create duplicate key (CrsCod,ItmInd) + Gbl.Hierarchy.Crs.CrsCod, + Item->Hierarchy.Index); + } + else + /***** New program item will be inserted at the end *****/ + Item->Hierarchy.Index = Gbl.Prg.LstItems[Gbl.Prg.Num - 1].Index + 1; + + /***** Child ==> parent level + 1 *****/ + Item->Hierarchy.Level = ParentItem->Hierarchy.Level + 1; + } + else // No parent specified + { + /***** New program item will be inserted at the end *****/ + Item->Hierarchy.Index = Gbl.Prg.LstItems[Gbl.Prg.Num - 1].Index + 1; + + /***** First level *****/ + Item->Hierarchy.Level = 1; + } + } + else // There are no items + { + /***** New program item will be inserted as the first one *****/ + Item->Hierarchy.Index = 1; + + /***** First level *****/ + Item->Hierarchy.Level = 1; + } + + /***** Insert new program item *****/ + Item->Hierarchy.ItmCod = Prg_InsertPrgItemIntoDB (Item,Txt); /***** Unlock table *****/ Gbl.DB.LockedTables = false; // Set to false before the following unlock... @@ -1821,11 +1950,36 @@ static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt) DB_Query ("can not unlock tables after moving items", "UNLOCK TABLES"); + /***** Free list items *****/ + Prg_FreeListItems (); + /***** Create groups *****/ if (Gbl.Crs.Grps.LstGrpsSel.NumGrps) Prg_CreateGrps (Item->Hierarchy.ItmCod); } +/*****************************************************************************/ +/***************** Create a new program item into database *******************/ +/*****************************************************************************/ + +static long Prg_InsertPrgItemIntoDB (struct ProgramItem *Item,const char *Txt) + { + return DB_QueryINSERTandReturnCode ("can not create new program item", + "INSERT INTO prg_items" + " (CrsCod,ItmInd,Level,UsrCod,StartTime,EndTime,Title,Txt)" + " VALUES" + " (%ld,%u,%u,%ld,FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld)," + "'%s','%s')", + Gbl.Hierarchy.Crs.CrsCod, + Item->Hierarchy.Index, + Item->Hierarchy.Level, + Gbl.Usrs.Me.UsrDat.UsrCod, + Item->TimeUTC[Dat_START_TIME], + Item->TimeUTC[Dat_END_TIME ], + Item->Title, + Txt); + } + /*****************************************************************************/ /******************** Update an existing program item ************************/ /*****************************************************************************/ @@ -2049,10 +2203,10 @@ static bool Prg_CheckIfIBelongToCrsOrGrpsThisItem (long ItmCod) " WHERE ItmCod=%ld" " AND " "(" - // Schedule item is for the whole course + // Item is for the whole course "ItmCod NOT IN (SELECT ItmCod FROM prg_grp)" " OR " - // Schedule item is for specific groups + // Item is for specific groups "ItmCod IN" " (SELECT prg_grp.ItmCod FROM prg_grp,crs_grp_usr" " WHERE crs_grp_usr.UsrCod=%ld" diff --git a/swad_program.h b/swad_program.h index 47bf2cfe9..be7c07cbc 100644 --- a/swad_program.h +++ b/swad_program.h @@ -69,11 +69,10 @@ struct ProgramItem void Prg_SeeCourseProgram (void); -void Prg_RequestCreatOrEditPrgItem (void); -void Prg_GetDataOfItemByCod (struct ProgramItem *PrgItem); -void Prg_FreeListItems (void); - -long Prg_GetParamItemCode (void); +void Prg_RequestCreatePrgItem (void); +void Prg_RequestChangePrgItem (void); +void Prg_RecFormNewPrgItem (void); +void Prg_RecFormChgPrgItem (void); void Prg_ReqRemPrgItem (void); void Prg_RemovePrgItem (void); diff --git a/swad_text_action.c b/swad_text_action.c index 0c3a0da8b..2d940ff21 100644 --- a/swad_text_action.c +++ b/swad_text_action.c @@ -4808,7 +4808,7 @@ const char *Txt_Actions[Act_NUM_ACTIONS] = "" // Precisa de tradução #endif , - [ActEdiOnePrgItm] = + [ActFrmChgPrgItm] = #if L==1 // ca "" // Necessita traducció #elif L==2 // de