From ea15787436d01316edb0931a0d34765dfa626fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Mon, 25 Mar 2019 19:05:10 +0100 Subject: [PATCH] Version18.88 --- css/{swad18.87.css => swad18.88.css} | 11 +- js/{swad18.85.js => swad18.88.js} | 13 +- swad_action.c | 4 +- swad_agenda.c | 4 +- swad_alert.c | 32 ++- swad_alert.h | 2 +- swad_assignment.c | 4 +- swad_attendance.c | 4 +- swad_box.c | 12 +- swad_changelog.h | 10 +- swad_exam.c | 378 +++++++++++++++------------ swad_exam.h | 18 +- swad_game.c | 4 +- swad_global.c | 1 + swad_global.h | 14 +- swad_icon.c | 8 +- swad_icon.h | 4 +- swad_layout.c | 9 +- swad_notice.c | 35 ++- swad_notice.h | 4 + swad_project.c | 4 +- swad_survey.c | 4 +- swad_text.c | 21 -- swad_timeline.c | 11 +- 24 files changed, 348 insertions(+), 263 deletions(-) rename css/{swad18.87.css => swad18.88.css} (99%) rename js/{swad18.85.js => swad18.88.js} (99%) diff --git a/css/swad18.87.css b/css/swad18.88.css similarity index 99% rename from css/swad18.87.css rename to css/swad18.88.css index 107323ec..d14ca548 100644 --- a/css/swad18.87.css +++ b/css/swad18.88.css @@ -1715,9 +1715,8 @@ a:hover /* Default ==> underlined */ { display:inline-block; box-sizing:border-box; - margin:5px 0 18px 0; - padding:12px; - background-color:rgba(255,255,255,0.95); + margin:5px 0; + padding:8px 12px 20px 12px; border-width:1px; border-style:solid; border-color:#C0C0C0; @@ -1725,6 +1724,12 @@ a:hover /* Default ==> underlined */ box-shadow:2px 5px 15px #888; text-align:center; overflow:hidden; + background-color:#ddecf1; + animation: fadein 2s linear forwards; + } +@keyframes fadein + { + to {background-color:white;} } .FRAME_ICO { diff --git a/js/swad18.85.js b/js/swad18.88.js similarity index 99% rename from js/swad18.85.js rename to js/swad18.88.js index 6414e3e4..319ce898 100644 --- a/js/swad18.85.js +++ b/js/swad18.88.js @@ -1346,6 +1346,7 @@ function DrawMonth (id,FirstDayOfWeek,YearToDraw,MonthToDraw,CurrentMonth,Curren var Yea = YearToDraw; var Mon = MonthToDraw; var Day; + var ExaCod; var StrMon; var StrDay; var StrDate; @@ -1484,12 +1485,13 @@ function DrawMonth (id,FirstDayOfWeek,YearToDraw,MonthToDraw,CurrentMonth,Curren Day == LstExamAnnouncements[NumExamAnnouncement].Day) { ThisDayHasEvent = true; if (!PrintView) { + ExaCod = LstExamAnnouncements[NumExamAnnouncement].ExaCod; StrMon = ((Mon < 10) ? '0' : '') + Mon; StrDay = ((Day < 10) ? '0' : '') + Day; - StrDate = Yea + '-' + StrMon + '-' + StrDay; - TextForDay = STR_EXAM + ': ' + StrDate; + StrDate = Yea + StrMon + StrDay; // YYYYMMDD + TextForDay = STR_EXAM; } - break; + break; // Only last exam in the day (list is ordered from more recent to older) } /***** Write the box with the day *****/ @@ -1504,7 +1506,10 @@ function DrawMonth (id,FirstDayOfWeek,YearToDraw,MonthToDraw,CurrentMonth,Curren if (!PrintView && ThisDayHasEvent) { FormIdNum++; FormId = id + '_event_' + FormIdNum; - Gbl_HTMLContent += '
' + + Gbl_HTMLContent += '' + FormEventParams + ' Ale_MAX_ALERTS) Lay_ShowErrorAndExit ("Too many alerts."); + i = Gbl.Alerts.Num; Gbl.Alerts.Num++; - Gbl.Alerts.List[Gbl.Alerts.Num - 1].Type = Type; + Gbl.Alerts.List[i].Type = Type; - Gbl.Alerts.List[Gbl.Alerts.Num - 1].Section = NULL; + Gbl.Alerts.List[i].Section = NULL; if (Section) if (Section[0]) - Gbl.Alerts.List[Gbl.Alerts.Num - 1].Section = Section; + if (asprintf (&Gbl.Alerts.List[i].Section,"%s", + Section) < 0) + Lay_NotEnoughMemoryExit (); va_start (ap,fmt); - NumBytesPrinted = vasprintf (&Gbl.Alerts.List[Gbl.Alerts.Num - 1].Text,fmt,ap); + NumBytesPrinted = vasprintf (&Gbl.Alerts.List[i].Text,fmt,ap); va_end (ap); if (NumBytesPrinted < 0) // If memory allocation wasn't possible, @@ -111,7 +116,7 @@ void Ale_CreateAlert (Ale_AlertType_t Type,const char *Section, /***************** Get current number of delayed alerts **********************/ /*****************************************************************************/ -unsigned Ale_GetNumAlerts (void) +size_t Ale_GetNumAlerts (void) { return Gbl.Alerts.Num; } @@ -174,7 +179,6 @@ static void Ale_ResetAlert (size_t i) { /***** Reset i-esim alert *****/ Gbl.Alerts.List[i].Type = Ale_NONE; // Reset alert - Gbl.Alerts.List[i].Section = NULL; /***** Free memory allocated for text *****/ if (Gbl.Alerts.List[i].Text) @@ -182,6 +186,13 @@ static void Ale_ResetAlert (size_t i) free ((void *) Gbl.Alerts.List[i].Text); Gbl.Alerts.List[i].Text = NULL; } + + /***** Free memory allocated for section *****/ + if (Gbl.Alerts.List[i].Section) + { + free ((void *) Gbl.Alerts.List[i].Section); + Gbl.Alerts.List[i].Section = NULL; + } } /***** Set number of alerts to 0 @@ -218,14 +229,17 @@ void Ale_ShowAlerts (const char *Section) { size_t i; bool ShowAlert; + size_t NumAlerts = Ale_GetNumAlerts (); for (i = 0; - i < Gbl.Alerts.Num; + i < NumAlerts; i++) if (Gbl.Alerts.List[i].Type != Ale_NONE) { - ShowAlert = Section ? (Gbl.Alerts.List[i].Section == Section) : - true; + if (Section) + ShowAlert = (bool) !strcmp (Gbl.Alerts.List[i].Section,Section); + else + ShowAlert = false; if (ShowAlert) { diff --git a/swad_alert.h b/swad_alert.h index 55b49a2d..4d451725 100644 --- a/swad_alert.h +++ b/swad_alert.h @@ -60,7 +60,7 @@ typedef enum void Ale_CreateAlert (Ale_AlertType_t Type,const char *Section, const char *fmt,...); -unsigned Ale_GetNumAlerts (void); +size_t Ale_GetNumAlerts (void); Ale_AlertType_t Ale_GetTypeOfLastAlert (void); const char *Ale_GetTextOfLastAlert (void); diff --git a/swad_assignment.c b/swad_assignment.c index 3a91e6e0..d0cf23ac 100644 --- a/swad_assignment.c +++ b/swad_assignment.c @@ -546,9 +546,9 @@ static void Asg_PutFormsToRemEditOneAsg (long AsgCod,bool Hidden) /***** Put form to hide/show assignment *****/ if (Hidden) - Ico_PutContextualIconToUnhide (ActShoAsg,Asg_PutParams); + Ico_PutContextualIconToUnhide (ActShoAsg,NULL,Asg_PutParams); else - Ico_PutContextualIconToHide (ActHidAsg,Asg_PutParams); + Ico_PutContextualIconToHide (ActHidAsg,NULL,Asg_PutParams); /***** Put form to edit assignment *****/ Ico_PutContextualIconToEdit (ActEdiOneAsg,Asg_PutParams); diff --git a/swad_attendance.c b/swad_attendance.c index 988cdcd1..fc6f69ae 100644 --- a/swad_attendance.c +++ b/swad_attendance.c @@ -570,9 +570,9 @@ static void Att_PutFormsToRemEditOneAttEvent (long AttCod,bool Hidden) /***** Put form to hide/show attendance event *****/ if (Hidden) - Ico_PutContextualIconToUnhide (ActShoAtt,Att_PutParams); + Ico_PutContextualIconToUnhide (ActShoAtt,NULL,Att_PutParams); else - Ico_PutContextualIconToHide (ActHidAtt,Att_PutParams); + Ico_PutContextualIconToHide (ActHidAtt,NULL,Att_PutParams); /***** Put form to edit attendance event *****/ Ico_PutContextualIconToEdit (ActEdiOneAtt,Att_PutParams); diff --git a/swad_box.c b/swad_box.c index aebf86d6..1c2db4d6 100644 --- a/swad_box.c +++ b/swad_box.c @@ -58,9 +58,9 @@ extern struct Globals Gbl; /*****************************************************************************/ static void Box_StartBoxInternal (const char *Width,const char *Title, - void (*FunctionToDrawContextualIcons) (void), - const char *HelpLink,Box_Closable_t Closable, - const char *ClassFrame); + void (*FunctionToDrawContextualIcons) (void), + const char *HelpLink,Box_Closable_t Closable, + const char *ClassFrame); /*****************************************************************************/ /******************* Start and end a table with rounded box ******************/ @@ -109,9 +109,9 @@ void Box_StartBoxShadow (const char *Width,const char *Title, } static void Box_StartBoxInternal (const char *Width,const char *Title, - void (*FunctionToDrawContextualIcons) (void), - const char *HelpLink,Box_Closable_t Closable, - const char *ClassFrame) + void (*FunctionToDrawContextualIcons) (void), + const char *HelpLink,Box_Closable_t Closable, + const char *ClassFrame) { extern const char *Txt_Help; extern const char *Txt_Close; diff --git a/swad_changelog.h b/swad_changelog.h index 9a74d972..707c7d37 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -443,9 +443,6 @@ Lo de mutear anuncios, en principio prefiero hacer una opci // TODO: Actualizar ayuda en GitHub, por ejemplo Preferencias ahora es Ajustes. -// TODO: Change in usability of Announcements of exams, suggested by Javier Fernández Baldomero. -// TODO: Al pulsar sobre una convocatoria de examen --> ir a la sección de esa convocatoria/aviso en lugar de mostrarlo repetido y destacado arriba - // TODO: Allow timeline posting only for users belonging to courses or admins to avoid user who create accounts only to post // TODO: Ver cómo recibir un fichero desde el cliente (SWADroid) en gsoap @@ -469,10 +466,11 @@ En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 18.87.1 (2019-03-24)" -#define CSS_FILE "swad18.87.css" -#define JS_FILE "swad18.85.js" +#define Log_PLATFORM_VERSION "SWAD 18.88 (2019-03-25)" +#define CSS_FILE "swad18.88.css" +#define JS_FILE "swad18.88.js" /* + Version 18.88: Mar 25, 2019 Change in usability of exam announcements, suggested by Mancia Anguita López and Javier Fernández Baldomero. (241089 lines) Version 18.87.1: Mar 24, 2019 Code refactoring in notices. (241011 lines) Version 18.87: Mar 24, 2019 Change in usability of notices. (240997 lines) Version 18.86.3: Mar 24, 2019 Optimization in suggestion of users to follow. (240965 lines) diff --git a/swad_exam.c b/swad_exam.c index 2af7f265..ef5dff50 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -75,15 +75,16 @@ extern struct Globals Gbl; static long Exa_GetParamsExamAnnouncement (void); static void Exa_AllocMemExamAnnouncement (void); static void Exa_UpdateNumUsrsNotifiedByEMailAboutExamAnnouncement (long ExaCod,unsigned NumUsrsToBeNotifiedByEMail); -static void Exa_ListExamAnnouncementsEdit (void); static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement); static void Exa_PutIconToCreateNewExamAnnouncement (void); static void Exa_PutButtonToCreateNewExamAnnouncement (void); static long Exa_AddExamAnnouncementToDB (void); -static void Exa_ModifyExamAnnouncementInDB (void); -static void Exa_GetDataExamAnnouncementFromDB (void); -static void Exa_ShowExamAnnouncement (Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement); +static void Exa_ModifyExamAnnouncementInDB (long ExaCod); +static void Exa_GetDataExamAnnouncementFromDB (long ExaCod); +static void Exa_ShowExamAnnouncement (long ExaCod, + Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement, + bool HighLight); static void Exa_PutIconsExamAnnouncement (void); static void Exa_PutParamExaCodToEdit (void); static long Exa_GetParamExaCod (void); @@ -96,18 +97,21 @@ static void Exa_GetNotifContentExamAnnouncement (char **ContentStr); void Exa_PutFrmEditAExamAnnouncement (void) { + long ExaCod; + /***** Allocate memory for the exam announcement *****/ Exa_AllocMemExamAnnouncement (); /***** Get the code of the exam announcement *****/ - Gbl.ExamAnns.ExaDat.ExaCod = Exa_GetParamsExamAnnouncement (); + ExaCod = Exa_GetParamsExamAnnouncement (); - if (Gbl.ExamAnns.ExaDat.ExaCod > 0) // -1 indicates that this is a new exam announcement + if (ExaCod > 0) // -1 indicates that this is a new exam announcement /***** Read exam announcement from the database *****/ - Exa_GetDataExamAnnouncementFromDB (); + Exa_GetDataExamAnnouncementFromDB (ExaCod); /***** Show exam announcement *****/ - Exa_ShowExamAnnouncement (Exa_FORM_VIEW); + Exa_ShowExamAnnouncement (ExaCod,Exa_FORM_VIEW, + false); // Don't highlight /***** Free memory of the exam announcement *****/ Exa_FreeMemExamAnnouncement (); @@ -270,46 +274,56 @@ void Exa_FreeMemExamAnnouncement (void) void Exa_ReceiveExamAnnouncement1 (void) { + extern const char *Txt_Created_new_announcement_of_exam; + extern const char *Txt_The_announcement_of_exam_has_been_successfully_updated; + long ExaCod; + bool NewExamAnnouncement; + char *Anchor = NULL; + /***** Allocate memory for the exam announcement *****/ Exa_AllocMemExamAnnouncement (); /***** Get parameters of the exam announcement *****/ - Gbl.ExamAnns.ExaDat.ExaCod = Exa_GetParamsExamAnnouncement (); - Gbl.ExamAnns.NewExamAnnouncement = (Gbl.ExamAnns.ExaDat.ExaCod < 0); + ExaCod = Exa_GetParamsExamAnnouncement (); + NewExamAnnouncement = (ExaCod < 0); /***** Add the exam announcement to the database and read it again from the database *****/ - if (Gbl.ExamAnns.NewExamAnnouncement) - Gbl.ExamAnns.ExaDat.ExaCod = Exa_AddExamAnnouncementToDB (); + if (NewExamAnnouncement) + Gbl.ExamAnns.NewExaCod = ExaCod = Exa_AddExamAnnouncementToDB (); else - Exa_ModifyExamAnnouncementInDB (); + Exa_ModifyExamAnnouncementInDB (ExaCod); /***** Free memory of the exam announcement *****/ Exa_FreeMemExamAnnouncement (); + + + /***** Create alert to show the change made *****/ + Exa_SetAnchorStr (ExaCod,&Anchor); + Ale_CreateAlert (Ale_SUCCESS,Anchor, + NewExamAnnouncement ? Txt_Created_new_announcement_of_exam : + Txt_The_announcement_of_exam_has_been_successfully_updated); + Exa_FreeAnchorStr (Anchor); + + /***** Set exam to be highlighted *****/ + Gbl.ExamAnns.HighlightExaCod = ExaCod; } void Exa_ReceiveExamAnnouncement2 (void) { - extern const char *Txt_Created_new_announcement_of_exam; - extern const char *Txt_The_announcement_of_exam_has_been_successfully_updated; unsigned NumUsrsToBeNotifiedByEMail; struct TL_Publication SocPub; - /***** Show message *****/ - Ale_ShowAlert (Ale_SUCCESS, - Gbl.ExamAnns.NewExamAnnouncement ? Txt_Created_new_announcement_of_exam : - Txt_The_announcement_of_exam_has_been_successfully_updated); - /***** Notify by email about the new exam announcement *****/ - if ((NumUsrsToBeNotifiedByEMail = Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_EXAM_ANNOUNCEMENT,Gbl.ExamAnns.ExaDat.ExaCod))) - Exa_UpdateNumUsrsNotifiedByEMailAboutExamAnnouncement (Gbl.ExamAnns.ExaDat.ExaCod,NumUsrsToBeNotifiedByEMail); + if ((NumUsrsToBeNotifiedByEMail = Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_EXAM_ANNOUNCEMENT,Gbl.ExamAnns.HighlightExaCod))) + Exa_UpdateNumUsrsNotifiedByEMailAboutExamAnnouncement (Gbl.ExamAnns.HighlightExaCod,NumUsrsToBeNotifiedByEMail); /***** Create a new social note about the new exam announcement *****/ - TL_StoreAndPublishNote (TL_NOTE_EXAM_ANNOUNCEMENT,Gbl.ExamAnns.ExaDat.ExaCod,&SocPub); + TL_StoreAndPublishNote (TL_NOTE_EXAM_ANNOUNCEMENT,Gbl.ExamAnns.HighlightExaCod,&SocPub); /***** Update RSS of current course *****/ RSS_UpdateRSSFileForACrs (&Gbl.CurrentCrs.Crs); - /***** Show exam announcement *****/ + /***** Show exam announcements *****/ Exa_ListExamAnnouncementsEdit (); } @@ -333,18 +347,21 @@ static void Exa_UpdateNumUsrsNotifiedByEMailAboutExamAnnouncement (long ExaCod,u void Exa_PrintExamAnnouncement (void) { + long ExaCod; + /***** Allocate memory for the exam announcement *****/ Exa_AllocMemExamAnnouncement (); /***** Get the code of the exam announcement *****/ - if ((Gbl.ExamAnns.ExaDat.ExaCod = Exa_GetParamExaCod ()) <= 0) + if ((ExaCod = Exa_GetParamExaCod ()) <= 0) Lay_ShowErrorAndExit ("Code of exam announcement is missing."); /***** Read exam announcement from the database *****/ - Exa_GetDataExamAnnouncementFromDB (); + Exa_GetDataExamAnnouncementFromDB (ExaCod); /***** Show exam announcement *****/ - Exa_ShowExamAnnouncement (Exa_PRINT_VIEW); + Exa_ShowExamAnnouncement (ExaCod,Exa_PRINT_VIEW, + false); // Don't highlight /***** Free memory of the exam announcement *****/ Exa_FreeMemExamAnnouncement (); @@ -358,9 +375,10 @@ void Exa_ReqRemoveExamAnnouncement (void) { extern const char *Txt_Do_you_really_want_to_remove_the_following_announcement_of_exam; extern const char *Txt_Remove; + long ExaCod; /***** Get the code of the exam announcement *****/ - if ((Gbl.ExamAnns.ExaDat.ExaCod = Exa_GetParamExaCod ()) <= 0) + if ((ExaCod = Exa_GetParamExaCod ()) <= 0) Lay_ShowErrorAndExit ("Code of exam announcement is missing."); /***** Show question and button to remove exam announcement *****/ @@ -369,11 +387,13 @@ void Exa_ReqRemoveExamAnnouncement (void) /* Show announcement */ Exa_AllocMemExamAnnouncement (); - Exa_GetDataExamAnnouncementFromDB (); - Exa_ShowExamAnnouncement (Exa_NORMAL_VIEW); + Exa_GetDataExamAnnouncementFromDB (ExaCod); + Exa_ShowExamAnnouncement (ExaCod,Exa_NORMAL_VIEW, + false); // Don't highlight Exa_FreeMemExamAnnouncement (); /* End alert */ + Ale_ShowAlertAndButton2 (ActRemExaAnn,NULL,NULL,Exa_PutParamExaCodToEdit, Btn_REMOVE_BUTTON,Txt_Remove); } @@ -426,9 +446,11 @@ void Exa_RemoveExamAnnouncement2 (void) // This function is splitted into a-priori and a-posteriori functions // in order to view updated links in month of left column -void Exa_HideExamAnnouncement1 (void) +void Exa_HideExamAnnouncement (void) { + extern const char *Txt_The_announcement_of_exam_is_now_hidden; long ExaCod; + char *Anchor = NULL; /***** Get the code of the exam announcement *****/ if ((ExaCod = Exa_GetParamExaCod ()) <= 0) @@ -440,17 +462,15 @@ void Exa_HideExamAnnouncement1 (void) " WHERE ExaCod=%ld AND CrsCod=%ld", (unsigned) Exa_HIDDEN_EXAM_ANNOUNCEMENT, ExaCod,Gbl.CurrentCrs.Crs.CrsCod); - } -void Exa_HideExamAnnouncement2 (void) - { - extern const char *Txt_The_announcement_of_exam_is_now_hidden; + /***** Set exam to be highlighted *****/ + Gbl.ExamAnns.HighlightExaCod = ExaCod; - /***** Write message to show the change made *****/ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_announcement_of_exam_is_now_hidden); - - /***** Show exam announcements again *****/ - Exa_ListExamAnnouncementsEdit (); + /***** Create alert to show the change made *****/ + Exa_SetAnchorStr (ExaCod,&Anchor); + Ale_CreateAlert (Ale_SUCCESS,Anchor, + Txt_The_announcement_of_exam_is_now_hidden); + Exa_FreeAnchorStr (Anchor); } /*****************************************************************************/ @@ -459,9 +479,11 @@ void Exa_HideExamAnnouncement2 (void) // This function is splitted into a-priori and a-posteriori functions // in order to view updated links in month of left column -void Exa_UnhideExamAnnouncement1 (void) +void Exa_UnhideExamAnnouncement (void) { + extern const char *Txt_The_announcement_of_exam_is_now_visible; long ExaCod; + char *Anchor = NULL; /***** Get the code of the exam announcement *****/ if ((ExaCod = Exa_GetParamExaCod ()) <= 0) @@ -473,17 +495,15 @@ void Exa_UnhideExamAnnouncement1 (void) " WHERE ExaCod=%ld AND CrsCod=%ld", (unsigned) Exa_VISIBLE_EXAM_ANNOUNCEMENT, ExaCod,Gbl.CurrentCrs.Crs.CrsCod); - } -void Exa_UnhideExamAnnouncement2 (void) - { - extern const char *Txt_The_announcement_of_exam_is_now_visible; + /***** Set exam to be highlighted *****/ + Gbl.ExamAnns.HighlightExaCod = ExaCod; - /***** Write message to show the change made *****/ - Ale_ShowAlert (Ale_SUCCESS,Txt_The_announcement_of_exam_is_now_visible); - - /***** Show exam announcements again *****/ - Exa_ListExamAnnouncementsEdit (); + /***** Create alert to show the change made *****/ + Exa_SetAnchorStr (ExaCod,&Anchor); + Ale_CreateAlert (Ale_SUCCESS,Anchor, + Txt_The_announcement_of_exam_is_now_visible); + Exa_FreeAnchorStr (Anchor); } /*****************************************************************************/ @@ -505,7 +525,7 @@ void Exa_ListExamAnnouncementsSee (void) /********** List all the exam announcements to edit or remove them ***********/ /*****************************************************************************/ -static void Exa_ListExamAnnouncementsEdit (void) +void Exa_ListExamAnnouncementsEdit (void) { Exa_ListExamAnnouncements (Exa_NORMAL_VIEW); } @@ -527,9 +547,9 @@ void Exa_GetExaCodToHighlight (void) void Exa_GetDateToHighlight (void) { - /***** Get the date (in YYYY-MM-DD format) + /***** Get the date (in YYYYMMDD format) of the exam announcements to highlight *****/ - Par_GetParToText ("Date",Gbl.ExamAnns.HighlightDate,4 + 1 + 2 + 1 + 2); + Par_GetParToText ("Date",Gbl.ExamAnns.HighlightDate,4 + 2 + 2); } /*****************************************************************************/ @@ -539,7 +559,6 @@ void Exa_GetDateToHighlight (void) static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement) { extern const char *Hlp_ASSESSMENT_Announcements; - extern const char *Txt_All_announcements_of_exams; extern const char *Txt_Announcements_of_exams; extern const char *Txt_No_announcements_of_exams_of_X; char SubQueryStatus[64]; @@ -547,6 +566,8 @@ static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewEx MYSQL_ROW row; unsigned long NumExaAnn; unsigned long NumExaAnns; + long ExaCod; + bool HighLight; bool ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH || Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); @@ -558,84 +579,6 @@ static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewEx sprintf (SubQueryStatus,"Status=%u", (unsigned) Exa_VISIBLE_EXAM_ANNOUNCEMENT); - /***** Show one highlighted exam announcement *****/ - if (Gbl.ExamAnns.HighlightExaCod > 0) - { - /***** Get one exam announcement from database *****/ - NumExaAnns = DB_QuerySELECT (&mysql_res,"can not get exam announcements" - " in this course for listing", - "SELECT ExaCod" - " FROM exam_announcements" - " WHERE ExaCod=%ld" - " AND CrsCod=%ld AND %s", - Gbl.ExamAnns.HighlightExaCod, - Gbl.CurrentCrs.Crs.CrsCod,SubQueryStatus); - - /***** List the existing exam announcements *****/ - for (NumExaAnn = 0; - NumExaAnn < NumExaAnns; - NumExaAnn++) - { - /***** Get the code of the exam announcement (row[0]) *****/ - row = mysql_fetch_row (mysql_res); - - if (sscanf (row[0],"%ld",&Gbl.ExamAnns.ExaDat.ExaCod) != 1) - Lay_ShowErrorAndExit ("Wrong code of exam announcement."); - - /***** Allocate memory for the exam announcement *****/ - Exa_AllocMemExamAnnouncement (); - - /***** Read the data of the exam announcement *****/ - Exa_GetDataExamAnnouncementFromDB (); - - /***** Show exam announcement *****/ - Exa_ShowExamAnnouncement (TypeViewExamAnnouncement); - - /***** Free memory of the exam announcement *****/ - Exa_FreeMemExamAnnouncement (); - } - } - - /***** Show highlighted exam announcements of a date *****/ - if (Gbl.ExamAnns.HighlightDate[0]) - { - /***** Get exam announcements (the most recent first) - in current course for a date from database *****/ - NumExaAnns = DB_QuerySELECT (&mysql_res,"can not get exam announcements" - " in this course for listing", - "SELECT ExaCod" - " FROM exam_announcements" - " WHERE CrsCod=%ld AND %s" - " AND DATE(ExamDate)='%s'" - " ORDER BY ExamDate DESC", - Gbl.CurrentCrs.Crs.CrsCod,SubQueryStatus, - Gbl.ExamAnns.HighlightDate); - - /***** List the existing exam announcements *****/ - for (NumExaAnn = 0; - NumExaAnn < NumExaAnns; - NumExaAnn++) - { - /***** Get the code of the exam announcement (row[0]) *****/ - row = mysql_fetch_row (mysql_res); - - if (sscanf (row[0],"%ld",&Gbl.ExamAnns.ExaDat.ExaCod) != 1) - Lay_ShowErrorAndExit ("Wrong code of exam announcement."); - - /***** Allocate memory for the exam announcement *****/ - Exa_AllocMemExamAnnouncement (); - - /***** Read the data of the exam announcement *****/ - Exa_GetDataExamAnnouncementFromDB (); - - /***** Show exam announcement *****/ - Exa_ShowExamAnnouncement (TypeViewExamAnnouncement); - - /***** Free memory of the exam announcement *****/ - Exa_FreeMemExamAnnouncement (); - } - } - /***** Get exam announcements (the most recent first) in current course from database *****/ NumExaAnns = DB_QuerySELECT (&mysql_res,"can not get exam announcements" @@ -647,10 +590,7 @@ static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewEx Gbl.CurrentCrs.Crs.CrsCod,SubQueryStatus); /***** Start box *****/ - Box_StartBox (NULL, - (Gbl.ExamAnns.HighlightExaCod > 0 || - Gbl.ExamAnns.HighlightDate[0]) ? Txt_All_announcements_of_exams : - Txt_Announcements_of_exams, + Box_StartBox (NULL,Txt_Announcements_of_exams, ICanEdit ? Exa_PutIconToCreateNewExamAnnouncement : NULL, Hlp_ASSESSMENT_Announcements,Box_NOT_CLOSABLE); @@ -668,17 +608,27 @@ static void Exa_ListExamAnnouncements (Exa_TypeViewExamAnnouncement_t TypeViewEx /***** Get the code of the exam announcement (row[0]) *****/ row = mysql_fetch_row (mysql_res); - if (sscanf (row[0],"%ld",&Gbl.ExamAnns.ExaDat.ExaCod) != 1) + if (sscanf (row[0],"%ld",&ExaCod) != 1) Lay_ShowErrorAndExit ("Wrong code of exam announcement."); /***** Allocate memory for the exam announcement *****/ Exa_AllocMemExamAnnouncement (); /***** Read the data of the exam announcement *****/ - Exa_GetDataExamAnnouncementFromDB (); + Exa_GetDataExamAnnouncementFromDB (ExaCod); /***** Show exam announcement *****/ - Exa_ShowExamAnnouncement (TypeViewExamAnnouncement); + HighLight = false; + if (ExaCod == Gbl.ExamAnns.HighlightExaCod) + HighLight = true; + else if (Gbl.ExamAnns.HighlightDate[0]) + { + if (!strcmp (Gbl.ExamAnns.ExaDat.ExamDate.YYYYMMDD, + Gbl.ExamAnns.HighlightDate)) + HighLight = true; + } + Exa_ShowExamAnnouncement (ExaCod,TypeViewExamAnnouncement, + HighLight); /***** Free memory of the exam announcement *****/ Exa_FreeMemExamAnnouncement (); @@ -767,7 +717,7 @@ static long Exa_AddExamAnnouncementToDB (void) /*************** Modify an exam announcement in the database *****************/ /*****************************************************************************/ -static void Exa_ModifyExamAnnouncementInDB (void) +static void Exa_ModifyExamAnnouncementInDB (long ExaCod) { /***** Modify exam announcement *****/ DB_QueryUPDATE ("can not update an exam announcement", @@ -795,7 +745,7 @@ static void Exa_ModifyExamAnnouncementInDB (void) Gbl.ExamAnns.ExaDat.MatRequired, Gbl.ExamAnns.ExaDat.MatAllowed, Gbl.ExamAnns.ExaDat.OtherInfo, - Gbl.ExamAnns.ExaDat.ExaCod); + ExaCod); } /*****************************************************************************/ @@ -811,14 +761,15 @@ void Exa_CreateListDatesOfExamAnnouncements (void) if (Gbl.DB.DatabaseIsOpen) { - /***** Get exam dates (no matter in what order) + /***** Get exam dates (ordered from more recent to older) of visible exam announcements in current course from database *****/ NumExaAnns = DB_QuerySELECT (&mysql_res,"can not get exam announcements" " in this course", - "SELECT DISTINCT(DATE(ExamDate))" + "SELECT ExaCod,DATE(ExamDate)" " FROM exam_announcements" - " WHERE CrsCod=%ld AND Status=%u", + " WHERE CrsCod=%ld AND Status=%u" + " ORDER BY ExamDate DESC", Gbl.CurrentCrs.Crs.CrsCod, (unsigned) Exa_VISIBLE_EXAM_ANNOUNCEMENT); @@ -828,7 +779,7 @@ void Exa_CreateListDatesOfExamAnnouncements (void) if (NumExaAnns) { /***** Allocate memory for the list *****/ - if ((Gbl.ExamAnns.Lst = (struct Date *) calloc (NumExaAnns,sizeof (struct Date))) == NULL) + if ((Gbl.ExamAnns.Lst = (struct Exa_ExamCodeAndDate *) calloc (NumExaAnns,sizeof (struct Exa_ExamCodeAndDate))) == NULL) Lay_NotEnoughMemoryExit (); /***** Get the dates of the existing exam announcements *****/ @@ -839,11 +790,14 @@ void Exa_CreateListDatesOfExamAnnouncements (void) /***** Get next exam announcement *****/ row = mysql_fetch_row (mysql_res); - /* Read the date of the exam (row[0]) */ - if (sscanf (row[0],"%04u-%02u-%02u", - &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].Year, - &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].Month, - &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].Day) != 3) + /* Get exam code (row[0]) */ + Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].ExaCod = Str_ConvertStrCodToLongCod (row[0]); + + /* Read the date of the exam (row[1]) */ + if (sscanf (row[1],"%04u-%02u-%02u", + &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].ExamDate.Year, + &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].ExamDate.Month, + &Gbl.ExamAnns.Lst[Gbl.ExamAnns.NumExaAnns].ExamDate.Day) != 3) Lay_ShowErrorAndExit ("Wrong date of exam."); /***** Increment number of elements in list *****/ @@ -874,7 +828,7 @@ void Exa_FreeListExamAnnouncements (void) /******** Read the data of an exam announcement from the database ************/ /*****************************************************************************/ -static void Exa_GetDataExamAnnouncementFromDB (void) +static void Exa_GetDataExamAnnouncementFromDB (long ExaCod) { MYSQL_RES *mysql_res; MYSQL_ROW row; @@ -891,7 +845,7 @@ static void Exa_GetDataExamAnnouncementFromDB (void) "CallDate,ExamDate,Duration,Place,ExamMode," "Structure,DocRequired,MatRequired,MatAllowed,OtherInfo" " FROM exam_announcements WHERE ExaCod=%ld", - Gbl.ExamAnns.ExaDat.ExaCod); + ExaCod); /***** The result of the query must have one row *****/ if (NumExaAnns != 1) @@ -927,14 +881,25 @@ static void Exa_GetDataExamAnnouncementFromDB (void) &Gbl.ExamAnns.ExaDat.CallDate.Year, &Gbl.ExamAnns.ExaDat.CallDate.Month, &Gbl.ExamAnns.ExaDat.CallDate.Day, - &Hour,&Minute,&Second) != 6) + &Hour, + &Minute, + &Second) != 6) Lay_ShowErrorAndExit ("Wrong date of exam announcement."); /* Date of exam (row[6]) */ if (sscanf (row[6],"%04u-%02u-%02u %02u:%02u:%02u", - &Gbl.ExamAnns.ExaDat.ExamDate.Year,&Gbl.ExamAnns.ExaDat.ExamDate.Month,&Gbl.ExamAnns.ExaDat.ExamDate.Day, - &Gbl.ExamAnns.ExaDat.StartTime.Hour,&Gbl.ExamAnns.ExaDat.StartTime.Minute,&Second) != 6) + &Gbl.ExamAnns.ExaDat.ExamDate.Year, + &Gbl.ExamAnns.ExaDat.ExamDate.Month, + &Gbl.ExamAnns.ExaDat.ExamDate.Day, + &Gbl.ExamAnns.ExaDat.StartTime.Hour, + &Gbl.ExamAnns.ExaDat.StartTime.Minute, + &Second) != 6) Lay_ShowErrorAndExit ("Wrong date of exam."); + snprintf (Gbl.ExamAnns.ExaDat.ExamDate.YYYYMMDD,sizeof (Gbl.ExamAnns.ExaDat.ExamDate.YYYYMMDD), + "%04u%02u%02u", + Gbl.ExamAnns.ExaDat.ExamDate.Year, + Gbl.ExamAnns.ExaDat.ExamDate.Month, + Gbl.ExamAnns.ExaDat.ExamDate.Day); /* Approximate duration (row[7]) */ if (sscanf (row[7],"%02u:%02u:%02u",&Gbl.ExamAnns.ExaDat.Duration.Hour,&Gbl.ExamAnns.ExaDat.Duration.Minute,&Second) != 3) @@ -976,7 +941,9 @@ static void Exa_GetDataExamAnnouncementFromDB (void) /************ Show a form with the data of an exam announcement **************/ /*****************************************************************************/ -static void Exa_ShowExamAnnouncement (Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement) +static void Exa_ShowExamAnnouncement (long ExaCod, + Exa_TypeViewExamAnnouncement_t TypeViewExamAnnouncement, + bool HighLight) { extern const char *Hlp_ASSESSMENT_Announcements_new_announcement; extern const char *Hlp_ASSESSMENT_Announcements_edit_announcement; @@ -1010,6 +977,10 @@ static void Exa_ShowExamAnnouncement (Exa_TypeViewExamAnnouncement_t TypeViewExa unsigned Year; unsigned Hour; unsigned Minute; + char *Anchor = NULL; + const char *Width; + void (*FunctionToDrawContextualIcons) (void); + const char *HelpLink; const char *ClassExaAnnouncement[Exa_NUM_VIEWS][Exa_NUM_STATUS] = { { // Exa_NORMAL_VIEW @@ -1047,21 +1018,41 @@ static void Exa_ShowExamAnnouncement (Exa_TypeViewExamAnnouncement_t TypeViewExa break; } + /***** Build anchor string *****/ + Exa_SetAnchorStr (ExaCod,&Anchor); + + /***** Start article *****/ + if (TypeViewExamAnnouncement == Exa_NORMAL_VIEW) + Lay_StartArticle (Anchor); + /***** Start box *****/ - Box_StartBox ("625px",NULL, - TypeViewExamAnnouncement == Exa_NORMAL_VIEW ? Exa_PutIconsExamAnnouncement : - NULL, - TypeViewExamAnnouncement == Exa_FORM_VIEW ? ((Gbl.ExamAnns.ExaDat.ExaCod > 0) ? Hlp_ASSESSMENT_Announcements_edit_announcement : - Hlp_ASSESSMENT_Announcements_new_announcement) : - NULL, - Box_NOT_CLOSABLE); + Width = "625px"; + Gbl.ExamAnns.Anchor = Anchor; // Used to put contextual icons + Gbl.ExamAnns.ExaCod = ExaCod; // Used to put contextual icons + FunctionToDrawContextualIcons = TypeViewExamAnnouncement == Exa_NORMAL_VIEW ? Exa_PutIconsExamAnnouncement : + NULL; + HelpLink = TypeViewExamAnnouncement == Exa_FORM_VIEW ? ((ExaCod > 0) ? Hlp_ASSESSMENT_Announcements_edit_announcement : + Hlp_ASSESSMENT_Announcements_new_announcement) : + NULL; + if (HighLight) + { + /* Show pending alerts */ + Ale_ShowAlerts (Anchor); + + /* Start highlighted box */ + Box_StartBoxShadow (Width,NULL,FunctionToDrawContextualIcons,HelpLink); + } + else // Don't highlight + /* Start normal box */ + Box_StartBox (Width,NULL,FunctionToDrawContextualIcons,HelpLink, + Box_NOT_CLOSABLE); if (TypeViewExamAnnouncement == Exa_FORM_VIEW) { /***** Start form *****/ - Frm_StartForm (ActRcvExaAnn); - if (Gbl.ExamAnns.ExaDat.ExaCod > 0) // Existing announcement of exam - Exa_PutParamExaCodToEdit (); + Frm_StartFormAnchor (ActRcvExaAnn,Anchor); + if (ExaCod > 0) // Existing announcement of exam + Exa_PutHiddenParamExaCod (ExaCod); } /***** Start table *****/ @@ -1500,14 +1491,22 @@ static void Exa_ShowExamAnnouncement (Exa_TypeViewExamAnnouncement_t TypeViewExa /***** End table, send button and end box *****/ if (TypeViewExamAnnouncement == Exa_FORM_VIEW) - Box_EndBoxTableWithButton ((Gbl.ExamAnns.ExaDat.ExaCod > 0) ? Btn_CONFIRM_BUTTON : - Btn_CREATE_BUTTON, + Box_EndBoxTableWithButton ((ExaCod > 0) ? Btn_CONFIRM_BUTTON : + Btn_CREATE_BUTTON, Txt_Publish_announcement_OF_EXAM); else Box_EndBoxTable (); + /***** Show QR code *****/ if (TypeViewExamAnnouncement == Exa_PRINT_VIEW) QR_ExamAnnnouncement (); + + /***** End article *****/ + if (TypeViewExamAnnouncement == Exa_NORMAL_VIEW) + Lay_EndArticle (); + + /***** Free anchor string *****/ + Exa_FreeAnchorStr (Anchor); } /*****************************************************************************/ @@ -1526,10 +1525,10 @@ static void Exa_PutIconsExamAnnouncement (void) switch (Gbl.ExamAnns.ExaDat.Status) { case Exa_VISIBLE_EXAM_ANNOUNCEMENT: - Ico_PutContextualIconToHide (ActHidExaAnn,Exa_PutParamExaCodToEdit); + Ico_PutContextualIconToHide (ActHidExaAnn,Gbl.ExamAnns.Anchor,Exa_PutParamExaCodToEdit); break; case Exa_HIDDEN_EXAM_ANNOUNCEMENT: - Ico_PutContextualIconToUnhide (ActShoExaAnn,Exa_PutParamExaCodToEdit); + Ico_PutContextualIconToUnhide (ActShoExaAnn,Gbl.ExamAnns.Anchor,Exa_PutParamExaCodToEdit); break; case Exa_DELETED_EXAM_ANNOUNCEMENT: // Not applicable here break; @@ -1549,7 +1548,7 @@ static void Exa_PutIconsExamAnnouncement (void) static void Exa_PutParamExaCodToEdit (void) { - Exa_PutHiddenParamExaCod (Gbl.ExamAnns.ExaDat.ExaCod); + Exa_PutHiddenParamExaCod (Gbl.ExamAnns.ExaCod); } void Exa_PutHiddenParamExaCod (long ExaCod) @@ -1567,6 +1566,40 @@ static long Exa_GetParamExaCod (void) return Par_GetParToLong ("ExaCod"); } +/*****************************************************************************/ +/*********** Build/free anchor string for an announcement of exam ************/ +/*****************************************************************************/ + +void Exa_SetAnchorStr (long ExaCod,char **Anchor) + { + if (ExaCod > 0) + { + if (ExaCod == Gbl.ExamAnns.NewExaCod) // New announcement of exam + { + if (asprintf (Anchor,"exam_new") < 0) + Lay_NotEnoughMemoryExit (); + } + else // Existing announcement of exam, not a new one + { + // Existing announcement of exam, not new + if (asprintf (Anchor,"exam_%ld", + ExaCod) < 0) + Lay_NotEnoughMemoryExit (); + } + } + else // ? + *Anchor = NULL; + } + +void Exa_FreeAnchorStr (char *Anchor) + { + if (Anchor) + { + free ((void *) Anchor); + Anchor = NULL; + } + } + /*****************************************************************************/ /************ Get summary and content about an exam announcement *************/ /*****************************************************************************/ @@ -1580,14 +1613,13 @@ void Exa_GetSummaryAndContentExamAnnouncement (char SummaryStr[Ntf_MAX_BYTES_SUM char StrExamDate[Cns_MAX_BYTES_DATE + 1]; /***** Initializations *****/ - Gbl.ExamAnns.ExaDat.ExaCod = ExaCod; SummaryStr[0] = '\0'; // Return nothing on error /***** Allocate memory for the exam announcement *****/ Exa_AllocMemExamAnnouncement (); /***** Get data of an exam announcement from database *****/ - Exa_GetDataExamAnnouncementFromDB (); + Exa_GetDataExamAnnouncementFromDB (ExaCod); /***** Content *****/ if (GetContent) diff --git a/swad_exam.h b/swad_exam.h index 94c2db28..779bc0f8 100644 --- a/swad_exam.h +++ b/swad_exam.h @@ -59,7 +59,6 @@ typedef enum struct ExamData { - long ExaCod; long CrsCod; Exa_ExamAnnouncementStatus_t Status; char CrsFullName[Hie_MAX_BYTES_FULL_NAME + 1]; @@ -78,6 +77,12 @@ struct ExamData char *OtherInfo; }; +struct Exa_ExamCodeAndDate + { + long ExaCod; + struct Date ExamDate; + }; + /*****************************************************************************/ /***************************** Public prototypes *****************************/ /*****************************************************************************/ @@ -89,20 +94,23 @@ void Exa_PrintExamAnnouncement (void); void Exa_ReqRemoveExamAnnouncement (void); void Exa_RemoveExamAnnouncement1 (void); void Exa_RemoveExamAnnouncement2 (void); -void Exa_HideExamAnnouncement1 (void); -void Exa_HideExamAnnouncement2 (void); -void Exa_UnhideExamAnnouncement1 (void); -void Exa_UnhideExamAnnouncement2 (void); +void Exa_HideExamAnnouncement (void); +void Exa_UnhideExamAnnouncement (void); void Exa_FreeMemExamAnnouncement (void); void Exa_FreeListExamAnnouncements (void); void Exa_ListExamAnnouncementsSee (void); +void Exa_ListExamAnnouncementsEdit (void); void Exa_GetExaCodToHighlight (void); void Exa_GetDateToHighlight (void); void Exa_CreateListDatesOfExamAnnouncements (void); void Exa_PutHiddenParamExaCod (long ExaCod); + +void Exa_SetAnchorStr (long ExaCod,char **Anchor); +void Exa_FreeAnchorStr (char *Anchor); + void Exa_GetSummaryAndContentExamAnnouncement (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1], char **ContentStr, long ExaCod,bool GetContent); diff --git a/swad_game.c b/swad_game.c index 9a272f07..a9beb9c5 100644 --- a/swad_game.c +++ b/swad_game.c @@ -827,9 +827,9 @@ static void Gam_PutFormsToRemEditOneGame (long GamCod,bool Visible, /***** Put icon to hide/show game *****/ if (Visible) - Ico_PutContextualIconToHide (ActHidGam,Gam_PutParams); + Ico_PutContextualIconToHide (ActHidGam,NULL,Gam_PutParams); else - Ico_PutContextualIconToUnhide (ActShoGam,Gam_PutParams); + Ico_PutContextualIconToUnhide (ActShoGam,NULL,Gam_PutParams); /***** Put icon to edit game *****/ Ico_PutContextualIconToEdit (ActEdiOneGam,Gam_PutParams); diff --git a/swad_global.c b/swad_global.c index ac11eccd..5a0cb16f 100644 --- a/swad_global.c +++ b/swad_global.c @@ -204,6 +204,7 @@ void Gbl_InitializeGlobals (void) Gbl.ExamAnns.NumExaAnns = 0; Gbl.ExamAnns.Lst = NULL; + Gbl.ExamAnns.NewExaCod = -1L; Gbl.ExamAnns.HighlightExaCod = -1L; Gbl.ExamAnns.HighlightDate[0] = '\0'; // No exam announcements highlighted diff --git a/swad_global.h b/swad_global.h index 0b093f69..2deea347 100644 --- a/swad_global.h +++ b/swad_global.h @@ -107,12 +107,12 @@ struct Globals } Form; struct { - unsigned Num; // Number of alert + size_t Num; // Number of alert struct { Ale_AlertType_t Type; - char *Text; - const char *Section; // Where to display the alert + char *Text; // Message to be displayed + char *Section; // Where to display the alert } List[Ale_MAX_ALERTS]; } Alerts; // Alert message created in a function and printed in a subsequent function. struct @@ -519,12 +519,14 @@ struct Globals } Syllabus; struct { - struct Date *Lst; // List of dates of exam announcements + struct Exa_ExamCodeAndDate *Lst; // List of exam announcements unsigned NumExaAnns; // Number of announcements of exam in the list + long NewExaCod; // New exam announcement just created long HighlightExaCod; // Exam announcement to be highlighted - char HighlightDate[4 + 1 + 2 + 1 + 2 + 1]; // Date with exam announcements to be highlighted (in YYYY-MM-DD format) + char HighlightDate[4 + 2 + 2 + 1]; // Date with exam announcements to be highlighted (in YYYYMMDD format) + long ExaCod; // Used to put contextual icons + const char *Anchor; // Used to put contextual icons struct ExamData ExaDat; - bool NewExamAnnouncement; } ExamAnns; struct { diff --git a/swad_icon.c b/swad_icon.c index 39173ffc..a9d2172c 100644 --- a/swad_icon.c +++ b/swad_icon.c @@ -261,20 +261,20 @@ void Ico_PutContextualIconToView (Act_Action_t NextAction,void (*FuncParams) ()) Txt_View); } -void Ico_PutContextualIconToHide (Act_Action_t NextAction,void (*FuncParams) ()) +void Ico_PutContextualIconToHide (Act_Action_t NextAction,const char *Anchor,void (*FuncParams) ()) { extern const char *Txt_Hide; - Lay_PutContextualLinkOnlyIcon (NextAction,NULL,FuncParams, + Lay_PutContextualLinkOnlyIcon (NextAction,Anchor,FuncParams, "eye.svg", Txt_Hide); } -void Ico_PutContextualIconToUnhide (Act_Action_t NextAction,void (*FuncParams) ()) +void Ico_PutContextualIconToUnhide (Act_Action_t NextAction,const char *Anchor,void (*FuncParams) ()) { extern const char *Txt_Show; - Lay_PutContextualLinkOnlyIcon (NextAction,NULL,FuncParams, + Lay_PutContextualLinkOnlyIcon (NextAction,Anchor,FuncParams, "eye-slash.svg", Txt_Show); } diff --git a/swad_icon.h b/swad_icon.h index c6022c62..a8ca6dc7 100644 --- a/swad_icon.h +++ b/swad_icon.h @@ -62,8 +62,8 @@ void Ico_PutContextualIconToRemove (Act_Action_t NextAction,void (*FuncParams) ( void Ico_PutContextualIconToEdit (Act_Action_t NextAction,void (*FuncParams) ()); void Ico_PutContextualIconToViewFiles (Act_Action_t NextAction,void (*FuncParams) ()); void Ico_PutContextualIconToView (Act_Action_t NextAction,void (*FuncParams) ()); -void Ico_PutContextualIconToUnhide (Act_Action_t NextAction,void (*FuncParams) ()); -void Ico_PutContextualIconToHide (Act_Action_t NextAction,void (*FuncParams) ()); +void Ico_PutContextualIconToUnhide (Act_Action_t NextAction,const char *Anchor,void (*FuncParams) ()); +void Ico_PutContextualIconToHide (Act_Action_t NextAction,const char *Anchor,void (*FuncParams) ()); void Ico_PutContextualIconToPrint (Act_Action_t NextAction,void (*FuncParams) ()); void Ico_PutDivIcon (const char *DivClass,const char *Icon,const char *Title); diff --git a/swad_layout.c b/swad_layout.c index 9182e52d..2aac2d4c 100644 --- a/swad_layout.c +++ b/swad_layout.c @@ -537,10 +537,11 @@ static void Lay_WriteScripts (void) for (NumExamAnnouncement = 0; NumExamAnnouncement < Gbl.ExamAnns.NumExaAnns; NumExamAnnouncement++) - fprintf (Gbl.F.Out," LstExamAnnouncements.push({ Year: %u, Month: %u, Day: %u });\n", - Gbl.ExamAnns.Lst[NumExamAnnouncement].Year, - Gbl.ExamAnns.Lst[NumExamAnnouncement].Month, - Gbl.ExamAnns.Lst[NumExamAnnouncement].Day); + fprintf (Gbl.F.Out," LstExamAnnouncements.push({ ExaCod: %ld, Year: %u, Month: %u, Day: %u });\n", + Gbl.ExamAnns.Lst[NumExamAnnouncement].ExaCod, + Gbl.ExamAnns.Lst[NumExamAnnouncement].ExamDate.Year, + Gbl.ExamAnns.Lst[NumExamAnnouncement].ExamDate.Month, + Gbl.ExamAnns.Lst[NumExamAnnouncement].ExamDate.Day); fprintf (Gbl.F.Out,"\n"); diff --git a/swad_notice.c b/swad_notice.c index f0705074..9169debd 100644 --- a/swad_notice.c +++ b/swad_notice.c @@ -25,8 +25,10 @@ /********************************* Headers ***********************************/ /*****************************************************************************/ +#define _GNU_SOURCE // For asprintf #include // For PATH_MAX #include // For NULL +#include // For sscanf, asprintf, etc. #include // For exit, system, malloc, calloc, free, etc. #include @@ -640,11 +642,10 @@ static void Not_DrawANotice (Not_Listing_t TypeNoticesListing, }; static unsigned UniqueId = 0; struct UsrData UsrDat; - char Anchor[16 + 10 + 1]; + char *Anchor = NULL; /***** Build anchor string *****/ - snprintf (Anchor,sizeof (Anchor), - "NOT_%ld",NotCod); + Not_SetAnchorStr (NotCod,&Anchor); /***** Start article for this notice *****/ if (TypeNoticesListing == Not_LIST_FULL_NOTICES) @@ -778,6 +779,34 @@ static void Not_DrawANotice (Not_Listing_t TypeNoticesListing, fprintf (Gbl.F.Out,""); Lay_EndArticle (); } + + /***** Free anchor string *****/ + Not_FreeAnchorStr (Anchor); + } + +/*****************************************************************************/ +/****************** Build/free anchor string for a notice ********************/ +/*****************************************************************************/ + +void Not_SetAnchorStr (long NotCod,char **Anchor) + { + if (NotCod > 0) // Existing announcement of exam, not a new one + { + if (asprintf (Anchor,"not_%ld", + NotCod) < 0) + Lay_NotEnoughMemoryExit (); + } + else // ? + *Anchor = NULL; + } + +void Not_FreeAnchorStr (char *Anchor) + { + if (Anchor) + { + free ((void *) Anchor); + Anchor = NULL; + } } /*****************************************************************************/ diff --git a/swad_notice.h b/swad_notice.h index 398170fc..83d30059 100644 --- a/swad_notice.h +++ b/swad_notice.h @@ -68,6 +68,10 @@ void Not_RequestRemNotice (void); void Not_RemoveNotice (void); void Not_ShowNotices (Not_Listing_t TypeNoticesListing,long HighlightNotCod); + +void Not_SetAnchorStr (long NotCod,char **Anchor); +void Not_FreeAnchorStr (char *Anchor); + void Not_GetSummaryAndContentNotice (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1], char **ContentStr, long NotCod,bool GetContent); diff --git a/swad_project.c b/swad_project.c index 967840a9..f1e37156 100644 --- a/swad_project.c +++ b/swad_project.c @@ -2185,10 +2185,10 @@ static void Prj_PutFormsToRemEditOnePrj (long PrjCod,Prj_HiddenVisibl_t Hidden, switch (Hidden) { case Prj_HIDDEN: - Ico_PutContextualIconToUnhide (ActShoPrj,Prj_PutCurrentParams); + Ico_PutContextualIconToUnhide (ActShoPrj,NULL,Prj_PutCurrentParams); break; case Prj_VISIBL: - Ico_PutContextualIconToHide (ActHidPrj,Prj_PutCurrentParams); + Ico_PutContextualIconToHide (ActHidPrj,NULL,Prj_PutCurrentParams); break; } diff --git a/swad_survey.c b/swad_survey.c index acc28273..80bf5f93 100644 --- a/swad_survey.c +++ b/swad_survey.c @@ -814,9 +814,9 @@ static void Svy_PutFormsToRemEditOneSvy (long SvyCod,bool Visible) /***** Put form to hide/show survey *****/ if (Visible) - Ico_PutContextualIconToHide (ActHidSvy,Svy_PutParams); + Ico_PutContextualIconToHide (ActHidSvy,NULL,Svy_PutParams); else - Ico_PutContextualIconToUnhide (ActShoSvy,Svy_PutParams); + Ico_PutContextualIconToUnhide (ActShoSvy,NULL,Svy_PutParams); /***** Put form to edit survey *****/ Ico_PutContextualIconToEdit (ActEdiOneSvy,Svy_PutParams); diff --git a/swad_text.c b/swad_text.c index 03e0cc3c..1ec7b069 100644 --- a/swad_text.c +++ b/swad_text.c @@ -1211,27 +1211,6 @@ const char *Txt_all = "tudo"; #endif -const char *Txt_All_announcements_of_exams = -#if L==1 // ca - "Totes les convocatòries d'exàmens"; -#elif L==2 // de - "Alle Aufrufe für Prüfung"; -#elif L==3 // en - "All announcements of exams"; -#elif L==4 // es - "Todas las convocatorias de exámenes"; -#elif L==5 // fr - "Tous les convocations à examens"; -#elif L==6 // gn - "Todas las convocatorias de exámenes"; // Okoteve traducción -#elif L==7 // it - "Tutti i appelli d'esame"; -#elif L==8 // pl - "Wszystkie ogloszenia egzaminów"; -#elif L==9 // pt - "Todas as chamadas para exames"; -#endif - const char *Txt_all_degrees = #if L==1 // ca "Totes les titulacions"; diff --git a/swad_timeline.c b/swad_timeline.c index 60675927..d4f3ecd9 100644 --- a/swad_timeline.c +++ b/swad_timeline.c @@ -1879,6 +1879,7 @@ static void TL_PutFormGoToAction (const struct TL_Note *SocNot) extern const char *Txt_TIMELINE_NOTE[TL_NUM_NOTE_TYPES]; extern const char *Txt_not_available; char Class[64]; + char *Anchor = NULL; const Act_Action_t TL_DefaultActions[TL_NUM_NOTE_TYPES] = { ActUnk, // TL_NOTE_UNKNOWN @@ -2001,7 +2002,10 @@ static void TL_PutFormGoToAction (const struct TL_Note *SocNot) Crs_PutParamCrsCod (SocNot->HieCod); // Go to another course break; case TL_NOTE_EXAM_ANNOUNCEMENT: - Frm_StartFormUnique (TL_DefaultActions[SocNot->NoteType]); + Exa_SetAnchorStr (SocNot->Cod,&Anchor); + Frm_StartFormUniqueAnchor (TL_DefaultActions[SocNot->NoteType], + Anchor); // Locate on this specific exam + Exa_FreeAnchorStr (Anchor); Exa_PutHiddenParamExaCod (SocNot->Cod); if (SocNot->HieCod != Gbl.CurrentCrs.Crs.CrsCod) // Not the current course Crs_PutParamCrsCod (SocNot->HieCod); // Go to another course @@ -2021,7 +2025,10 @@ static void TL_PutFormGoToAction (const struct TL_Note *SocNot) Crs_PutParamCrsCod (SocNot->HieCod); // Go to another course break; case TL_NOTE_NOTICE: - Frm_StartFormUnique (TL_DefaultActions[SocNot->NoteType]); + Not_SetAnchorStr (SocNot->Cod,&Anchor); + Frm_StartFormUniqueAnchor (TL_DefaultActions[SocNot->NoteType], + Anchor); + Not_FreeAnchorStr (Anchor); Not_PutHiddenParamNotCod (SocNot->Cod); if (SocNot->HieCod != Gbl.CurrentCrs.Crs.CrsCod) // Not the current course Crs_PutParamCrsCod (SocNot->HieCod); // Go to another course