From af2eaccf3cf3f5cac060306cb841dedad2b311ee Mon Sep 17 00:00:00 2001 From: Huong Nguyen Date: Fri, 15 Oct 2021 16:42:06 +0700 Subject: [PATCH] MDL-72825 calendar: Course name still exists in the course view --- blocks/timeline/amd/build/view_courses.min.js | 2 +- blocks/timeline/amd/build/view_courses.min.js.map | 2 +- blocks/timeline/amd/src/view_courses.js | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/blocks/timeline/amd/build/view_courses.min.js b/blocks/timeline/amd/build/view_courses.min.js index 0b50026ad14..65fccfc74b3 100644 --- a/blocks/timeline/amd/build/view_courses.min.js +++ b/blocks/timeline/amd/build/view_courses.min.js @@ -1,2 +1,2 @@ -define ("block_timeline/view_courses",["jquery","core/notification","core/custom_interaction_events","core/str","core/templates","block_timeline/event_list","core_course/repository","block_timeline/calendar_events_repository"],function(a,b,c,d,e,f,g,h){var i={MORE_COURSES_BUTTON:"[data-action=\"more-courses\"]",MORE_COURSES_BUTTON_CONTAINER:"[data-region=\"more-courses-button-container\"]",NO_COURSES_EMPTY_MESSAGE:"[data-region=\"no-courses-empty-message\"]",COURSES_LIST:"[data-region=\"courses-list\"]",COURSE_ITEMS_LOADING_PLACEHOLDER:"[data-region=\"course-items-loading-placeholder\"]",COURSE_EVENTS_CONTAINER:"[data-region=\"course-events-container\"]",COURSE_NAME:"[data-region=\"course-name\"]",LOADING_ICON:".loading-icon",TIMELINE_BLOCK:"[data-region=\"timeline\"]",TIMELINE_SEARCH:"[data-region=\"search-input\"]"},j={COURSE_ITEMS:"block_timeline/course-items",LOADING_ICON:"core/loading"},k=5,l=86400,m=function(a){a.find(i.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass("hidden")},n=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).addClass("hidden")},o=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).removeClass("hidden")},p=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!0);e.render(j.LOADING_ICON,{}).then(function(a){b.append(a);return a}).catch(function(){return!1})},q=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!1);b.find(i.LOADING_ICON).remove()},r=function(a){a.find(i.NO_COURSES_EMPTY_MESSAGE).removeClass("hidden")},s=function(a,b){var c=a.find(i.COURSES_LIST);e.appendNodeContents(c,b,"")},t=function(a){return 0b},G=function(a,b,c,d){var e=a.map(function(a){return a.id});return C(e,b,k+1,c,d)},H=function(a,b,c,d,f){return e.render(j.COURSE_ITEMS,{courses:a,midnight:c,hasdaysoffset:!0,hasdayslimit:f!=void 0,daysoffset:d,dayslimit:f,nodayslimit:f==void 0}).then(function(a){m(b);if(a){s(b,a)}else{if(!t(b)){r(b)}}return a}).then(function(c){if(a.length<2){n(b)}else{o(b)}return c}).catch(function(){m(b)})},I=function(c){var e=u(c),h=w(c);return g.getEnrolledCoursesByTimelineClassification("inprogress",h,e,"fullname asc").then(function(b){var e=Date.now(),g=b.courses,h=b.nextoffset,j=x(c),l=y(c),m=z(c),n=A(c),o=B(c),p=c.closest(i.TIMELINE_BLOCK).find(i.TIMELINE_SEARCH).val();v(c,h);var q=G(g,n,o,p),r=H(g,c,m,j,l);return a.when(q,r).then(function(b){if(F(c,e)){return b}g.forEach(function(e){var g=e.id,h=[],i=c.find("[data-region=\"course-events-container\"][data-course-id=\""+g+"\"]"),j=i.find(f.rootSelector),l=b.groupedbycourse.filter(function(a){return a.courseid==g});if(l.length){h=l[0].events}var m=a.Deferred().resolve({events:h}).promise();d.get_string("ariaeventlistpaginationnavcourses","block_timeline",e.fullnamedisplay).then(function(a){f.init(j,k,{1:m},a);return a}).catch(function(){f.init(j,k,{1:m})})});return b})}).catch(b.exception)},J=function(c){var e=Date.now(),g=A(c),h=B(c),j=c.find(i.COURSE_EVENTS_CONTAINER),l=j.map(function(){return a(this).attr("data-course-id")}).get(),m=c.closest(i.TIMELINE_BLOCK).find(i.TIMELINE_SEARCH).val();E(c,e);return C(l,g,k+1,h,m).then(function(b){if(F(c,e)){return b}j.each(function(c,e){e=a(e);var g=e.attr("data-course-id"),h=e.find(i.COURSE_NAME).text(),j=e.find(f.rootSelector),l=a.Deferred(),m=[],n=b.groupedbycourse.filter(function(a){return a.courseid==g});if(n.length){m=n[0].events}l.resolve({events:m});var o={courseview:!0};d.get_string("ariaeventlistpaginationnavcourses","block_timeline",h).then(function(a){f.init(j,k,{1:l.promise()},a,o);return a}).catch(function(){f.init(j,k,{1:l.promise()},void 0,o)})});return b}).catch(b.exception)},K=function(a){c.define(a,[c.events.activate]);a.on(c.events.activate,i.MORE_COURSES_BUTTON,function(b,c){p(a);I(a).then(function(){q(a)}).catch(function(){q(a)});if(c){c.originalEvent.preventDefault();c.originalEvent.stopPropagation()}b.stopPropagation()})},L=function(a){if(!a.attr("data-seen")){if(t(a)){J(a)}else{I(a)}a.attr("data-seen",!0)}};return{init:function init(b){b=a(b);E(b,Date.now());if(b.hasClass("active")){I(b);b.attr("data-seen",!0)}K(b)},reset:function reset(a){a.removeAttr("data-seen");if(a.hasClass("active")){L(a)}},shown:L}}); +define ("block_timeline/view_courses",["jquery","core/notification","core/custom_interaction_events","core/str","core/templates","block_timeline/event_list","core_course/repository","block_timeline/calendar_events_repository"],function(a,b,c,d,e,f,g,h){var i={MORE_COURSES_BUTTON:"[data-action=\"more-courses\"]",MORE_COURSES_BUTTON_CONTAINER:"[data-region=\"more-courses-button-container\"]",NO_COURSES_EMPTY_MESSAGE:"[data-region=\"no-courses-empty-message\"]",COURSES_LIST:"[data-region=\"courses-list\"]",COURSE_ITEMS_LOADING_PLACEHOLDER:"[data-region=\"course-items-loading-placeholder\"]",COURSE_EVENTS_CONTAINER:"[data-region=\"course-events-container\"]",COURSE_NAME:"[data-region=\"course-name\"]",LOADING_ICON:".loading-icon",TIMELINE_BLOCK:"[data-region=\"timeline\"]",TIMELINE_SEARCH:"[data-region=\"search-input\"]"},j={COURSE_ITEMS:"block_timeline/course-items",LOADING_ICON:"core/loading"},k=5,l=86400,m={courseview:!0},n=function(a){a.find(i.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass("hidden")},o=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).addClass("hidden")},p=function(a){a.find(i.MORE_COURSES_BUTTON_CONTAINER).removeClass("hidden")},q=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!0);e.render(j.LOADING_ICON,{}).then(function(a){b.append(a);return a}).catch(function(){return!1})},r=function(a){var b=a.find(i.MORE_COURSES_BUTTON);b.prop("disabled",!1);b.find(i.LOADING_ICON).remove()},s=function(a){a.find(i.NO_COURSES_EMPTY_MESSAGE).removeClass("hidden")},t=function(a,b){var c=a.find(i.COURSES_LIST);e.appendNodeContents(c,b,"")},u=function(a){return 0b},H=function(a,b,c,d){var e=a.map(function(a){return a.id});return D(e,b,k+1,c,d)},I=function(a,b,c,d,f){return e.render(j.COURSE_ITEMS,{courses:a,midnight:c,hasdaysoffset:!0,hasdayslimit:f!=void 0,daysoffset:d,dayslimit:f,nodayslimit:f==void 0}).then(function(a){n(b);if(a){t(b,a)}else{if(!u(b)){s(b)}}return a}).then(function(c){if(a.length<2){o(b)}else{p(b)}return c}).catch(function(){n(b)})},J=function(c){var e=v(c),h=x(c);return g.getEnrolledCoursesByTimelineClassification("inprogress",h,e,"fullname asc").then(function(b){var e=Date.now(),g=b.courses,h=b.nextoffset,j=y(c),l=z(c),n=A(c),o=B(c),p=C(c),q=c.closest(i.TIMELINE_BLOCK).find(i.TIMELINE_SEARCH).val();w(c,h);var r=H(g,o,p,q),s=I(g,c,n,j,l);return a.when(r,s).then(function(b){if(G(c,e)){return b}g.forEach(function(e){var g=e.id,h=[],i=c.find("[data-region=\"course-events-container\"][data-course-id=\""+g+"\"]"),j=i.find(f.rootSelector),l=b.groupedbycourse.filter(function(a){return a.courseid==g});if(l.length){h=l[0].events}var n=a.Deferred().resolve({events:h}).promise();d.get_string("ariaeventlistpaginationnavcourses","block_timeline",e.fullnamedisplay).then(function(a){f.init(j,k,{1:n},a,m);return a}).catch(function(){f.init(j,k,{1:n},void 0,m)})});return b})}).catch(b.exception)},K=function(c){var e=Date.now(),g=B(c),h=C(c),j=c.find(i.COURSE_EVENTS_CONTAINER),l=j.map(function(){return a(this).attr("data-course-id")}).get(),n=c.closest(i.TIMELINE_BLOCK).find(i.TIMELINE_SEARCH).val();F(c,e);return D(l,g,k+1,h,n).then(function(b){if(G(c,e)){return b}j.each(function(c,e){e=a(e);var g=e.attr("data-course-id"),h=e.find(i.COURSE_NAME).text(),j=e.find(f.rootSelector),l=a.Deferred(),n=[],o=b.groupedbycourse.filter(function(a){return a.courseid==g});if(o.length){n=o[0].events}l.resolve({events:n});d.get_string("ariaeventlistpaginationnavcourses","block_timeline",h).then(function(a){f.init(j,k,{1:l.promise()},a,m);return a}).catch(function(){f.init(j,k,{1:l.promise()},void 0,m)})});return b}).catch(b.exception)},L=function(a){c.define(a,[c.events.activate]);a.on(c.events.activate,i.MORE_COURSES_BUTTON,function(b,c){q(a);J(a).then(function(){r(a)}).catch(function(){r(a)});if(c){c.originalEvent.preventDefault();c.originalEvent.stopPropagation()}b.stopPropagation()})},M=function(a){if(!a.attr("data-seen")){if(u(a)){K(a)}else{J(a)}a.attr("data-seen",!0)}};return{init:function init(b){b=a(b);F(b,Date.now());if(b.hasClass("active")){J(b);b.attr("data-seen",!0)}L(b)},reset:function reset(a){a.removeAttr("data-seen");if(a.hasClass("active")){M(a)}},shown:M}}); //# sourceMappingURL=view_courses.min.js.map diff --git a/blocks/timeline/amd/build/view_courses.min.js.map b/blocks/timeline/amd/build/view_courses.min.js.map index 7f6dc904c6c..265f4df7006 100644 --- a/blocks/timeline/amd/build/view_courses.min.js.map +++ b/blocks/timeline/amd/build/view_courses.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/view_courses.js"],"names":["define","$","Notification","CustomEvents","Str","Templates","EventList","CourseRepository","EventsRepository","SELECTORS","MORE_COURSES_BUTTON","MORE_COURSES_BUTTON_CONTAINER","NO_COURSES_EMPTY_MESSAGE","COURSES_LIST","COURSE_ITEMS_LOADING_PLACEHOLDER","COURSE_EVENTS_CONTAINER","COURSE_NAME","LOADING_ICON","TIMELINE_BLOCK","TIMELINE_SEARCH","TEMPLATES","COURSE_ITEMS","COURSE_EVENT_LIMIT","SECONDS_IN_DAY","hideLoadingPlaceholder","root","find","addClass","hideMoreCoursesButton","showMoreCoursesButton","removeClass","enableMoreCoursesButtonLoading","button","prop","render","then","html","append","catch","disableMoreCoursesButtonLoading","remove","showNoCoursesEmptyMessage","renderCourseItemsHTML","container","appendNodeContents","hasLoadedCourses","length","getOffset","parseInt","attr","setOffset","offset","getLimit","getDaysOffset","getDaysLimit","daysLimit","getMidnight","getStartTime","midnight","daysOffset","getEndTime","getEventsForCourseIds","courseIds","startTime","limit","endTime","searchValue","args","courseids","starttime","endtime","searchvalue","queryByCourses","getEventReloadTime","data","setEventReloadTime","time","hasReloadedEventsSince","loadEventsForCourses","courses","map","course","id","updateDisplayFromCourses","hasdaysoffset","hasdayslimit","daysoffset","dayslimit","nodayslimit","loadMoreCourses","getEnrolledCoursesByTimelineClassification","result","startEventLoadingTime","Date","now","nextOffset","nextoffset","closest","val","eventsPromise","renderPromise","when","eventsByCourse","forEach","courseId","events","courseEventsContainer","eventListRoot","rootSelector","courseGroups","groupedbycourse","filter","group","courseid","pageOnePreload","Deferred","resolve","promise","get_string","fullnamedisplay","string","init","exception","reloadCourseEvents","startReloadTime","courseEventsContainers","get","each","index","courseName","text","eventListContainer","pageDeferred","additionalConfig","courseview","registerEventListeners","activate","on","e","originalEvent","preventDefault","stopPropagation","shown","hasClass","reset","removeAttr"],"mappings":"AAsBAA,OAAM,+BACN,CACI,QADJ,CAEI,mBAFJ,CAGI,gCAHJ,CAII,UAJJ,CAKI,gBALJ,CAMI,2BANJ,CAOI,wBAPJ,CAQI,2CARJ,CADM,CAWN,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIIC,CAJJ,CAKIC,CALJ,CAMIC,CANJ,CAOIC,CAPJ,CAQIC,CARJ,CASE,IAEMC,CAAAA,CAAS,CAAG,CACZC,mBAAmB,CAAE,gCADT,CAEZC,6BAA6B,CAAE,iDAFnB,CAGZC,wBAAwB,CAAE,4CAHd,CAIZC,YAAY,CAAE,gCAJF,CAKZC,gCAAgC,CAAE,oDALtB,CAMZC,uBAAuB,CAAE,2CANb,CAOZC,WAAW,CAAE,+BAPD,CAQZC,YAAY,CAAE,eARF,CASZC,cAAc,CAAE,4BATJ,CAUZC,eAAe,CAAE,gCAVL,CAFlB,CAeMC,CAAS,CAAG,CACZC,YAAY,CAAE,6BADF,CAEZJ,YAAY,CAAE,cAFF,CAflB,CAsBMK,CAAkB,CAAG,CAtB3B,CAwBMC,CAAc,MAxBpB,CA+BMC,CAAsB,CAAG,SAASC,CAAT,CAAe,CACxCA,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACK,gCAApB,EAAsDa,QAAtD,CAA+D,QAA/D,CACH,CAjCH,CAwCMC,CAAqB,CAAG,SAASH,CAAT,CAAe,CACvCA,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACE,6BAApB,EAAmDgB,QAAnD,CAA4D,QAA5D,CACH,CA1CH,CAiDME,CAAqB,CAAG,SAASJ,CAAT,CAAe,CACvCA,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACE,6BAApB,EAAmDmB,WAAnD,CAA+D,QAA/D,CACH,CAnDH,CA0DMC,CAA8B,CAAG,SAASN,CAAT,CAAe,CAChD,GAAIO,CAAAA,CAAM,CAAGP,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACC,mBAApB,CAAb,CACAsB,CAAM,CAACC,IAAP,CAAY,UAAZ,KACA5B,CAAS,CAAC6B,MAAV,CAAiBd,CAAS,CAACH,YAA3B,CAAyC,EAAzC,EACKkB,IADL,CACU,SAASC,CAAT,CAAe,CACjBJ,CAAM,CAACK,MAAP,CAAcD,CAAd,EACA,MAAOA,CAAAA,CACV,CAJL,EAKKE,KALL,CAKW,UAAW,CAEd,QACH,CARL,CASH,CAtEH,CA6EMC,CAA+B,CAAG,SAASd,CAAT,CAAe,CACjD,GAAIO,CAAAA,CAAM,CAAGP,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACC,mBAApB,CAAb,CACAsB,CAAM,CAACC,IAAP,CAAY,UAAZ,KACAD,CAAM,CAACN,IAAP,CAAYjB,CAAS,CAACQ,YAAtB,EAAoCuB,MAApC,EACH,CAjFH,CAwFMC,CAAyB,CAAG,SAAShB,CAAT,CAAe,CAC3CA,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACG,wBAApB,EAA8CkB,WAA9C,CAA0D,QAA1D,CACH,CA1FH,CAkGMY,CAAqB,CAAG,SAASjB,CAAT,CAAeW,CAAf,CAAqB,CAC7C,GAAIO,CAAAA,CAAS,CAAGlB,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACI,YAApB,CAAhB,CACAR,CAAS,CAACuC,kBAAV,CAA6BD,CAA7B,CAAwCP,CAAxC,CAA8C,EAA9C,CACH,CArGH,CA6GMS,CAAgB,CAAG,SAASpB,CAAT,CAAe,CAClC,MAA6D,EAAtD,CAAAA,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACM,uBAApB,EAA6C+B,MACvD,CA/GH,CAuHMC,CAAS,CAAG,SAAStB,CAAT,CAAe,CAC3B,MAAOuB,CAAAA,QAAQ,CAACvB,CAAI,CAACwB,IAAL,CAAU,aAAV,CAAD,CAA2B,EAA3B,CAClB,CAzHH,CAiIMC,CAAS,CAAG,SAASzB,CAAT,CAAe0B,CAAf,CAAuB,CACnC1B,CAAI,CAACwB,IAAL,CAAU,aAAV,CAAyBE,CAAzB,CACH,CAnIH,CA2IMC,CAAQ,CAAG,SAAS3B,CAAT,CAAe,CAC1B,MAAOuB,CAAAA,QAAQ,CAACvB,CAAI,CAACwB,IAAL,CAAU,YAAV,CAAD,CAA0B,EAA1B,CAClB,CA7IH,CAqJMI,CAAa,CAAG,SAAS5B,CAAT,CAAe,CAC/B,MAAOuB,CAAAA,QAAQ,CAACvB,CAAI,CAACwB,IAAL,CAAU,kBAAV,CAAD,CAAgC,EAAhC,CAClB,CAvJH,CAiKMK,CAAY,CAAG,SAAS7B,CAAT,CAAe,CAC9B,GAAI8B,CAAAA,CAAS,CAAG9B,CAAI,CAACwB,IAAL,CAAU,iBAAV,CAAhB,CACA,MAAOM,CAAAA,CAAS,QAAT,CAAyBP,QAAQ,CAACO,CAAD,CAAY,EAAZ,CAAjC,OACV,CApKH,CA4KMC,CAAW,CAAG,SAAS/B,CAAT,CAAe,CAC7B,MAAOuB,CAAAA,QAAQ,CAACvB,CAAI,CAACwB,IAAL,CAAU,eAAV,CAAD,CAA6B,EAA7B,CAClB,CA9KH,CAwLMQ,CAAY,CAAG,SAAShC,CAAT,CAAe,IAC1BiC,CAAAA,CAAQ,CAAGF,CAAW,CAAC/B,CAAD,CADI,CAE1BkC,CAAU,CAAGN,CAAa,CAAC5B,CAAD,CAFA,CAG9B,MAAOiC,CAAAA,CAAQ,CAAIC,CAAU,CAAGpC,CACnC,CA5LH,CAsMMqC,CAAU,CAAG,SAASnC,CAAT,CAAe,IACxBiC,CAAAA,CAAQ,CAAGF,CAAW,CAAC/B,CAAD,CADE,CAExB8B,CAAS,CAAGD,CAAY,CAAC7B,CAAD,CAFA,CAG5B,MAAO8B,CAAAA,CAAS,QAAT,CAAyBG,CAAQ,CAAIH,CAAS,CAAGhC,CAAjD,GACV,CA1MH,CAuNMsC,CAAqB,CAAG,SAASC,CAAT,CAAoBC,CAApB,CAA+BC,CAA/B,CAAsCC,CAAtC,CAA+CC,CAA/C,CAA4D,CACpF,GAAIC,CAAAA,CAAI,CAAG,CACPC,SAAS,CAAEN,CADJ,CAEPO,SAAS,CAAEN,CAFJ,CAGPC,KAAK,CAAEA,CAHA,CAAX,CAMA,GAAIC,CAAJ,CAAa,CACTE,CAAI,CAACG,OAAL,CAAeL,CAClB,CAED,GAAIC,CAAJ,CAAiB,CACbC,CAAI,CAACI,WAAL,CAAmBL,CACtB,CAED,MAAO1D,CAAAA,CAAgB,CAACgE,cAAjB,CAAgCL,CAAhC,CACV,CAvOH,CA+OMM,CAAkB,CAAG,SAAShD,CAAT,CAAe,CACpC,MAAOA,CAAAA,CAAI,CAACiD,IAAL,CAAU,sBAAV,CACV,CAjPH,CAyPMC,CAAkB,CAAG,SAASlD,CAAT,CAAemD,CAAf,CAAqB,CAC1CnD,CAAI,CAACiD,IAAL,CAAU,sBAAV,CAAkCE,CAAlC,CACH,CA3PH,CAqQMC,CAAsB,CAAG,SAASpD,CAAT,CAAemD,CAAf,CAAqB,CAC9C,MAAOH,CAAAA,CAAkB,CAAChD,CAAD,CAAlB,CAA2BmD,CACrC,CAvQH,CAkRME,CAAoB,CAAG,SAASC,CAAT,CAAkBhB,CAAlB,CAA6BE,CAA7B,CAAsCC,CAAtC,CAAmD,CAC1E,GAAIJ,CAAAA,CAAS,CAAGiB,CAAO,CAACC,GAAR,CAAY,SAASC,CAAT,CAAiB,CACzC,MAAOA,CAAAA,CAAM,CAACC,EACjB,CAFe,CAAhB,CAIA,MAAOrB,CAAAA,CAAqB,CAACC,CAAD,CAAYC,CAAZ,CAAuBzC,CAAkB,CAAG,CAA5C,CAA+C2C,CAA/C,CAAwDC,CAAxD,CAC/B,CAxRH,CAoSMiB,CAAwB,CAAG,SAASJ,CAAT,CAAkBtD,CAAlB,CAAwBiC,CAAxB,CAAkCC,CAAlC,CAA8CJ,CAA9C,CAAyD,CAEpF,MAAOlD,CAAAA,CAAS,CAAC6B,MAAV,CAAiBd,CAAS,CAACC,YAA3B,CAAyC,CAC5C0D,OAAO,CAAEA,CADmC,CAE5CrB,QAAQ,CAAEA,CAFkC,CAG5C0B,aAAa,GAH+B,CAI5CC,YAAY,CAAE9B,CAAS,QAJqB,CAK5C+B,UAAU,CAAE3B,CALgC,CAM5C4B,SAAS,CAAEhC,CANiC,CAO5CiC,WAAW,CAAEjC,CAAS,QAPsB,CAAzC,EAQJpB,IARI,CAQC,SAASC,CAAT,CAAe,CACnBZ,CAAsB,CAACC,CAAD,CAAtB,CAEA,GAAIW,CAAJ,CAAU,CAGNM,CAAqB,CAACjB,CAAD,CAAOW,CAAP,CACxB,CAJD,IAIO,CACH,GAAI,CAACS,CAAgB,CAACpB,CAAD,CAArB,CAA6B,CAGzBgB,CAAyB,CAAChB,CAAD,CAC5B,CACJ,CAED,MAAOW,CAAAA,CACV,CAxBM,EAyBND,IAzBM,CAyBD,SAASC,CAAT,CAAe,CACjB,GAAI2C,CAAO,CAACjC,MAAR,CAzSO,CAySX,CAAmC,CAG/BlB,CAAqB,CAACH,CAAD,CACxB,CAJD,IAIO,CAEHI,CAAqB,CAACJ,CAAD,CACxB,CAED,MAAOW,CAAAA,CACV,CApCM,EAqCNE,KArCM,CAqCA,UAAW,CACdd,CAAsB,CAACC,CAAD,CACzB,CAvCM,CAwCV,CA9UH,CAuVMgE,CAAe,CAAG,SAAShE,CAAT,CAAe,IAC7B0B,CAAAA,CAAM,CAAGJ,CAAS,CAACtB,CAAD,CADW,CAE7BuC,CAAK,CAAGZ,CAAQ,CAAC3B,CAAD,CAFa,CAKjC,MAAOlB,CAAAA,CAAgB,CAACmF,0CAAjB,CAxUiB,YAwUjB,CAEH1B,CAFG,CAGHb,CAHG,CAvUO,cAuUP,EAKLhB,IALK,CAKA,SAASwD,CAAT,CAAiB,IAChBC,CAAAA,CAAqB,CAAGC,IAAI,CAACC,GAAL,EADR,CAEhBf,CAAO,CAAGY,CAAM,CAACZ,OAFD,CAGhBgB,CAAU,CAAGJ,CAAM,CAACK,UAHJ,CAIhBrC,CAAU,CAAGN,CAAa,CAAC5B,CAAD,CAJV,CAKhB8B,CAAS,CAAGD,CAAY,CAAC7B,CAAD,CALR,CAMhBiC,CAAQ,CAAGF,CAAW,CAAC/B,CAAD,CANN,CAOhBsC,CAAS,CAAGN,CAAY,CAAChC,CAAD,CAPR,CAQhBwC,CAAO,CAAGL,CAAU,CAACnC,CAAD,CARJ,CASdyC,CAAW,CAAGzC,CAAI,CAACwE,OAAL,CAAaxF,CAAS,CAACS,cAAvB,EAAuCQ,IAAvC,CAA4CjB,CAAS,CAACU,eAAtD,EAAuE+E,GAAvE,EATA,CAYpBhD,CAAS,CAACzB,CAAD,CAAOsE,CAAP,CAAT,CAZoB,GAchBI,CAAAA,CAAa,CAAGrB,CAAoB,CAACC,CAAD,CAAUhB,CAAV,CAAqBE,CAArB,CAA8BC,CAA9B,CAdpB,CAgBhBkC,CAAa,CAAGjB,CAAwB,CAACJ,CAAD,CAAUtD,CAAV,CAAgBiC,CAAhB,CAA0BC,CAA1B,CAAsCJ,CAAtC,CAhBxB,CAkBpB,MAAOtD,CAAAA,CAAC,CAACoG,IAAF,CAAOF,CAAP,CAAsBC,CAAtB,EACFjE,IADE,CACG,SAASmE,CAAT,CAAyB,CAC3B,GAAIzB,CAAsB,CAACpD,CAAD,CAAOmE,CAAP,CAA1B,CAAyD,CAErD,MAAOU,CAAAA,CACV,CAIDvB,CAAO,CAACwB,OAAR,CAAgB,SAAStB,CAAT,CAAiB,IACzBuB,CAAAA,CAAQ,CAAGvB,CAAM,CAACC,EADO,CAEzBuB,CAAM,CAAG,EAFgB,CAIzBC,CAAqB,CAAGjF,CAAI,CAACC,IAAL,CADJ,8DAA6D8E,CAA7D,CAAwE,KACpE,CAJC,CAKzBG,CAAa,CAAGD,CAAqB,CAAChF,IAAtB,CAA2BpB,CAAS,CAACsG,YAArC,CALS,CAMzBC,CAAY,CAAGP,CAAc,CAACQ,eAAf,CAA+BC,MAA/B,CAAsC,SAASC,CAAT,CAAgB,CACrE,MAAOA,CAAAA,CAAK,CAACC,QAAN,EAAkBT,CAC5B,CAFkB,CANU,CAU7B,GAAIK,CAAY,CAAC/D,MAAjB,CAAyB,CAErB2D,CAAM,CAAGI,CAAY,CAAC,CAAD,CAAZ,CAAgBJ,MAC5B,CAID,GAAIS,CAAAA,CAAc,CAAGjH,CAAC,CAACkH,QAAF,GAAaC,OAAb,CAAqB,CAACX,MAAM,CAAEA,CAAT,CAArB,EAAuCY,OAAvC,EAArB,CAEAjH,CAAG,CAACkH,UAAJ,CAAe,mCAAf,CAAoD,gBAApD,CAAsErC,CAAM,CAACsC,eAA7E,EACKpF,IADL,CACU,SAASqF,CAAT,CAAiB,CACnBlH,CAAS,CAACmH,IAAV,CAAed,CAAf,CAA8BrF,CAA9B,CAAkD,CAAC,EAAK4F,CAAN,CAAlD,CAAyEM,CAAzE,EACA,MAAOA,CAAAA,CACV,CAJL,EAKKlF,KALL,CAKW,UAAW,CAEdhC,CAAS,CAACmH,IAAV,CAAed,CAAf,CAA8BrF,CAA9B,CAAkD,CAAC,EAAK4F,CAAN,CAAlD,CACH,CARL,CASH,CA5BD,EA8BA,MAAOZ,CAAAA,CACV,CAxCE,CAyCV,CAhEM,EAgEJhE,KAhEI,CAgEEpC,CAAY,CAACwH,SAhEf,CAiEV,CA7ZH,CAsaMC,CAAkB,CAAG,SAASlG,CAAT,CAAe,IAChCmG,CAAAA,CAAe,CAAG/B,IAAI,CAACC,GAAL,EADc,CAEhC/B,CAAS,CAAGN,CAAY,CAAChC,CAAD,CAFQ,CAGhCwC,CAAO,CAAGL,CAAU,CAACnC,CAAD,CAHY,CAIhCoG,CAAsB,CAAGpG,CAAI,CAACC,IAAL,CAAUjB,CAAS,CAACM,uBAApB,CAJO,CAKhC+C,CAAS,CAAG+D,CAAsB,CAAC7C,GAAvB,CAA2B,UAAW,CAClD,MAAO/E,CAAAA,CAAC,CAAC,IAAD,CAAD,CAAQgD,IAAR,CAAa,gBAAb,CACV,CAFe,EAEb6E,GAFa,EALoB,CAQ9B5D,CAAW,CAAGzC,CAAI,CAACwE,OAAL,CAAaxF,CAAS,CAACS,cAAvB,EAAuCQ,IAAvC,CAA4CjB,CAAS,CAACU,eAAtD,EAAuE+E,GAAvE,EARgB,CAWpCvB,CAAkB,CAAClD,CAAD,CAAOmG,CAAP,CAAlB,CAGA,MAAO/D,CAAAA,CAAqB,CAACC,CAAD,CAAYC,CAAZ,CAAuBzC,CAAkB,CAAG,CAA5C,CAA+C2C,CAA/C,CAAwDC,CAAxD,CAArB,CACF/B,IADE,CACG,SAASmE,CAAT,CAAyB,CAC3B,GAAIzB,CAAsB,CAACpD,CAAD,CAAOmG,CAAP,CAA1B,CAAmD,CAE/C,MAAOtB,CAAAA,CACV,CAEDuB,CAAsB,CAACE,IAAvB,CAA4B,SAASC,CAAT,CAAgBrF,CAAhB,CAA2B,CACnDA,CAAS,CAAG1C,CAAC,CAAC0C,CAAD,CAAb,CADmD,GAE/C6D,CAAAA,CAAQ,CAAG7D,CAAS,CAACM,IAAV,CAAe,gBAAf,CAFoC,CAG/CgF,CAAU,CAAGtF,CAAS,CAACjB,IAAV,CAAejB,CAAS,CAACO,WAAzB,EAAsCkH,IAAtC,EAHkC,CAI/CC,CAAkB,CAAGxF,CAAS,CAACjB,IAAV,CAAepB,CAAS,CAACsG,YAAzB,CAJ0B,CAK/CwB,CAAY,CAAGnI,CAAC,CAACkH,QAAF,EALgC,CAM/CV,CAAM,CAAG,EANsC,CAO/CI,CAAY,CAAGP,CAAc,CAACQ,eAAf,CAA+BC,MAA/B,CAAsC,SAASC,CAAT,CAAgB,CACrE,MAAOA,CAAAA,CAAK,CAACC,QAAN,EAAkBT,CAC5B,CAFkB,CAPgC,CAWnD,GAAIK,CAAY,CAAC/D,MAAjB,CAAyB,CAErB2D,CAAM,CAAGI,CAAY,CAAC,CAAD,CAAZ,CAAgBJ,MAC5B,CAED2B,CAAY,CAAChB,OAAb,CAAqB,CAACX,MAAM,CAAEA,CAAT,CAArB,EAEA,GAAI4B,CAAAA,CAAgB,CAAG,CAACC,UAAU,GAAX,CAAvB,CAGAlI,CAAG,CAACkH,UAAJ,CAAe,mCAAf,CAAoD,gBAApD,CAAsEW,CAAtE,EACK9F,IADL,CACU,SAASqF,CAAT,CAAiB,CACnBlH,CAAS,CAACmH,IAAV,CAAeU,CAAf,CAAmC7G,CAAnC,CAAuD,CAAC,EAAK8G,CAAY,CAACf,OAAb,EAAN,CAAvD,CACIG,CADJ,CACYa,CADZ,EAEA,MAAOb,CAAAA,CACV,CALL,EAMKlF,KANL,CAMW,UAAW,CAEdhC,CAAS,CAACmH,IAAV,CAAeU,CAAf,CAAmC7G,CAAnC,CAAuD,CAAC,EAAK8G,CAAY,CAACf,OAAb,EAAN,CAAvD,QACegB,CADf,CAEH,CAVL,CAWH,CAhCD,EAkCA,MAAO/B,CAAAA,CACV,CA1CE,EA0CAhE,KA1CA,CA0CMpC,CAAY,CAACwH,SA1CnB,CA2CV,CA/dH,CAseMa,CAAsB,CAAG,SAAS9G,CAAT,CAAe,CACxCtB,CAAY,CAACH,MAAb,CAAoByB,CAApB,CAA0B,CAACtB,CAAY,CAACsG,MAAb,CAAoB+B,QAArB,CAA1B,EAGA/G,CAAI,CAACgH,EAAL,CAAQtI,CAAY,CAACsG,MAAb,CAAoB+B,QAA5B,CAAsC/H,CAAS,CAACC,mBAAhD,CAAqE,SAASgI,CAAT,CAAYhE,CAAZ,CAAkB,CACnF3C,CAA8B,CAACN,CAAD,CAA9B,CACAgE,CAAe,CAAChE,CAAD,CAAf,CACKU,IADL,CACU,UAAW,CACbI,CAA+B,CAACd,CAAD,CAElC,CAJL,EAKKa,KALL,CAKW,UAAW,CACdC,CAA+B,CAACd,CAAD,CAClC,CAPL,EASA,GAAIiD,CAAJ,CAAU,CACNA,CAAI,CAACiE,aAAL,CAAmBC,cAAnB,GACAlE,CAAI,CAACiE,aAAL,CAAmBE,eAAnB,EACH,CACDH,CAAC,CAACG,eAAF,EACH,CAhBD,CAiBH,CA3fH,CAuiBMC,CAAK,CAAG,SAASrH,CAAT,CAAe,CACvB,GAAI,CAACA,CAAI,CAACwB,IAAL,CAAU,WAAV,CAAL,CAA6B,CACzB,GAAIJ,CAAgB,CAACpB,CAAD,CAApB,CAA4B,CAGxBkG,CAAkB,CAAClG,CAAD,CACrB,CAJD,IAIO,CAEHgE,CAAe,CAAChE,CAAD,CAClB,CAEDA,CAAI,CAACwB,IAAL,CAAU,WAAV,IACH,CACJ,CApjBH,CAsjBE,MAAO,CACHwE,IAAI,CAjDG,QAAPA,CAAAA,IAAO,CAAShG,CAAT,CAAe,CACtBA,CAAI,CAAGxB,CAAC,CAACwB,CAAD,CAAR,CAEAkD,CAAkB,CAAClD,CAAD,CAAOoE,IAAI,CAACC,GAAL,EAAP,CAAlB,CAEA,GAAIrE,CAAI,CAACsH,QAAL,CAAc,QAAd,CAAJ,CAA6B,CAEzBtD,CAAe,CAAChE,CAAD,CAAf,CACAA,CAAI,CAACwB,IAAL,CAAU,WAAV,IACH,CAEDsF,CAAsB,CAAC9G,CAAD,CACzB,CAoCM,CAEHuH,KAAK,CA9BG,QAARA,CAAAA,KAAQ,CAASvH,CAAT,CAAe,CACvBA,CAAI,CAACwH,UAAL,CAAgB,WAAhB,EACA,GAAIxH,CAAI,CAACsH,QAAL,CAAc,QAAd,CAAJ,CAA6B,CACzBD,CAAK,CAACrH,CAAD,CACR,CACJ,CAuBM,CAGHqH,KAAK,CAAEA,CAHJ,CAKV,CA/kBK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manage the timeline courses view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/str',\n 'core/templates',\n 'block_timeline/event_list',\n 'core_course/repository',\n 'block_timeline/calendar_events_repository'\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Str,\n Templates,\n EventList,\n CourseRepository,\n EventsRepository\n) {\n\n var SELECTORS = {\n MORE_COURSES_BUTTON: '[data-action=\"more-courses\"]',\n MORE_COURSES_BUTTON_CONTAINER: '[data-region=\"more-courses-button-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n COURSES_LIST: '[data-region=\"courses-list\"]',\n COURSE_ITEMS_LOADING_PLACEHOLDER: '[data-region=\"course-items-loading-placeholder\"]',\n COURSE_EVENTS_CONTAINER: '[data-region=\"course-events-container\"]',\n COURSE_NAME: '[data-region=\"course-name\"]',\n LOADING_ICON: '.loading-icon',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-region=\"search-input\"]'\n };\n\n var TEMPLATES = {\n COURSE_ITEMS: 'block_timeline/course-items',\n LOADING_ICON: 'core/loading'\n };\n\n var COURSE_CLASSIFICATION = 'inprogress';\n var COURSE_SORT = 'fullname asc';\n var COURSE_EVENT_LIMIT = 5;\n var COURSE_LIMIT = 2;\n var SECONDS_IN_DAY = 60 * 60 * 24;\n\n /**\n * Hide the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n var hideLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Hide the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var hideMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).addClass('hidden');\n };\n\n /**\n * Show the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var showMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).removeClass('hidden');\n };\n\n /**\n * Disable the \"more courses\" button and show the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var enableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {})\n .then(function(html) {\n button.append(html);\n return html;\n })\n .catch(function() {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Enable the \"more courses\" button and remove the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var disableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', false);\n button.find(SELECTORS.LOADING_ICON).remove();\n };\n\n /**\n * Display the message for when there are no courses available.\n *\n * @param {object} root The rool element.\n */\n var showNoCoursesEmptyMessage = function(root) {\n root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Render the course items HTML to the page.\n *\n * @param {object} root The rool element.\n * @param {string} html The course items HTML to render.\n */\n var renderCourseItemsHTML = function(root, html) {\n var container = root.find(SELECTORS.COURSES_LIST);\n Templates.appendNodeContents(container, html, '');\n };\n\n /**\n * Check if any courses have been loaded.\n *\n * @param {object} root The rool element.\n * @return {bool}\n */\n var hasLoadedCourses = function(root) {\n return root.find(SELECTORS.COURSE_EVENTS_CONTAINER).length > 0;\n };\n\n /**\n * Return the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getOffset = function(root) {\n return parseInt(root.attr('data-offset'), 10);\n };\n\n /**\n * Set the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @param {Number} offset Offset value.\n */\n var setOffset = function(root, offset) {\n root.attr('data-offset', offset);\n };\n\n /**\n * Return the limit value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-limit'), 10);\n };\n\n /**\n * Return the days offset value for fetching events.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getDaysOffset = function(root) {\n return parseInt(root.attr('data-days-offset'), 10);\n };\n\n /**\n * Return the days limit value for fetching events. The days\n * limit is optional so undefined will be returned if it isn't\n * set.\n *\n * @param {object} root The rool element.\n * @return {int|undefined}\n */\n var getDaysLimit = function(root) {\n var daysLimit = root.attr('data-days-limit');\n return daysLimit != undefined ? parseInt(daysLimit, 10) : undefined;\n };\n\n /**\n * Return the timestamp for the user's midnight.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getMidnight = function(root) {\n return parseInt(root.attr('data-midnight'), 10);\n };\n\n /**\n * Return the start time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getStartTime = function(root) {\n var midnight = getMidnight(root);\n var daysOffset = getDaysOffset(root);\n return midnight + (daysOffset * SECONDS_IN_DAY);\n };\n\n /**\n * Return the end time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEndTime = function(root) {\n var midnight = getMidnight(root);\n var daysLimit = getDaysLimit(root);\n return daysLimit != undefined ? midnight + (daysLimit * SECONDS_IN_DAY) : false;\n };\n\n /**\n * Get a list of events for the given course ids. Returns a promise that will\n * be resolved with the events.\n *\n * @param {array} courseIds The list of course ids to fetch events for.\n * @param {Number} startTime Timestamp to fetch events from.\n * @param {Number} limit Limit to the number of events (this applies per course, not total)\n * @param {Number} endTime Timestamp to fetch events to.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise.\n */\n var getEventsForCourseIds = function(courseIds, startTime, limit, endTime, searchValue) {\n var args = {\n courseids: courseIds,\n starttime: startTime,\n limit: limit\n };\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n return EventsRepository.queryByCourses(args);\n };\n\n /**\n * Get the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEventReloadTime = function(root) {\n return root.data('last-event-load-time');\n };\n\n /**\n * Set the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n */\n var setEventReloadTime = function(root, time) {\n root.data('last-event-load-time', time);\n };\n\n /**\n * Check if events have begun reloading since the given\n * time.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n * @return {bool}\n */\n var hasReloadedEventsSince = function(root, time) {\n return getEventReloadTime(root) > time;\n };\n\n /**\n * Send a request to the server to load the events for the courses.\n *\n * @param {array} courses List of course objects.\n * @param {Number} startTime Timestamp to load events after.\n * @param {int|undefined} endTime Timestamp to load events up until.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise resolved with the events.\n */\n var loadEventsForCourses = function(courses, startTime, endTime, searchValue) {\n var courseIds = courses.map(function(course) {\n return course.id;\n });\n\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue);\n };\n\n /**\n * Render the courses in the DOM once the server has returned the courses.\n *\n * @param {array} courses List of course objects.\n * @param {object} root The root element\n * @param {Number} midnight The midnight timestamp in the user's timezone.\n * @param {Number} daysOffset Number of days from today to offset the events.\n * @param {Number} daysLimit Number of days from today to limit the events to.\n * @return {object} jQuery promise resolved after rendering is complete.\n */\n var updateDisplayFromCourses = function(courses, root, midnight, daysOffset, daysLimit) {\n // Render the courses template.\n return Templates.render(TEMPLATES.COURSE_ITEMS, {\n courses: courses,\n midnight: midnight,\n hasdaysoffset: true,\n hasdayslimit: daysLimit != undefined,\n daysoffset: daysOffset,\n dayslimit: daysLimit,\n nodayslimit: daysLimit == undefined,\n }).then(function(html) {\n hideLoadingPlaceholder(root);\n\n if (html) {\n // Template rendering is complete and we have the HTML so we can\n // add it to the DOM.\n renderCourseItemsHTML(root, html);\n } else {\n if (!hasLoadedCourses(root)) {\n // There were no courses to render so show the empty placeholder\n // message for the user to tell them.\n showNoCoursesEmptyMessage(root);\n }\n }\n\n return html;\n })\n .then(function(html) {\n if (courses.length < COURSE_LIMIT) {\n // We know there aren't any more courses because we got back less\n // than we asked for so hide the button to request more.\n hideMoreCoursesButton(root);\n } else {\n // Make sure the button is visible if there are more courses to load.\n showMoreCoursesButton(root);\n }\n\n return html;\n })\n .catch(function() {\n hideLoadingPlaceholder(root);\n });\n };\n\n /**\n * Find all of the visible course blocks and initialise the event\n * list module to being loading the events for the course block.\n *\n * @param {object} root The root element for the timeline courses view.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var loadMoreCourses = function(root) {\n var offset = getOffset(root);\n var limit = getLimit(root);\n\n // Start loading the next set of courses.\n return CourseRepository.getEnrolledCoursesByTimelineClassification(\n COURSE_CLASSIFICATION,\n limit,\n offset,\n COURSE_SORT\n ).then(function(result) {\n var startEventLoadingTime = Date.now();\n var courses = result.courses;\n var nextOffset = result.nextoffset;\n var daysOffset = getDaysOffset(root);\n var daysLimit = getDaysLimit(root);\n var midnight = getMidnight(root);\n var startTime = getStartTime(root);\n var endTime = getEndTime(root);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Record the next offset if we want to request more courses.\n setOffset(root, nextOffset);\n // Load the events for these courses.\n var eventsPromise = loadEventsForCourses(courses, startTime, endTime, searchValue);\n // Render the courses in the DOM.\n var renderPromise = updateDisplayFromCourses(courses, root, midnight, daysOffset, daysLimit);\n\n return $.when(eventsPromise, renderPromise)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startEventLoadingTime)) {\n // All of the events are being reloaded so ignore our results.\n return eventsByCourse;\n }\n\n // When we've got all of the courses and events we can render the events in the\n // correct course event list.\n courses.forEach(function(course) {\n var courseId = course.id;\n var events = [];\n var containerSelector = '[data-region=\"course-events-container\"][data-course-id=\"' + courseId + '\"]';\n var courseEventsContainer = root.find(containerSelector);\n var eventListRoot = courseEventsContainer.find(EventList.rootSelector);\n var courseGroups = eventsByCourse.groupedbycourse.filter(function(group) {\n return group.courseid == courseId;\n });\n\n if (courseGroups.length) {\n // Get the events for this course.\n events = courseGroups[0].events;\n }\n\n // Create a preloaded page to pass to the event list because we've already\n // loaded the first page of events.\n var pageOnePreload = $.Deferred().resolve({events: events}).promise();\n // Initialise the event list pagination area for this course.\n Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', course.fullnamedisplay)\n .then(function(string) {\n EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, string);\n return string;\n })\n .catch(function() {\n // An error is ok, just render with the default string.\n EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload});\n });\n });\n\n return eventsByCourse;\n });\n }).catch(Notification.exception);\n };\n\n /**\n * Reload the events for all of the visible courses. These events will be loaded\n * in a single request to the server.\n *\n * @param {object} root The root element.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var reloadCourseEvents = function(root) {\n var startReloadTime = Date.now();\n var startTime = getStartTime(root);\n var endTime = getEndTime(root);\n var courseEventsContainers = root.find(SELECTORS.COURSE_EVENTS_CONTAINER);\n var courseIds = courseEventsContainers.map(function() {\n return $(this).attr('data-course-id');\n }).get();\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Record when we started our request.\n setEventReloadTime(root, startReloadTime);\n\n // Load all of the events for the given courses.\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startReloadTime)) {\n // A new reload has begun so ignore our results.\n return eventsByCourse;\n }\n\n courseEventsContainers.each(function(index, container) {\n container = $(container);\n var courseId = container.attr('data-course-id');\n var courseName = container.find(SELECTORS.COURSE_NAME).text();\n var eventListContainer = container.find(EventList.rootSelector);\n var pageDeferred = $.Deferred();\n var events = [];\n var courseGroups = eventsByCourse.groupedbycourse.filter(function(group) {\n return group.courseid == courseId;\n });\n\n if (courseGroups.length) {\n // Get the events just for this course.\n events = courseGroups[0].events;\n }\n\n pageDeferred.resolve({events: events});\n\n var additionalConfig = {courseview: true};\n // Re-initialise the events list with the preloaded events we just got from\n // the server.\n Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', courseName)\n .then(function(string) {\n EventList.init(eventListContainer, COURSE_EVENT_LIMIT, {'1': pageDeferred.promise()},\n string, additionalConfig);\n return string;\n })\n .catch(function() {\n // Ignore a failure to load the string. Just render with the default string.\n EventList.init(eventListContainer, COURSE_EVENT_LIMIT, {'1': pageDeferred.promise()},\n undefined, additionalConfig);\n });\n });\n\n return eventsByCourse;\n }).catch(Notification.exception);\n };\n\n /**\n * Add event listeners to load more courses for the courses view.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var registerEventListeners = function(root) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Show more courses and load their events when the user clicks the \"more courses\"\n // button.\n root.on(CustomEvents.events.activate, SELECTORS.MORE_COURSES_BUTTON, function(e, data) {\n enableMoreCoursesButtonLoading(root);\n loadMoreCourses(root)\n .then(function() {\n disableMoreCoursesButtonLoading(root);\n return;\n })\n .catch(function() {\n disableMoreCoursesButtonLoading(root);\n });\n\n if (data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }\n e.stopPropagation();\n });\n };\n\n /**\n * Initialise the timeline courses view. Begin loading the events\n * if this view is active. Add the relevant event listeners.\n *\n * This function should only be called once per page load because it\n * is adding event listeners to the page.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n setEventReloadTime(root, Date.now());\n\n if (root.hasClass('active')) {\n // Only load if this is active otherwise it will be lazy loaded later.\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n\n registerEventListeners(root);\n };\n\n /**\n * Reset the element back to it's initial state. Begin loading the events again\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n root.removeAttr('data-seen');\n if (root.hasClass('active')) {\n shown(root);\n }\n };\n\n /**\n * If this is the first time this view has been displayed then begin loading\n * the events.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen')) {\n if (hasLoadedCourses(root)) {\n // This isn't the first time this view is shown so just reload the\n // events for the courses we've already loaded.\n reloadCourseEvents(root);\n } else {\n // We haven't loaded any courses yet so do that now.\n loadMoreCourses(root);\n }\n\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"file":"view_courses.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/view_courses.js"],"names":["define","$","Notification","CustomEvents","Str","Templates","EventList","CourseRepository","EventsRepository","SELECTORS","MORE_COURSES_BUTTON","MORE_COURSES_BUTTON_CONTAINER","NO_COURSES_EMPTY_MESSAGE","COURSES_LIST","COURSE_ITEMS_LOADING_PLACEHOLDER","COURSE_EVENTS_CONTAINER","COURSE_NAME","LOADING_ICON","TIMELINE_BLOCK","TIMELINE_SEARCH","TEMPLATES","COURSE_ITEMS","COURSE_EVENT_LIMIT","SECONDS_IN_DAY","additionalConfig","courseview","hideLoadingPlaceholder","root","find","addClass","hideMoreCoursesButton","showMoreCoursesButton","removeClass","enableMoreCoursesButtonLoading","button","prop","render","then","html","append","catch","disableMoreCoursesButtonLoading","remove","showNoCoursesEmptyMessage","renderCourseItemsHTML","container","appendNodeContents","hasLoadedCourses","length","getOffset","parseInt","attr","setOffset","offset","getLimit","getDaysOffset","getDaysLimit","daysLimit","getMidnight","getStartTime","midnight","daysOffset","getEndTime","getEventsForCourseIds","courseIds","startTime","limit","endTime","searchValue","args","courseids","starttime","endtime","searchvalue","queryByCourses","getEventReloadTime","data","setEventReloadTime","time","hasReloadedEventsSince","loadEventsForCourses","courses","map","course","id","updateDisplayFromCourses","hasdaysoffset","hasdayslimit","daysoffset","dayslimit","nodayslimit","loadMoreCourses","getEnrolledCoursesByTimelineClassification","result","startEventLoadingTime","Date","now","nextOffset","nextoffset","closest","val","eventsPromise","renderPromise","when","eventsByCourse","forEach","courseId","events","courseEventsContainer","eventListRoot","rootSelector","courseGroups","groupedbycourse","filter","group","courseid","pageOnePreload","Deferred","resolve","promise","get_string","fullnamedisplay","string","init","exception","reloadCourseEvents","startReloadTime","courseEventsContainers","get","each","index","courseName","text","eventListContainer","pageDeferred","registerEventListeners","activate","on","e","originalEvent","preventDefault","stopPropagation","shown","hasClass","reset","removeAttr"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manage the timeline courses view for the timeline block.\n *\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/custom_interaction_events',\n 'core/str',\n 'core/templates',\n 'block_timeline/event_list',\n 'core_course/repository',\n 'block_timeline/calendar_events_repository'\n],\nfunction(\n $,\n Notification,\n CustomEvents,\n Str,\n Templates,\n EventList,\n CourseRepository,\n EventsRepository\n) {\n\n var SELECTORS = {\n MORE_COURSES_BUTTON: '[data-action=\"more-courses\"]',\n MORE_COURSES_BUTTON_CONTAINER: '[data-region=\"more-courses-button-container\"]',\n NO_COURSES_EMPTY_MESSAGE: '[data-region=\"no-courses-empty-message\"]',\n COURSES_LIST: '[data-region=\"courses-list\"]',\n COURSE_ITEMS_LOADING_PLACEHOLDER: '[data-region=\"course-items-loading-placeholder\"]',\n COURSE_EVENTS_CONTAINER: '[data-region=\"course-events-container\"]',\n COURSE_NAME: '[data-region=\"course-name\"]',\n LOADING_ICON: '.loading-icon',\n TIMELINE_BLOCK: '[data-region=\"timeline\"]',\n TIMELINE_SEARCH: '[data-region=\"search-input\"]'\n };\n\n var TEMPLATES = {\n COURSE_ITEMS: 'block_timeline/course-items',\n LOADING_ICON: 'core/loading'\n };\n\n var COURSE_CLASSIFICATION = 'inprogress';\n var COURSE_SORT = 'fullname asc';\n var COURSE_EVENT_LIMIT = 5;\n var COURSE_LIMIT = 2;\n var SECONDS_IN_DAY = 60 * 60 * 24;\n\n const additionalConfig = {courseview: true};\n\n /**\n * Hide the loading placeholder elements.\n *\n * @param {object} root The rool element.\n */\n var hideLoadingPlaceholder = function(root) {\n root.find(SELECTORS.COURSE_ITEMS_LOADING_PLACEHOLDER).addClass('hidden');\n };\n\n /**\n * Hide the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var hideMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).addClass('hidden');\n };\n\n /**\n * Show the \"more courses\" button.\n *\n * @param {object} root The rool element.\n */\n var showMoreCoursesButton = function(root) {\n root.find(SELECTORS.MORE_COURSES_BUTTON_CONTAINER).removeClass('hidden');\n };\n\n /**\n * Disable the \"more courses\" button and show the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var enableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', true);\n Templates.render(TEMPLATES.LOADING_ICON, {})\n .then(function(html) {\n button.append(html);\n return html;\n })\n .catch(function() {\n // It's not important if this false so just do so silently.\n return false;\n });\n };\n\n /**\n * Enable the \"more courses\" button and remove the loading spinner.\n *\n * @param {object} root The rool element.\n */\n var disableMoreCoursesButtonLoading = function(root) {\n var button = root.find(SELECTORS.MORE_COURSES_BUTTON);\n button.prop('disabled', false);\n button.find(SELECTORS.LOADING_ICON).remove();\n };\n\n /**\n * Display the message for when there are no courses available.\n *\n * @param {object} root The rool element.\n */\n var showNoCoursesEmptyMessage = function(root) {\n root.find(SELECTORS.NO_COURSES_EMPTY_MESSAGE).removeClass('hidden');\n };\n\n /**\n * Render the course items HTML to the page.\n *\n * @param {object} root The rool element.\n * @param {string} html The course items HTML to render.\n */\n var renderCourseItemsHTML = function(root, html) {\n var container = root.find(SELECTORS.COURSES_LIST);\n Templates.appendNodeContents(container, html, '');\n };\n\n /**\n * Check if any courses have been loaded.\n *\n * @param {object} root The rool element.\n * @return {bool}\n */\n var hasLoadedCourses = function(root) {\n return root.find(SELECTORS.COURSE_EVENTS_CONTAINER).length > 0;\n };\n\n /**\n * Return the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getOffset = function(root) {\n return parseInt(root.attr('data-offset'), 10);\n };\n\n /**\n * Set the offset value for fetching courses.\n *\n * @param {object} root The rool element.\n * @param {Number} offset Offset value.\n */\n var setOffset = function(root, offset) {\n root.attr('data-offset', offset);\n };\n\n /**\n * Return the limit value for fetching courses.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-limit'), 10);\n };\n\n /**\n * Return the days offset value for fetching events.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getDaysOffset = function(root) {\n return parseInt(root.attr('data-days-offset'), 10);\n };\n\n /**\n * Return the days limit value for fetching events. The days\n * limit is optional so undefined will be returned if it isn't\n * set.\n *\n * @param {object} root The rool element.\n * @return {int|undefined}\n */\n var getDaysLimit = function(root) {\n var daysLimit = root.attr('data-days-limit');\n return daysLimit != undefined ? parseInt(daysLimit, 10) : undefined;\n };\n\n /**\n * Return the timestamp for the user's midnight.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getMidnight = function(root) {\n return parseInt(root.attr('data-midnight'), 10);\n };\n\n /**\n * Return the start time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getStartTime = function(root) {\n var midnight = getMidnight(root);\n var daysOffset = getDaysOffset(root);\n return midnight + (daysOffset * SECONDS_IN_DAY);\n };\n\n /**\n * Return the end time for fetching events. This is calculated\n * based on the user's midnight value so that timezones are\n * preserved.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEndTime = function(root) {\n var midnight = getMidnight(root);\n var daysLimit = getDaysLimit(root);\n return daysLimit != undefined ? midnight + (daysLimit * SECONDS_IN_DAY) : false;\n };\n\n /**\n * Get a list of events for the given course ids. Returns a promise that will\n * be resolved with the events.\n *\n * @param {array} courseIds The list of course ids to fetch events for.\n * @param {Number} startTime Timestamp to fetch events from.\n * @param {Number} limit Limit to the number of events (this applies per course, not total)\n * @param {Number} endTime Timestamp to fetch events to.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise.\n */\n var getEventsForCourseIds = function(courseIds, startTime, limit, endTime, searchValue) {\n var args = {\n courseids: courseIds,\n starttime: startTime,\n limit: limit\n };\n\n if (endTime) {\n args.endtime = endTime;\n }\n\n if (searchValue) {\n args.searchvalue = searchValue;\n }\n\n return EventsRepository.queryByCourses(args);\n };\n\n /**\n * Get the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @return {Number}\n */\n var getEventReloadTime = function(root) {\n return root.data('last-event-load-time');\n };\n\n /**\n * Set the last time the events were reloaded.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n */\n var setEventReloadTime = function(root, time) {\n root.data('last-event-load-time', time);\n };\n\n /**\n * Check if events have begun reloading since the given\n * time.\n *\n * @param {object} root The rool element.\n * @param {Number} time Timestamp in milliseconds.\n * @return {bool}\n */\n var hasReloadedEventsSince = function(root, time) {\n return getEventReloadTime(root) > time;\n };\n\n /**\n * Send a request to the server to load the events for the courses.\n *\n * @param {array} courses List of course objects.\n * @param {Number} startTime Timestamp to load events after.\n * @param {int|undefined} endTime Timestamp to load events up until.\n * @param {string|undefined} searchValue Search value\n * @return {object} jQuery promise resolved with the events.\n */\n var loadEventsForCourses = function(courses, startTime, endTime, searchValue) {\n var courseIds = courses.map(function(course) {\n return course.id;\n });\n\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue);\n };\n\n /**\n * Render the courses in the DOM once the server has returned the courses.\n *\n * @param {array} courses List of course objects.\n * @param {object} root The root element\n * @param {Number} midnight The midnight timestamp in the user's timezone.\n * @param {Number} daysOffset Number of days from today to offset the events.\n * @param {Number} daysLimit Number of days from today to limit the events to.\n * @return {object} jQuery promise resolved after rendering is complete.\n */\n var updateDisplayFromCourses = function(courses, root, midnight, daysOffset, daysLimit) {\n // Render the courses template.\n return Templates.render(TEMPLATES.COURSE_ITEMS, {\n courses: courses,\n midnight: midnight,\n hasdaysoffset: true,\n hasdayslimit: daysLimit != undefined,\n daysoffset: daysOffset,\n dayslimit: daysLimit,\n nodayslimit: daysLimit == undefined,\n }).then(function(html) {\n hideLoadingPlaceholder(root);\n\n if (html) {\n // Template rendering is complete and we have the HTML so we can\n // add it to the DOM.\n renderCourseItemsHTML(root, html);\n } else {\n if (!hasLoadedCourses(root)) {\n // There were no courses to render so show the empty placeholder\n // message for the user to tell them.\n showNoCoursesEmptyMessage(root);\n }\n }\n\n return html;\n })\n .then(function(html) {\n if (courses.length < COURSE_LIMIT) {\n // We know there aren't any more courses because we got back less\n // than we asked for so hide the button to request more.\n hideMoreCoursesButton(root);\n } else {\n // Make sure the button is visible if there are more courses to load.\n showMoreCoursesButton(root);\n }\n\n return html;\n })\n .catch(function() {\n hideLoadingPlaceholder(root);\n });\n };\n\n /**\n * Find all of the visible course blocks and initialise the event\n * list module to being loading the events for the course block.\n *\n * @param {object} root The root element for the timeline courses view.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var loadMoreCourses = function(root) {\n var offset = getOffset(root);\n var limit = getLimit(root);\n\n // Start loading the next set of courses.\n return CourseRepository.getEnrolledCoursesByTimelineClassification(\n COURSE_CLASSIFICATION,\n limit,\n offset,\n COURSE_SORT\n ).then(function(result) {\n var startEventLoadingTime = Date.now();\n var courses = result.courses;\n var nextOffset = result.nextoffset;\n var daysOffset = getDaysOffset(root);\n var daysLimit = getDaysLimit(root);\n var midnight = getMidnight(root);\n var startTime = getStartTime(root);\n var endTime = getEndTime(root);\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Record the next offset if we want to request more courses.\n setOffset(root, nextOffset);\n // Load the events for these courses.\n var eventsPromise = loadEventsForCourses(courses, startTime, endTime, searchValue);\n // Render the courses in the DOM.\n var renderPromise = updateDisplayFromCourses(courses, root, midnight, daysOffset, daysLimit);\n\n return $.when(eventsPromise, renderPromise)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startEventLoadingTime)) {\n // All of the events are being reloaded so ignore our results.\n return eventsByCourse;\n }\n\n // When we've got all of the courses and events we can render the events in the\n // correct course event list.\n courses.forEach(function(course) {\n var courseId = course.id;\n var events = [];\n var containerSelector = '[data-region=\"course-events-container\"][data-course-id=\"' + courseId + '\"]';\n var courseEventsContainer = root.find(containerSelector);\n var eventListRoot = courseEventsContainer.find(EventList.rootSelector);\n var courseGroups = eventsByCourse.groupedbycourse.filter(function(group) {\n return group.courseid == courseId;\n });\n\n if (courseGroups.length) {\n // Get the events for this course.\n events = courseGroups[0].events;\n }\n\n // Create a preloaded page to pass to the event list because we've already\n // loaded the first page of events.\n var pageOnePreload = $.Deferred().resolve({events: events}).promise();\n // Initialise the event list pagination area for this course.\n Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', course.fullnamedisplay)\n .then(function(string) {\n EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, string, additionalConfig);\n return string;\n })\n .catch(function() {\n // An error is ok, just render with the default string.\n EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, undefined,\n additionalConfig);\n });\n });\n\n return eventsByCourse;\n });\n }).catch(Notification.exception);\n };\n\n /**\n * Reload the events for all of the visible courses. These events will be loaded\n * in a single request to the server.\n *\n * @param {object} root The root element.\n * @return {object} jQuery promise resolved with courses and events.\n */\n var reloadCourseEvents = function(root) {\n var startReloadTime = Date.now();\n var startTime = getStartTime(root);\n var endTime = getEndTime(root);\n var courseEventsContainers = root.find(SELECTORS.COURSE_EVENTS_CONTAINER);\n var courseIds = courseEventsContainers.map(function() {\n return $(this).attr('data-course-id');\n }).get();\n const searchValue = root.closest(SELECTORS.TIMELINE_BLOCK).find(SELECTORS.TIMELINE_SEARCH).val();\n\n // Record when we started our request.\n setEventReloadTime(root, startReloadTime);\n\n // Load all of the events for the given courses.\n return getEventsForCourseIds(courseIds, startTime, COURSE_EVENT_LIMIT + 1, endTime, searchValue)\n .then(function(eventsByCourse) {\n if (hasReloadedEventsSince(root, startReloadTime)) {\n // A new reload has begun so ignore our results.\n return eventsByCourse;\n }\n\n courseEventsContainers.each(function(index, container) {\n container = $(container);\n var courseId = container.attr('data-course-id');\n var courseName = container.find(SELECTORS.COURSE_NAME).text();\n var eventListContainer = container.find(EventList.rootSelector);\n var pageDeferred = $.Deferred();\n var events = [];\n var courseGroups = eventsByCourse.groupedbycourse.filter(function(group) {\n return group.courseid == courseId;\n });\n\n if (courseGroups.length) {\n // Get the events just for this course.\n events = courseGroups[0].events;\n }\n\n pageDeferred.resolve({events: events});\n\n // Re-initialise the events list with the preloaded events we just got from\n // the server.\n Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', courseName)\n .then(function(string) {\n EventList.init(eventListContainer, COURSE_EVENT_LIMIT, {'1': pageDeferred.promise()},\n string, additionalConfig);\n return string;\n })\n .catch(function() {\n // Ignore a failure to load the string. Just render with the default string.\n EventList.init(eventListContainer, COURSE_EVENT_LIMIT, {'1': pageDeferred.promise()},\n undefined, additionalConfig);\n });\n });\n\n return eventsByCourse;\n }).catch(Notification.exception);\n };\n\n /**\n * Add event listeners to load more courses for the courses view.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var registerEventListeners = function(root) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Show more courses and load their events when the user clicks the \"more courses\"\n // button.\n root.on(CustomEvents.events.activate, SELECTORS.MORE_COURSES_BUTTON, function(e, data) {\n enableMoreCoursesButtonLoading(root);\n loadMoreCourses(root)\n .then(function() {\n disableMoreCoursesButtonLoading(root);\n return;\n })\n .catch(function() {\n disableMoreCoursesButtonLoading(root);\n });\n\n if (data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n }\n e.stopPropagation();\n });\n };\n\n /**\n * Initialise the timeline courses view. Begin loading the events\n * if this view is active. Add the relevant event listeners.\n *\n * This function should only be called once per page load because it\n * is adding event listeners to the page.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var init = function(root) {\n root = $(root);\n\n setEventReloadTime(root, Date.now());\n\n if (root.hasClass('active')) {\n // Only load if this is active otherwise it will be lazy loaded later.\n loadMoreCourses(root);\n root.attr('data-seen', true);\n }\n\n registerEventListeners(root);\n };\n\n /**\n * Reset the element back to it's initial state. Begin loading the events again\n * if this view is active.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var reset = function(root) {\n root.removeAttr('data-seen');\n if (root.hasClass('active')) {\n shown(root);\n }\n };\n\n /**\n * If this is the first time this view has been displayed then begin loading\n * the events.\n *\n * @param {object} root The root element for the timeline courses view.\n */\n var shown = function(root) {\n if (!root.attr('data-seen')) {\n if (hasLoadedCourses(root)) {\n // This isn't the first time this view is shown so just reload the\n // events for the courses we've already loaded.\n reloadCourseEvents(root);\n } else {\n // We haven't loaded any courses yet so do that now.\n loadMoreCourses(root);\n }\n\n root.attr('data-seen', true);\n }\n };\n\n return {\n init: init,\n reset: reset,\n shown: shown\n };\n});\n"],"file":"view_courses.min.js"} \ No newline at end of file diff --git a/blocks/timeline/amd/src/view_courses.js b/blocks/timeline/amd/src/view_courses.js index 22c24842937..575ebf87fb6 100644 --- a/blocks/timeline/amd/src/view_courses.js +++ b/blocks/timeline/amd/src/view_courses.js @@ -66,6 +66,8 @@ function( var COURSE_LIMIT = 2; var SECONDS_IN_DAY = 60 * 60 * 24; + const additionalConfig = {courseview: true}; + /** * Hide the loading placeholder elements. * @@ -441,12 +443,13 @@ function( // Initialise the event list pagination area for this course. Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', course.fullnamedisplay) .then(function(string) { - EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, string); + EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, string, additionalConfig); return string; }) .catch(function() { // An error is ok, just render with the default string. - EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}); + EventList.init(eventListRoot, COURSE_EVENT_LIMIT, {'1': pageOnePreload}, undefined, + additionalConfig); }); }); @@ -501,7 +504,6 @@ function( pageDeferred.resolve({events: events}); - var additionalConfig = {courseview: true}; // Re-initialise the events list with the preloaded events we just got from // the server. Str.get_string('ariaeventlistpaginationnavcourses', 'block_timeline', courseName)