Version 21.107: Jul 15, 2022 Move up/down resource of program item.

This commit is contained in:
acanas 2022-07-15 18:15:40 +02:00
parent e45bf73e21
commit 942db928ce
17 changed files with 332 additions and 173 deletions

View File

@ -606,11 +606,12 @@ TODO: Fix bug: error al enviar un mensaje a dos recipientes, error on duplicate
TODO: Attach pdf files in multimedia.
*/
#define Log_PLATFORM_VERSION "SWAD 21.106 (2022-07-14)"
#define Log_PLATFORM_VERSION "SWAD 21.107 (2022-07-15)"
#define CSS_FILE "swad21.103.6.css"
#define JS_FILE "swad21.100.js"
/*
Version 21.106: Jul 14, 2022 Hide/unhide resource from program item. (328816 lines)
Version 21.107: Jul 15, 2022 Move up/down resource of program item. (328953 lines)
Version 21.106: Jul 14, 2022 Hide/unhide resource of program item. (328816 lines)
Version 21.105: Jul 14, 2022 Removing resource from program item. (328617 lines)
Version 21.104.1: Jul 13, 2022 Adding resources to program items. (328504 lines)
Version 21.104: Jul 12, 2022 Adding resources to program items. (328263 lines)

View File

@ -4337,3 +4337,15 @@ void DB_ExitOnMySQLError (const char *Message)
Message,mysql_error (&Gbl.mysql));
Err_ShowErrorAndExit (BigErrorMsg);
}
/*****************************************************************************/
/********** Unlock tables to make the exchange of items atomic ***************/
/*****************************************************************************/
void DB_UnlockTables (void)
{
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ("can not unlock tables",
"UNLOCK TABLES");
}

View File

@ -77,4 +77,6 @@ void DB_Query (const char *MsgError,const char *fmt,...);
void DB_FreeMySQLResult (MYSQL_RES **mysql_res);
void DB_ExitOnMySQLError (const char *Message);
void DB_UnlockTables (void);
#endif

View File

@ -619,18 +619,6 @@ void Exa_DB_LockTables (void)
Gbl.DB.LockedTables = true;
}
/*****************************************************************************/
/********** Unlock tables to make the exchange of sets atomic ****************/
/*****************************************************************************/
void Exa_DB_UnlockTables (void)
{
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ("can not unlock tables after exchanging sets of questions",
"UNLOCK TABLES");
}
/*****************************************************************************/
/*********************** Get number of sets in an exam ***********************/
/*****************************************************************************/

View File

@ -61,7 +61,6 @@ void Exa_DB_UpdateNumQstsToExam (long SetCod,long ExaCod,unsigned NumQstsToPrint
void Exa_DB_UpdateSetIndexesInExamGreaterThan (long ExaCod,long SetInd);
void Exa_DB_UpdateSetIndex (long SetInd,long SetCod,long ExaCod);
void Exa_DB_LockTables (void);
void Exa_DB_UnlockTables (void);
unsigned Exa_DB_GetNumSetsExam (long ExaCod);
unsigned Exa_DB_GetNumQstsExam (long ExaCod);
unsigned Exa_DB_GetExamSets (MYSQL_RES **mysql_res,long ExaCod);

View File

@ -1797,7 +1797,7 @@ static void ExaSet_ExchangeSets (long ExaCod,
Exa_DB_UpdateSetIndex ( (long) SetIndBottom ,SetCodTop ,ExaCod);
/***** Unlock table *****/
Exa_DB_LockTables ();
DB_UnlockTables ();
}
/*****************************************************************************/

View File

@ -2173,7 +2173,7 @@ static void Gam_ExchangeQuestions (long GamCod,
Gam_DB_UpdateQstIndex ( (long) QstIndBottom ,GamCod,QstCodTop );
/***** Unlock table *****/
Gam_DB_UnlockTable ();
DB_UnlockTables ();
}
/*****************************************************************************/

View File

@ -487,18 +487,6 @@ void Gam_DB_LockTable (void)
Gbl.DB.LockedTables = true;
}
/*****************************************************************************/
/********** Unlock table to make the exchange of questions atomic ************/
/*****************************************************************************/
void Gam_DB_UnlockTable (void)
{
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ("can not unlock tables after moving game questions",
"UNLOCK TABLES");
}
/*****************************************************************************/
/******************* Get number of questions of a game *********************/
/*****************************************************************************/

View File

@ -55,7 +55,6 @@ void Gam_DB_InsertQstInGame (long GamCod,unsigned QstInd,long QstCod);
void Gam_DB_UpdateIndexesOfQstsGreaterThan (long GamCod,unsigned QstInd);
void Gam_DB_UpdateQstIndex (long QstInd,long GamCod,long QstCod);
void Gam_DB_LockTable (void);
void Gam_DB_UnlockTable (void);
unsigned Gam_DB_GetNumQstsGame (long GamCod);
unsigned Gam_DB_GetGameQuestionsBasic (MYSQL_RES **mysql_res,long GamCod);

View File

@ -881,7 +881,7 @@ bool Grp_ChangeMyGrpsAtomically (struct ListCodGrps *LstGrpsIWant)
Grp_FreeListCodGrp (&LstGrpsIBelong);
/***** Unlock tables after changes in my groups *****/
Grp_DB_UnlockTables ();
DB_UnlockTables ();
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ();
@ -946,7 +946,7 @@ void Grp_ChangeGrpsOtherUsrAtomically (struct ListCodGrps *LstGrpsUsrWants)
/***** Unlock tables after changes in groups *****/
if (Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs == Rol_STD)
Grp_DB_UnlockTables ();
DB_UnlockTables ();
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ();

View File

@ -57,18 +57,6 @@ void Grp_DB_LockTables (void)
Gbl.DB.LockedTables = true;
}
/*****************************************************************************/
/*********** Unlock tables after changes in registration in groups ***********/
/*****************************************************************************/
void Grp_DB_UnlockTables (void)
{
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ("can not unlock tables after changing user's groups",
"UNLOCK TABLES");
}
/*****************************************************************************/
/************************** Create a new group type **************************/
/*****************************************************************************/

View File

@ -34,7 +34,6 @@
/*****************************************************************************/
void Grp_DB_LockTables (void);
void Grp_DB_UnlockTables (void);
long Grp_DB_CreateGroupType (const struct GroupType *GrpTyp);
void Grp_DB_CreateGroup (const struct Grp_Groups *Grps);

View File

@ -1314,7 +1314,7 @@ static bool Prg_ExchangeItemRanges (int NumItemTop,int NumItemBottom)
DiffEnd = Bottom.End - Top.End;
/***** Lock table to make the move atomic *****/
Prg_DB_LockTable ();
Prg_DB_LockTableItems ();
/***** Exchange indexes of items *****/
// This implementation works with non continuous indexes
@ -1357,7 +1357,7 @@ Bottom.End: | 49| 222|-->|-->-49| 222| | -49| 222|-->|--> 26| 2
-((long) Bottom.Begin)); // All indexes in bottom part
/***** Unlock table *****/
Prg_DB_UnlockTable ();
DB_UnlockTables ();
return true; // Success
}
@ -1894,7 +1894,7 @@ static void Prg_InsertItem (const struct Prg_Item *ParentItem,
unsigned NumItemLastChild;
/***** Lock table to create program item *****/
Prg_DB_LockTable ();
Prg_DB_LockTableItems ();
/***** Get list of program items *****/
Prg_GetListItems ();
@ -1941,7 +1941,7 @@ static void Prg_InsertItem (const struct Prg_Item *ParentItem,
Item->Hierarchy.ItmCod = Prg_DB_InsertItem (Item,Txt);
/***** Unlock table *****/
Prg_DB_UnlockTable ();
DB_UnlockTables ();
/***** Free list items *****/
Prg_FreeListItems ();

View File

@ -120,28 +120,16 @@ void Prg_DB_UpdateIndexRange (long Diff,long Begin,long End)
}
/*****************************************************************************/
/************ Lock tables to make the exchange of items atomic ***************/
/************ Lock table to make the exchange of items atomic ****************/
/*****************************************************************************/
void Prg_DB_LockTable (void)
void Prg_DB_LockTableItems (void)
{
DB_Query ("can not lock table",
"LOCK TABLES prg_items WRITE");
Gbl.DB.LockedTables = true;
}
/*****************************************************************************/
/********** Unlock tables to make the exchange of items atomic ***************/
/*****************************************************************************/
void Prg_DB_UnlockTable (void)
{
Gbl.DB.LockedTables = false; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
DB_Query ("can not unlock tables",
"UNLOCK TABLES");
}
/*****************************************************************************/
/************ Move down all indexes of after last child of parent ************/
/*****************************************************************************/
@ -256,63 +244,6 @@ void Prg_DB_GetItemTxt (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/****************** Get list of item resources from database *****************/
/*****************************************************************************/
unsigned Prg_DB_GetListResources (MYSQL_RES **mysql_res,long ItmCod,
bool ShowHiddenResources)
{/*
static const char *HiddenSubQuery[Rol_NUM_ROLES] =
{
[Rol_UNK ] = " AND Hidden='N'",
[Rol_GST ] = " AND Hidden='N'",
[Rol_USR ] = " AND Hidden='N'",
[Rol_STD ] = " AND Hidden='N'",
[Rol_NET ] = " AND Hidden='N'",
[Rol_TCH ] = "",
[Rol_DEG_ADM] = " AND Hidden='N'",
[Rol_CTR_ADM] = " AND Hidden='N'",
[Rol_INS_ADM] = " AND Hidden='N'",
[Rol_SYS_ADM] = "",
}; */
static const char *HiddenSubQuery[2] =
{
[false] = " AND Hidden='N'",
[true ] = "",
};
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get item resources",
"SELECT ItmCod," // row[0]
"RscCod," // row[1]
"Hidden," // row[2]
"Title" // row[3]
" FROM prg_resources"
" WHERE ItmCod=%ld"
"%s"
" ORDER BY RscInd",
ItmCod,
HiddenSubQuery[ShowHiddenResources]);
}
/*****************************************************************************/
/****************** Get item resource data using its code ********************/
/*****************************************************************************/
unsigned Prg_DB_GetDataOfResourceByCod (MYSQL_RES **mysql_res,long RscCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get item resource data",
"SELECT ItmCod," // row[0]
"RscCod," // row[1]
"Hidden," // row[2]
"Title" // row[3]
" FROM prg_resources"
" WHERE RscCod=%ld",
RscCod);
}
/*****************************************************************************/
/****************** Get number of courses with program items *****************/
/*****************************************************************************/
@ -494,6 +425,130 @@ void Prg_DB_RemoveCrsItems (long CrsCod)
CrsCod);
}
/*****************************************************************************/
/****************** Get list of item resources from database *****************/
/*****************************************************************************/
unsigned Prg_DB_GetListResources (MYSQL_RES **mysql_res,long ItmCod,
bool ShowHiddenResources)
{/*
static const char *HiddenSubQuery[Rol_NUM_ROLES] =
{
[Rol_UNK ] = " AND Hidden='N'",
[Rol_GST ] = " AND Hidden='N'",
[Rol_USR ] = " AND Hidden='N'",
[Rol_STD ] = " AND Hidden='N'",
[Rol_NET ] = " AND Hidden='N'",
[Rol_TCH ] = "",
[Rol_DEG_ADM] = " AND Hidden='N'",
[Rol_CTR_ADM] = " AND Hidden='N'",
[Rol_INS_ADM] = " AND Hidden='N'",
[Rol_SYS_ADM] = "",
}; */
static const char *HiddenSubQuery[2] =
{
[false] = " AND Hidden='N'",
[true ] = "",
};
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get item resources",
"SELECT ItmCod," // row[0]
"RscCod," // row[1]
"RscInd," // row[2]
"Hidden," // row[3]
"Title" // row[4]
" FROM prg_resources"
" WHERE ItmCod=%ld"
"%s"
" ORDER BY RscInd",
ItmCod,
HiddenSubQuery[ShowHiddenResources]);
}
/*****************************************************************************/
/****************** Get item resource data using its code ********************/
/*****************************************************************************/
unsigned Prg_DB_GetDataOfResourceByCod (MYSQL_RES **mysql_res,long RscCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get item resource data",
"SELECT ItmCod," // row[0]
"RscCod," // row[1]
"RscInd," // row[2]
"Hidden," // row[3]
"Title" // row[4]
" FROM prg_resources"
" WHERE RscCod=%ld",
RscCod);
}
/*****************************************************************************/
/****************** Get item resource data using its code ********************/
/*****************************************************************************/
unsigned Prg_DB_GetDataOfResourceByInd (MYSQL_RES **mysql_res,
long ItmCod,unsigned RscInd)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get item resource data",
"SELECT ItmCod," // row[0]
"RscCod," // row[1]
"RscInd," // row[2]
"Hidden," // row[3]
"Title" // row[4]
" FROM prg_resources"
" WHERE ItmCod=%ld"
" AND RscInd=%u",
ItmCod,RscInd);
}
/*****************************************************************************/
/************* Get the resource index before/after a given one ***************/
/*****************************************************************************/
unsigned Prg_DB_GetRscIndBefore (long ItmCod,unsigned RscInd)
{
return
DB_QuerySELECTUnsigned ("can not get the resource before",
"SELECT COALESCE(MAX(RscInd),0)"
" FROM prg_resources"
" WHERE ItmCod=%ld"
" AND RscInd<%u",
ItmCod,RscInd);
}
unsigned Prg_DB_GetRscIndAfter (long ItmCod,unsigned RscInd)
{
return
DB_QuerySELECTUnsigned ("can not get the resource after",
"SELECT COALESCE(MIN(RscInd),0)"
" FROM prg_resources"
" WHERE ItmCod=%ld"
" AND RscInd>%u",
ItmCod,RscInd);
}
/*****************************************************************************/
/*********** Get resource code given item code and resource index ************/
/*****************************************************************************/
long Prg_DB_GetRscCodFromRscInd (long ItmCod,unsigned RscInd)
{
/***** Trivial check: resource index should be > 0 *****/
if (RscInd == 0)
return -1L;
/***** Get resource code given item code and resource index *****/
return DB_QuerySELECTCode ("can not get resource code",
"SELECT RscCod"
" FROM prg_resources"
" WHERE ItmCod=%ld"
" AND RscInd=%u",
ItmCod,RscInd);
}
/*****************************************************************************/
/************************** Remove an item resource **************************/
/*****************************************************************************/
@ -522,3 +577,28 @@ void Prg_DB_HideOrUnhideResource (long RscCod,bool Hide)
'N',
RscCod);
}
/*****************************************************************************/
/********** Lock table to make the exchange of resources atomic **************/
/*****************************************************************************/
void Prg_DB_LockTableResources (void)
{
DB_Query ("can not lock table",
"LOCK TABLES prg_resources WRITE");
Gbl.DB.LockedTables = true;
}
/*****************************************************************************/
/************* Update the index of a resource given its code *****************/
/*****************************************************************************/
void Prg_DB_UpdateRscInd (long RscCod,int RscInd)
{
DB_QueryUPDATE ("can not update index of resource",
"UPDATE prg_resources"
" SET RscInd=%d"
" WHERE RscCod=%ld",
RscInd,
RscCod);
}

View File

@ -40,8 +40,7 @@ long Prg_DB_InsertItem (const struct Prg_Item *Item,const char *Txt);
void Prg_DB_UpdateItem (const struct Prg_Item *Item,const char *Txt);
void Prg_DB_HideOrUnhideItem (long ItmCod,bool Hide);
void Prg_DB_UpdateIndexRange (long Diff,long Begin,long End);
void Prg_DB_LockTable (void);
void Prg_DB_UnlockTable (void);
void Prg_DB_LockTableItems (void);
void Prg_DB_MoveDownItems (unsigned Index);
void Prg_DB_MoveLeftRightItemRange (const struct Prg_ItemRange *ToMove,
Prg_MoveLeftRight_t LeftRight);
@ -50,10 +49,6 @@ unsigned Prg_DB_GetListItems (MYSQL_RES **mysql_res);
unsigned Prg_DB_GetDataOfItemByCod (MYSQL_RES **mysql_res,long ItmCod);
void Prg_DB_GetItemTxt (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1]);
unsigned Prg_DB_GetListResources (MYSQL_RES **mysql_res,long ItmCod,
bool ShowHiddenResources);
unsigned Prg_DB_GetDataOfResourceByCod (MYSQL_RES **mysql_res,long RscCod);
unsigned Prg_DB_GetNumCoursesWithItems (HieLvl_Level_t Scope);
unsigned Prg_DB_GetNumItems (HieLvl_Level_t Scope);
@ -61,8 +56,20 @@ void Prg_DB_RemoveItemRange (const struct Prg_ItemRange *ToRemove);
void Prg_DB_RemoveCrsItems (long CrsCod);
//------------------------------ Resources ------------------------------------
unsigned Prg_DB_GetListResources (MYSQL_RES **mysql_res,long ItmCod,
bool ShowHiddenResources);
unsigned Prg_DB_GetDataOfResourceByCod (MYSQL_RES **mysql_res,long RscCod);
unsigned Prg_DB_GetDataOfResourceByInd (MYSQL_RES **mysql_res,
long ItmCod,unsigned RscInd);
unsigned Prg_DB_GetRscIndBefore (long ItmCod,unsigned RscInd);
unsigned Prg_DB_GetRscIndAfter (long ItmCod,unsigned RscInd);
long Prg_DB_GetRscCodFromRscInd (long ItmCod,unsigned RscInd);
void Prg_DB_RemoveResource (const struct PrgRsc_Resource *Resource);
void Prg_DB_HideOrUnhideResource (long RscCod,bool Hide);
void Prg_DB_LockTableResources (void);
void Prg_DB_UpdateRscInd (long RscCod,int RscInd);
#endif

View File

@ -82,6 +82,14 @@ struct Level
bool Hidden; // If each level from 1 to maximum level is hidden
};
*/
#define PrgRsc_NUM_MOVEMENTS_UP_DOWN 2
typedef enum
{
PrgRsc_MOVE_UP,
PrgRsc_MOVE_DOWN,
} PrgRsc_MoveUpDown_t;
/*****************************************************************************/
/***************************** Private variables *****************************/
/*****************************************************************************/
@ -139,9 +147,9 @@ static long PrgRsc_GetParamRscCod (void);
static void PrgRsc_HideOrUnhideResource (bool Hide);
static bool PrgRsc_CheckIfMoveUpIsAllowed (unsigned NumRsc);
static bool PrgRsc_CheckIfMoveDownIsAllowed (unsigned NumRsc,
unsigned NumResources);
static void PrgRsc_MoveUpDownResource (PrgRsc_MoveUpDown_t UpDown);
static bool PrgRsc_ExchangeResources (const struct PrgRsc_Rsc *Rsc1,
const struct PrgRsc_Rsc *Rsc2);
/*****************************************************************************/
/****************************** Show resources *******************************/
@ -348,10 +356,10 @@ static void PrgRsc_GetDataOfResourceByCod (struct PrgRsc_Resource *Resource)
{
MYSQL_RES *mysql_res;
if (Resource->RscCod > 0)
if (Resource->Rsc.Cod > 0)
{
/***** Get data of item resource *****/
if (Prg_DB_GetDataOfResourceByCod (&mysql_res,Resource->RscCod))
if (Prg_DB_GetDataOfResourceByCod (&mysql_res,Resource->Rsc.Cod))
PrgRsc_GetDataOfResource (Resource,&mysql_res);
else
PrgRsc_ResetResource (Resource);
@ -379,20 +387,22 @@ static void PrgRsc_GetDataOfResource (struct PrgRsc_Resource *Resource,
/*
ItmCod row[0]
RscCod row[1]
Hidden row[2]
Title row[3]
RscInd row[2]
Hidden row[3]
Title row[4]
*/
/* Get code of the program item (row[0]) */
Resource->ItmCod = Str_ConvertStrCodToLongCod (row[0]);
/* Get code of the item resource (row[1]) */
Resource->RscCod = Str_ConvertStrCodToLongCod (row[1]);
/* Get code and index of the item resource (row[1], row[2]) */
Resource->Rsc.Cod = Str_ConvertStrCodToLongCod (row[1]);
Resource->Rsc.Ind = Str_ConvertStrToUnsigned (row[2]);
/* Get whether the program item is hidden (row(2)) */
Resource->Hidden = (row[2][0] == 'Y');
/* Get whether the program item is hidden (row(3)) */
Resource->Hidden = (row[3][0] == 'Y');
/* Get the title of the item resource (row[3]) */
Str_Copy (Resource->Title,row[3],sizeof (Resource->Title) - 1);
/* Get the title of the item resource (row[4]) */
Str_Copy (Resource->Title,row[4],sizeof (Resource->Title) - 1);
}
/*****************************************************************************/
@ -402,7 +412,8 @@ static void PrgRsc_GetDataOfResource (struct PrgRsc_Resource *Resource,
static void PrgRsc_ResetResource (struct PrgRsc_Resource *Resource)
{
Resource->ItmCod = -1L;
Resource->RscCod = -1L;
Resource->Rsc.Cod = -1L;
Resource->Rsc.Ind = 0;
Resource->Hidden = false;
Resource->Title[0] = '\0';
}
@ -480,15 +491,15 @@ static void PrgRsc_PutFormsToRemEditOneResource (unsigned NumRsc,
case Rol_SYS_ADM:
/***** Put form to remove item resource *****/
Ico_PutContextualIconToRemove (ActReqRemPrgRsc,PrgRsc_RESOURCE_SECTION_ID,
PrgRsc_PutParams,&Resource->RscCod);
PrgRsc_PutParams,&Resource->Rsc.Cod);
/***** Put form to hide/show item resource *****/
if (Resource->Hidden)
Ico_PutContextualIconToUnhide (ActUnhPrgRsc,PrgRsc_RESOURCE_SECTION_ID,
PrgRsc_PutParams,&Resource->RscCod);
PrgRsc_PutParams,&Resource->Rsc.Cod);
else
Ico_PutContextualIconToHide (ActHidPrgRsc,PrgRsc_RESOURCE_SECTION_ID,
PrgRsc_PutParams,&Resource->RscCod);
PrgRsc_PutParams,&Resource->Rsc.Cod);
/***** Put form to edit program item *****/
// Ico_PutContextualIconToEdit (ActFrmChgPrgItm,"item_form",
@ -501,17 +512,17 @@ static void PrgRsc_PutFormsToRemEditOneResource (unsigned NumRsc,
HTM_BR ();
/***** Put icon to move up the item *****/
if (PrgRsc_CheckIfMoveUpIsAllowed (NumRsc))
if (NumRsc > 0)
Lay_PutContextualLinkOnlyIcon (ActUp_PrgRsc,PrgRsc_RESOURCE_SECTION_ID,
PrgRsc_PutParams,&Resource->RscCod,
PrgRsc_PutParams,&Resource->Rsc.Cod,
"arrow-up.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-up.svg",Ico_BLACK,Txt_Movement_not_allowed);
/***** Put icon to move down the item *****/
if (PrgRsc_CheckIfMoveDownIsAllowed (NumRsc,NumResources))
if (NumRsc < NumResources - 1)
Lay_PutContextualLinkOnlyIcon (ActDwnPrgRsc,PrgRsc_RESOURCE_SECTION_ID,
PrgRsc_PutParams,&Resource->RscCod,
PrgRsc_PutParams,&Resource->Rsc.Cod,
"arrow-down.svg",Ico_BLACK);
else
Ico_PutIconOff ("arrow-down.svg",Ico_BLACK,Txt_Movement_not_allowed);
@ -569,7 +580,7 @@ void PrgRsc_ReqRemResource (void)
Prg_GetListItems ();
/***** Get data of the item resource from database *****/
Resource.RscCod = PrgRsc_GetParamRscCod ();
Resource.Rsc.Cod = PrgRsc_GetParamRscCod ();
PrgRsc_GetDataOfResourceByCod (&Resource);
if (Resource.ItmCod <= 0)
Err_WrongResourceExit ();
@ -578,7 +589,7 @@ void PrgRsc_ReqRemResource (void)
Ale_CreateAlert (Ale_QUESTION,PrgRsc_RESOURCE_SECTION_ID,
Txt_Do_you_really_want_to_remove_the_resource_X,
Resource.Title);
PrgSrc_RscCodToBeRemoved = Resource.RscCod;
PrgSrc_RscCodToBeRemoved = Resource.Rsc.Cod;
/***** Get the code of the program item *****/
ItmCodBeforeForm = Resource.ItmCod;
@ -609,7 +620,7 @@ void PrgRsc_RemoveResource (void)
Prg_GetListItems ();
/***** Get data of the item resource from database *****/
Resource.RscCod = PrgRsc_GetParamRscCod ();
Resource.Rsc.Cod = PrgRsc_GetParamRscCod ();
PrgRsc_GetDataOfResourceByCod (&Resource);
if (Resource.ItmCod <= 0)
Err_WrongResourceExit ();
@ -659,13 +670,13 @@ static void PrgRsc_HideOrUnhideResource (bool Hide)
Prg_GetListItems ();
/***** Get data of the item resource from database *****/
Resource.RscCod = PrgRsc_GetParamRscCod ();
Resource.Rsc.Cod = PrgRsc_GetParamRscCod ();
PrgRsc_GetDataOfResourceByCod (&Resource);
if (Resource.ItmCod <= 0)
Err_WrongResourceExit ();
/***** Hide/unhide item resource *****/
Prg_DB_HideOrUnhideResource (Resource.RscCod,Hide);
Prg_DB_HideOrUnhideResource (Resource.Rsc.Cod,Hide);
/***** Get the code of the program item *****/
ItmCodBeforeForm = Resource.ItmCod;
@ -681,32 +692,111 @@ static void PrgRsc_HideOrUnhideResource (bool Hide)
}
/*****************************************************************************/
/********************* Check if resource can be moved up *********************/
/**************************** Move up/down resource **************************/
/*****************************************************************************/
static bool PrgRsc_CheckIfMoveUpIsAllowed (unsigned NumRsc)
{
/***** Trivial check: if resource is the first one, move up is not allowed *****/
return (NumRsc != 0);
}
/*****************************************************************************/
/******************** Check if resource can be moved down ********************/
/*****************************************************************************/
static bool PrgRsc_CheckIfMoveDownIsAllowed (unsigned NumRsc,
unsigned NumResources)
{
/***** Trivial check: if resource is the last one, move up is not allowed *****/
return (NumRsc < NumResources - 1);
}
void PrgRsc_MoveUpResource (void)
{
PrgRsc_MoveUpDownResource (PrgRsc_MOVE_UP);
}
void PrgRsc_MoveDownResource (void)
{
PrgRsc_MoveUpDownResource (PrgRsc_MOVE_DOWN);
}
static void PrgRsc_MoveUpDownResource (PrgRsc_MoveUpDown_t UpDown)
{
extern const char *Txt_Movement_not_allowed;
struct PrgRsc_Resource Resource;
struct PrgRsc_Rsc Rsc2;
long ItmCodBeforeForm;
unsigned FormLevel;
struct Prg_ItemRange ToHighlight;
bool Success = false;
static unsigned (*GetOtherRscInd[PrgRsc_NUM_MOVEMENTS_UP_DOWN])(long ItmCod,unsigned RscInd) =
{
[PrgRsc_MOVE_UP ] = Prg_DB_GetRscIndBefore,
[PrgRsc_MOVE_DOWN] = Prg_DB_GetRscIndAfter,
};
/***** Get list of program items *****/
Prg_GetListItems ();
/***** Get data of the item resource from database *****/
Resource.Rsc.Cod = PrgRsc_GetParamRscCod ();
PrgRsc_GetDataOfResourceByCod (&Resource);
if (Resource.ItmCod <= 0)
Err_WrongResourceExit ();
/***** Move up/down resource *****/
if ((Rsc2.Ind = GetOtherRscInd[UpDown] (Resource.ItmCod,Resource.Rsc.Ind))) // 0 ==> movement not allowed
{
/* Get the other resource code */
Rsc2.Cod = Prg_DB_GetRscCodFromRscInd (Resource.ItmCod,Rsc2.Ind);
/* Exchange subtrees */
Success = PrgRsc_ExchangeResources (&Resource.Rsc,&Rsc2);
}
if (!Success)
Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed);
/***** Get the code of the program item *****/
ItmCodBeforeForm = Resource.ItmCod;
FormLevel = Prg_GetLevelFromNumItem (Prg_GetNumItemFromItmCod (Resource.ItmCod));
/***** Show current program items, if any *****/
Prg_SetItemRangeEmpty (&ToHighlight);
Prg_ShowAllItems (Prg_PUT_FORM_CHANGE_ITEM,
&ToHighlight,-1L,ItmCodBeforeForm,FormLevel);
/***** Free list of program items *****/
Prg_FreeListItems ();
}
/*****************************************************************************/
/**** Exchange the order of two consecutive subtrees in a course program *****/
/*****************************************************************************/
// Return true if success
static bool PrgRsc_ExchangeResources (const struct PrgRsc_Rsc *Rsc1,
const struct PrgRsc_Rsc *Rsc2)
{
if (Rsc1->Ind > 0 && // Indexes should be in the range [1, 2,...]
Rsc2->Ind > 0)
{
/***** Lock table to make the move atomic *****/
Prg_DB_LockTableResources ();
/***** Exchange indexes of items *****/
// This implementation works with non continuous indexes
/*
Example:
Rsc1->Ind = 5
Rsc2->Ind = 17
Step 1 Step 2 Step 3 (Equivalent to)
+-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+
|Rsc.Ind|Rsc.Cod| |Rsc.Ind|Rsc.Cod| |Rsc.Ind|Rsc.Cod| |Rsc.Ind|Rsc.Cod| |Rsc.Ind|Rsc.Cod|
+-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+
| 5 | 218 | | 5 | 218 |-->|--> 17 | 218 | | 17 | 218 | | 5 | 240 |
| 17 | 240 |-->|-->-17 | 240 | | -17 | 240 |-->|--> 5 | 240 | | 17 | 218 |
+-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+
*/
/* Step 1: Change second index to negative,
necessary to preserve unique index (ItmCod,RscInd) */
Prg_DB_UpdateRscInd (Rsc2->Cod,-(int) Rsc2->Ind);
/* Step 2: Change first index */
Prg_DB_UpdateRscInd (Rsc1->Cod, (int) Rsc2->Ind);
/* Step 3: Change second index */
Prg_DB_UpdateRscInd (Rsc2->Cod, (int) Rsc1->Ind);
/***** Unlock table *****/
DB_UnlockTables ();
return true; // Success
}
return false; // No success
}

View File

@ -40,10 +40,16 @@
#define PrgRsc_MAX_CHARS_PROGRAM_RESOURCE_TITLE (128 - 1) // 127
#define PrgRsc_MAX_BYTES_PROGRAM_RESOURCE_TITLE ((PrgRsc_MAX_CHARS_PROGRAM_RESOURCE_TITLE + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
struct PrgRsc_Rsc
{
long Cod;
unsigned Ind; // 1, 2, 3...
};
struct PrgRsc_Resource
{
long ItmCod;
long RscCod;
struct PrgRsc_Rsc Rsc;
bool Hidden;
char Title[PrgRsc_MAX_BYTES_PROGRAM_RESOURCE_TITLE + 1];
};