Reworked category selection

This commit is contained in:
PMKuipers 2023-12-13 23:49:06 +01:00
parent 32bab2de5e
commit b8c0f910c1
27 changed files with 343 additions and 150 deletions

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/modedit-modal",["exports","core/fragment","./util/string-helper","core/ajax","core/notification","core/templates"],(function(_exports,_fragment,_stringHelper,_ajax,_notification,_templates){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};var _default={install(Vue){let strings=(0,_stringHelper.load_strings)({editmod:{save$core:"save$core",cancel$core:"cancel$core"}});Vue.component("s-edit-mod",{props:{cmid:{type:Number},coursectxid:{type:Number},title:{type:String,default:""},genericonly:{type:Boolean,default:!1}},data:()=>({content:"",text:strings.editmod}),computed:{},methods:{openForm(){this.$refs.editormodal.show()},onShown(){const self=this;let params={cmid:this.cmid};console.info("Loading form"),(0,_fragment.loadFragment)("local_treestudyplan","mod_edit_form",this.coursectxid,params).then(((html,js)=>{(0,_templates.replaceNodeContents)(self.$refs.content,html,js)})).catch(_notification.default.exception)},onSave(){const self=this;let form=this.$refs.content.getElementsByTagName("form")[0];form.dispatchEvent(new Event("save-form-state"));const formdata=new FormData(form),data=new URLSearchParams(formdata).toString();(0,_ajax.call)([{methodname:"local_treestudyplan_submit_cm_editform",args:{cmid:this.cmid,formdata:data}}])[0].done((()=>{self.$emit("saved",formdata)})).fail(_notification.default.exception)}},template:'\n <span class=\'s-edit-mod\'><a href=\'#\' @click.prevent="openForm"><slot><i class="fa fa-cog"></i></slot></a>\n <b-modal\n ref="editormodal"\n scrollable\n centered\n size="xl"\n id="\'modal-cm-\'+cmid"\n @shown="onShown"\n @ok="onSave"\n :title="title"\n :ok-title="text.save$core"\n ><div :class="\'s-edit-mod-form \'+ (genericonly?\'genericonly\':\'\')" ref="content"\n ><div class="d-flex justify-content-center mb-3"><b-spinner variant="primary"></b-spinner></div\n ></div\n ></b-modal>\n </span>\n '})}};return _exports.default=_default,_exports.default}));
define("local_treestudyplan/modedit-modal",["exports","core/fragment","./util/string-helper","core/ajax","core/notification","core/templates"],(function(_exports,_fragment,_stringHelper,_ajax,_notification,_templates){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};var _default={install(Vue){let strings=(0,_stringHelper.load_strings)({editmod:{save$core:"save$core",cancel$core:"cancel$core"}});Vue.component("s-edit-mod",{props:{cmid:{type:Number},coursectxid:{type:Number},title:{type:String,default:""},genericonly:{type:Boolean,default:!1}},data:()=>({content:"",text:strings.editmod}),computed:{},methods:{openForm(){this.$refs.editormodal.show()},onShown(){const self=this;let params={cmid:this.cmid};console.info("Loading form"),(0,_fragment.loadFragment)("local_treestudyplan","mod_edit_form",this.coursectxid,params).then(((html,js)=>{(0,_templates.replaceNodeContents)(self.$refs.content,html,js)})).catch(_notification.default.exception)},onSave(){const self=this;let form=this.$refs.content.getElementsByTagName("form")[0];form.dispatchEvent(new Event("save-form-state"));const formdata=new FormData(form),data=new URLSearchParams(formdata).toString();(0,_ajax.call)([{methodname:"local_treestudyplan_submit_cm_editform",args:{cmid:this.cmid,formdata:data}}])[0].then((()=>{self.$emit("saved",formdata)})).catch(_notification.default.exception)}},template:'\n <span class=\'s-edit-mod\'><a href=\'#\' @click.prevent="openForm"><slot><i class="fa fa-cog"></i></slot></a>\n <b-modal\n ref="editormodal"\n scrollable\n centered\n size="xl"\n id="\'modal-cm-\'+cmid"\n @shown="onShown"\n @ok="onSave"\n :title="title"\n :ok-title="text.save$core"\n ><div :class="\'s-edit-mod-form \'+ (genericonly?\'genericonly\':\'\')" ref="content"\n ><div class="d-flex justify-content-center mb-3"><b-spinner variant="primary"></b-spinner></div\n ></div\n ></b-modal>\n </span>\n '})}};return _exports.default=_default,_exports.default}));
//# sourceMappingURL=modedit-modal.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/page-invitemanager",["jquery","core/str","core/ajax","core/modal_factory","core/modal_events","local_treestudyplan/handlers","local_treestudyplan/debugger"],(function($,str,ajax,ModalFactory,ModalEvents,handlers,Debugger){let debug=new Debugger("treestudyplan");return{init:function(){$(".path-local-treestudyplan a.m-action-confirm").on("click",(function(e){e.preventDefault();let $link=$(e.currentTarget),href=$link.attr("data-actionhref"),text=$link.attr("data-confirmtext"),oktext=$link.attr("data-confirmbtn");debug.info("Ok",oktext),null==oktext&&(oktext=str.get_string("ok"));let title=$link.attr("data-confirmtitle");debug.info("Title",title),null==title&&(title=str.get_string("confirm")),debug.info("Link, href, text",$link,href,text),ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL,title:title,body:text}).then((function(modal){modal.setSaveButtonText(oktext),modal.getRoot().on(ModalEvents.save,(function(){window.location=href})),$(modal.modal).css("max-width","345px"),modal.show()}))}))}}}));
define("local_treestudyplan/page-invitemanager",["exports","./util/debugger","core/str","core/modal_factory","core/modal_events"],(function(_exports,_debugger,_str,_modal_factory,_modal_events){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){getstr_func([{key:"ok",component:"core"},{key:"confirm",component:"core"}]).then((s=>{const strOk=s[0],strConfirm=s[1];document.querySelectorAll(".path-local-treestudyplan a.m-action-confirm").forEach((el=>{el.addEventListener("click",(e=>{e.preventDefault();const link=e.currentTarget;let href=link.getAttribute("data-actionhref"),text=link.getAttribute("data-confirmtext"),oktext=link.getAttribute("data-confirmbtn");null==oktext&&(oktext=strOk);let title=link.getAttribute("data-confirmtitle");null==title&&(title=strConfirm),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:text}).then((function(modal){return modal.setSaveButtonText(oktext),modal.getRoot().on(_modal_events.default.save,(function(){window.location=href})),modal.modal[0].style["max-width"]="345px",modal.show(),modal}))}))}))}))},_debugger=_interopRequireDefault(_debugger),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events);const getstr_func=void 0!==_str.getStrings?_str.getStrings:_str.get_strings;new _debugger.default("treestudyplan")}));
//# sourceMappingURL=page-invitemanager.min.js.map

View File

@ -1 +1 @@
{"version":3,"file":"page-invitemanager.min.js","sources":["../src/page-invitemanager.js"],"sourcesContent":["/*eslint no-var: \"error\" */\n/*eslint no-unused-vars: \"off\" */\n/*eslint linebreak-style: \"off\" */\n/*eslint-env es6*/\n// Put this file in path/to/plugin/amd/src\n// You can call it anything you like\n\ndefine(['jquery', 'core/str', 'core/ajax', 'core/modal_factory', 'core/modal_events',\n 'local_treestudyplan/handlers', 'local_treestudyplan/debugger'],\nfunction ($, str, ajax, ModalFactory, ModalEvents,\n handlers, Debugger) {\n let debug = new Debugger(\"treestudyplan\");\n\n let self = {\n init: function init() {\n $('.path-local-treestudyplan a.m-action-confirm').on('click', function (e) {\n e.preventDefault();\n let $link = $(e.currentTarget);\n let href = $link.attr('data-actionhref');\n let text = $link.attr('data-confirmtext');\n let oktext = $link.attr('data-confirmbtn');\n debug.info(\"Ok\", oktext);\n if (undefined == oktext) { oktext = str.get_string('ok'); }\n let title = $link.attr('data-confirmtitle');\n debug.info(\"Title\", title);\n if (undefined == title) { title = str.get_string('confirm'); }\n\n debug.info(\"Link, href, text\", $link, href, text);\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: text,\n }).then(function (modal) {\n modal.setSaveButtonText(oktext);\n\n let root = modal.getRoot();\n root.on(ModalEvents.save, function () {\n window.location = href;\n });\n\n $(modal.modal).css(\"max-width\", \"345px\");\n modal.show();\n });\n });\n },\n\n\n };\n return self;\n});"],"names":["define","$","str","ajax","ModalFactory","ModalEvents","handlers","Debugger","debug","init","on","e","preventDefault","$link","currentTarget","href","attr","text","oktext","info","undefined","get_string","title","create","type","types","SAVE_CANCEL","body","then","modal","setSaveButtonText","getRoot","save","window","location","css","show"],"mappings":"AAOAA,gDAAO,CAAC,SAAU,WAAY,YAAa,qBAAsB,oBACzD,+BAAgC,iCACxC,SAAUC,EAAGC,IAAKC,KAAMC,aAAcC,YAC5BC,SAAUC,cACZC,MAAQ,IAAID,SAAS,uBAEd,CACPE,KAAM,WACFR,EAAE,gDAAgDS,GAAG,SAAS,SAAUC,GACpEA,EAAEC,qBACEC,MAAQZ,EAAEU,EAAEG,eACZC,KAAOF,MAAMG,KAAK,mBAClBC,KAAOJ,MAAMG,KAAK,oBAClBE,OAASL,MAAMG,KAAK,mBACxBR,MAAMW,KAAK,KAAMD,QACbE,MAAaF,SAAUA,OAAShB,IAAImB,WAAW,WAC/CC,MAAQT,MAAMG,KAAK,qBACvBR,MAAMW,KAAK,QAASG,OAChBF,MAAaE,QAASA,MAAQpB,IAAImB,WAAW,YAEjDb,MAAMW,KAAK,mBAAoBN,MAAOE,KAAME,MAE5Cb,aAAamB,OAAO,CAChBC,KAAMpB,aAAaqB,MAAMC,YACzBJ,MAAOA,MACPK,KAAMV,OACPW,MAAK,SAAUC,OACdA,MAAMC,kBAAkBZ,QAEbW,MAAME,UACZrB,GAAGL,YAAY2B,MAAM,WACtBC,OAAOC,SAAWnB,QAGtBd,EAAE4B,MAAMA,OAAOM,IAAI,YAAa,SAChCN,MAAMO,cAQzB"}
{"version":3,"file":"page-invitemanager.min.js","sources":["../src/page-invitemanager.js"],"sourcesContent":["/*eslint no-var: \"error\" */\n/*eslint no-unused-vars: \"off\" */\n/*eslint linebreak-style: \"off\" */\n/*eslint-env es6*/\n// Put this file in path/to/plugin/amd/src\n// You can call it anything you like\n\nimport Debugger from './util/debugger';\nimport {get_strings} from 'core/str';\nimport {getStrings} from 'core/str';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\n\n/* Determine the proper getstrings function to use (MDL4.3+ recommends use of getStrings, which is jquery independent) */\nconst getstr_func = (getStrings !== undefined)?getStrings:get_strings;\n\nlet debug = new Debugger(\"treestudyplan\");\n\n /**\n * Init function for page-invitemanager\n * @return undefined\n */\nexport function init() {\n getstr_func([\n { key: 'ok', component: 'core'},\n { key: 'confirm', component: 'core'},\n ]).then((s) => {\n const strOk = s[0];\n const strConfirm = s[1];\n\n const els = document.querySelectorAll('.path-local-treestudyplan a.m-action-confirm');\n els.forEach((el) => {\n el.addEventListener('click', (e) => {\n e.preventDefault();\n const link = e.currentTarget;\n let href = link.getAttribute('data-actionhref');\n let text = link.getAttribute('data-confirmtext');\n let oktext = link.getAttribute('data-confirmbtn');\n if (undefined == oktext) {\n oktext = strOk;\n }\n let title = link.getAttribute('data-confirmtitle');\n if (undefined == title) {\n title = strConfirm;\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: text,\n }).then(function (modal) {\n modal.setSaveButtonText(oktext);\n\n let root = modal.getRoot();\n root.on(ModalEvents.save, function () {\n window.location = href;\n });\n modal.modal[0].style[\"max-width\"] = \"345px\";\n modal.show();\n return modal;\n });\n });\n });\n });\n}\n"],"names":["getstr_func","key","component","then","s","strOk","strConfirm","document","querySelectorAll","forEach","el","addEventListener","e","preventDefault","link","currentTarget","href","getAttribute","text","oktext","undefined","title","create","type","ModalFactory","types","SAVE_CANCEL","body","modal","setSaveButtonText","getRoot","on","ModalEvents","save","window","location","style","show","getStrings","get_strings","Debugger"],"mappings":"qWAuBIA,YAAY,CACR,CAAEC,IAAK,KAAMC,UAAW,QACxB,CAAED,IAAK,UAAWC,UAAW,UAC9BC,MAAMC,UACCC,MAAQD,EAAE,GACVE,WAAaF,EAAE,GAETG,SAASC,iBAAiB,gDAClCC,SAASC,KACTA,GAAGC,iBAAiB,SAAUC,IAC1BA,EAAEC,uBACIC,KAAOF,EAAEG,kBACXC,KAAOF,KAAKG,aAAa,mBACzBC,KAAOJ,KAAKG,aAAa,oBACzBE,OAASL,KAAKG,aAAa,mBAC3BG,MAAaD,SACbA,OAASd,WAETgB,MAAQP,KAAKG,aAAa,qBAC1BG,MAAaC,QACbA,MAAQf,mCAGCgB,OAAO,CAChBC,KAAMC,uBAAaC,MAAMC,YACzBL,MAAOA,MACPM,KAAMT,OACPf,MAAK,SAAUyB,cACdA,MAAMC,kBAAkBV,QAEbS,MAAME,UACZC,GAAGC,sBAAYC,MAAM,WACtBC,OAAOC,SAAWnB,QAEtBY,MAAMA,MAAM,GAAGQ,MAAM,aAAe,QACpCR,MAAMS,OACCT,+KA7CrB5B,iBAA8BoB,IAAfkB,gBAA0BA,gBAAWC,iBAE9C,IAAIC,kBAAS"}

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/page-view-plan",["exports","core/ajax","core/notification","./vue/vue","./util/debugger","./util/string-helper","./studyplan-processor","./util/date-helper","./report-viewer-components","./treestudyplan-components","./modedit-modal","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_ajax,_notification,_vue,_debugger,_stringHelper,_studyplanProcessor,_dateHelper,_reportViewerComponents,_treestudyplanComponents,_modeditModal,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(contextid,categoryid){contextid=void 0===contextid||!Number.isInteger(Number(contextid))||contextid<1?1:Number(contextid);categoryid=void 0!==categoryid&&Number.isInteger(Number(categoryid))?Number(categoryid):0;let app=new _vue.default({el:"#root",data:{displayedstudyplan:null,activestudyplan:null,associatedstudents:[],selectedstudent:null,studentstudyplan:null,loadingstudyplan:!1,studyplans:[],text:strings.studyplan,toolbox:{right:!0},usedcontexts:[]},async mounted(){(0,_ajax.call)([{methodname:"local_treestudyplan_list_studyplans",args:{context_id:contextid}}])[0].done((function(response){const timingval={present:0,past:1,future:2};response.sort(((a,b)=>{const timinga=(0,_dateHelper.studyplanTiming)(a),timingb=(0,_dateHelper.studyplanTiming)(b),t=timingval[timinga]-timingval[timingb];return 0==t?a.name.localeCompare(b.name):t})),app.studyplans=response;const parts=window.location.hash.replace("#","").split("-");if(parts&&parts.length>0)for(let idx in app.studyplans)if(app.studyplans[idx].id==parts[0]){app.selectStudyplan(app.studyplans[idx],parts[1]);break}})).fail(_notification.default.exception),(0,_ajax.call)([{methodname:"local_treestudyplan_list_used_categories",args:{operation:"view"}}])[0].done((function(response){const contexts=[];for(const ix in response)response[ix].studyplancount>0&&contexts.push(response[ix]);app.usedcontexts=contexts})).fail(_notification.default.exception)},computed:{dropdown_title(){return this.activestudyplan&&this.activestudyplan.name?this.activestudyplan.name:this.text.studyplan_select_placeholder},contextid:()=>contextid},methods:{switchContext(cat){const params=new URLSearchParams(location.search);params.delete("categoryid"),params.set("contextid",cat.context_id),window.location.search=params.toString()},closeStudyplan(){app.activestudyplan=null,app.associatedstudents=[],app.studentstudyplan=[],app.displayedstudyplan=null,window.location.hash=""},selectStudyplan(studyplan,studentid){app.loadingstudyplan=!0,app.activestudyplan=null,app.associatedstudents=[],app.selectedstudent=null,app.studentstudyplan=null,(0,_ajax.call)([{methodname:"local_treestudyplan_get_studyplan_map",args:{id:studyplan.id}}])[0].done((function(response){app.activestudyplan=(0,_studyplanProcessor.ProcessStudyplan)(response,!0),app.displayedstudyplan=app.activestudyplan,app.loadingstudyplan=!1,window.location.hash=app.activestudyplan.id,(0,_ajax.call)([{methodname:"local_treestudyplan_all_associated",args:{studyplan_id:studyplan.id}}])[0].done((function(response){if(app.associatedstudents=response,studentid)for(const student of app.associatedstudents)if(student.id==studentid){app.showStudentView(student);break}})).fail(_notification.default.exception)})).fail((function(error){_notification.default.exception(error),app.loadingstudyplan=!1}))},showStudentView(student){app.selectedstudent=student,app.studentstudyplan=null,app.loadingstudyplan=!0,(0,_ajax.call)([{methodname:"local_treestudyplan_get_user_studyplan",args:{userid:student.id,studyplanid:app.activestudyplan.id}}])[0].done((function(response){app.studentstudyplan=(0,_studyplanProcessor.ProcessStudyplan)(response,!1),app.displayedstudyplan=app.studentstudyplan,app.loadingstudyplan=!1,window.location.hash=app.activestudyplan.id+"-"+student.id})).fail((function(error){_notification.default.exception(error),app.loadingstudyplan=!1}))},showOverview(){app.selectedstudent=null,app.studentstudyplan=null,app.displayedstudyplan=app.activestudyplan,window.location.hash=app.activestudyplan.id}}})},_notification=_interopRequireDefault(_notification),_vue=_interopRequireDefault(_vue),_debugger=_interopRequireDefault(_debugger),_reportViewerComponents=_interopRequireDefault(_reportViewerComponents),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents),_modeditModal=_interopRequireDefault(_modeditModal),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_reportViewerComponents.default),_vue.default.use(_modeditModal.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);new _debugger.default("treestudyplanviewer");let strings=(0,_stringHelper.load_strings)({studyplan:{studyplan_select_placeholder:"studyplan_select_placeholder"}})}));
define("local_treestudyplan/page-view-plan",["exports","core/ajax","core/notification","./vue/vue","./util/debugger","./util/string-helper","./studyplan-processor","./util/date-helper","./report-viewer-components","./treestudyplan-components","./modedit-modal","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_ajax,_notification,_vue,_debugger,_stringHelper,_studyplanProcessor,_dateHelper,_reportViewerComponents,_treestudyplanComponents,_modeditModal,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(contextid,categoryid){contextid=void 0===contextid||!Number.isInteger(Number(contextid))||contextid<1?1:Number(contextid);categoryid=void 0!==categoryid&&Number.isInteger(Number(categoryid))?Number(categoryid):0;let app=new _vue.default({el:"#root",data:{displayedstudyplan:null,activestudyplan:null,associatedstudents:[],selectedstudent:null,studentstudyplan:null,loadingstudyplan:!1,studyplans:[],text:strings.studyplan,toolbox:{right:!0},usedcontexts:[]},async mounted(){(0,_ajax.call)([{methodname:"local_treestudyplan_list_studyplans",args:{context_id:contextid}}])[0].then((function(response){const timingval={present:0,past:1,future:2};response.sort(((a,b)=>{const timinga=(0,_dateHelper.studyplanTiming)(a),timingb=(0,_dateHelper.studyplanTiming)(b),t=timingval[timinga]-timingval[timingb];return 0==t?a.name.localeCompare(b.name):t})),app.studyplans=response;const parts=window.location.hash.replace("#","").split("-");if(parts&&parts.length>0)for(let idx in app.studyplans)if(app.studyplans[idx].id==parts[0]){app.selectStudyplan(app.studyplans[idx],parts[1]);break}})).catch(_notification.default.exception),(0,_ajax.call)([{methodname:"local_treestudyplan_list_used_categories",args:{operation:"view",refcontext_id:contextid}}])[0].then((function(response){const contexts=[];for(const ix in response)response[ix].studyplancount>0&&contexts.push(response[ix]);app.usedcontexts=contexts})).catch(_notification.default.exception)},computed:{dropdown_title(){return this.activestudyplan&&this.activestudyplan.name?this.activestudyplan.name:this.text.studyplan_select_placeholder},contextid:()=>contextid},methods:{switchContext(cat){const params=new URLSearchParams(location.search);params.delete("categoryid"),params.set("contextid",cat.context_id),window.location.search=params.toString()},closeStudyplan(){app.activestudyplan=null,app.associatedstudents=[],app.studentstudyplan=[],app.displayedstudyplan=null,window.location.hash=""},selectStudyplan(studyplan,studentid){app.loadingstudyplan=!0,app.activestudyplan=null,app.associatedstudents=[],app.selectedstudent=null,app.studentstudyplan=null,(0,_ajax.call)([{methodname:"local_treestudyplan_get_studyplan_map",args:{id:studyplan.id}}])[0].then((function(response){app.activestudyplan=(0,_studyplanProcessor.ProcessStudyplan)(response,!0),app.displayedstudyplan=app.activestudyplan,app.loadingstudyplan=!1,window.location.hash=app.activestudyplan.id,(0,_ajax.call)([{methodname:"local_treestudyplan_all_associated",args:{studyplan_id:studyplan.id}}])[0].then((function(response){if(app.associatedstudents=response,studentid)for(const student of app.associatedstudents)if(student.id==studentid){app.showStudentView(student);break}})).catch(_notification.default.exception)})).catch((function(error){_notification.default.exception(error),app.loadingstudyplan=!1}))},showStudentView(student){app.selectedstudent=student,app.studentstudyplan=null,app.loadingstudyplan=!0,(0,_ajax.call)([{methodname:"local_treestudyplan_get_user_studyplan",args:{userid:student.id,studyplanid:app.activestudyplan.id}}])[0].then((function(response){app.studentstudyplan=(0,_studyplanProcessor.ProcessStudyplan)(response,!1),app.displayedstudyplan=app.studentstudyplan,app.loadingstudyplan=!1,window.location.hash=app.activestudyplan.id+"-"+student.id})).catch((function(error){_notification.default.exception(error),app.loadingstudyplan=!1}))},showOverview(){app.selectedstudent=null,app.studentstudyplan=null,app.displayedstudyplan=app.activestudyplan,window.location.hash=app.activestudyplan.id}}})},_notification=_interopRequireDefault(_notification),_vue=_interopRequireDefault(_vue),_debugger=_interopRequireDefault(_debugger),_reportViewerComponents=_interopRequireDefault(_reportViewerComponents),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents),_modeditModal=_interopRequireDefault(_modeditModal),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_reportViewerComponents.default),_vue.default.use(_modeditModal.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);new _debugger.default("treestudyplanviewer");let strings=(0,_stringHelper.load_strings)({studyplan:{studyplan_select_placeholder:"studyplan_select_placeholder"}})}));
//# sourceMappingURL=page-view-plan.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -72,7 +72,7 @@ export default {
// notifyFormSubmittedByJavascript(form); // Moodle 4.00+ only
const formdata = new FormData(form);
const data =new URLSearchParams(formdata).toString();
const data = new URLSearchParams(formdata).toString();
//const formdata = new FormData(form);
//const data = {};
//formdata.forEach((value, key) => (data[key] = value));
@ -80,9 +80,9 @@ export default {
call([{
methodname: 'local_treestudyplan_submit_cm_editform',
args: {cmid: this.cmid, formdata: data}
}])[0].done(()=>{
}])[0].then(()=>{
self.$emit("saved",formdata);
}).fail(notification.exception);
}).catch(notification.exception);
}
},

View File

@ -198,7 +198,7 @@ export function init(contextid,categoryid,options) {
}).catch(notification.exception);
call([{
methodname: 'local_treestudyplan_list_used_categories',
args: { operation: 'edit'}
args: { operation: 'edit', refcontext_id: contextid}
}])[0].then(function(response){
app.usedcontexts = response;
}).catch(notification.exception);
@ -246,12 +246,12 @@ export function init(contextid,categoryid,options) {
call([{
methodname: 'local_treestudyplan_get_studyplan_map',
args: { id: studyplan.id}
}])[0].done(function(response){
}])[0].then(function(response){
app.activestudyplan = ProcessStudyplan(response);
debug.info('studyplan processed');
app.loadingstudyplan = false;
window.location.hash = app.activestudyplan.id;
}).fail(function(error){
}).catch(function(error){
notification.exception(error);
app.loadingstudyplan = false;
});
@ -270,14 +270,14 @@ export function init(contextid,categoryid,options) {
format: "application/json",
context_id: contextid,
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
self.initialize();
} else {
debug.error("Import failed: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
}, "application/json");
},
export_plan(plan,format){
@ -291,10 +291,10 @@ export function init(contextid,categoryid,options) {
studyplan_id: plan.id,
format: format
},
}])[0].done(function(response){
}])[0].then(function(response){
download(plan.shortname+".json",response.content,response.format);
}).fail(notification.exception);
}).catch(notification.exception);
},
toggletoolbox(event) {
debug.info(event);

View File

@ -5,27 +5,44 @@
// Put this file in path/to/plugin/amd/src
// You can call it anything you like
define(['jquery', 'core/str', 'core/ajax', 'core/modal_factory', 'core/modal_events',
'local_treestudyplan/handlers', 'local_treestudyplan/debugger'],
function ($, str, ajax, ModalFactory, ModalEvents,
handlers, Debugger) {
let debug = new Debugger("treestudyplan");
import Debugger from './util/debugger';
import {get_strings} from 'core/str';
import {getStrings} from 'core/str';
import ModalFactory from 'core/modal_factory';
import ModalEvents from 'core/modal_events';
let self = {
init: function init() {
$('.path-local-treestudyplan a.m-action-confirm').on('click', function (e) {
/* Determine the proper getstrings function to use (MDL4.3+ recommends use of getStrings, which is jquery independent) */
const getstr_func = (getStrings !== undefined)?getStrings:get_strings;
let debug = new Debugger("treestudyplan");
/**
* Init function for page-invitemanager
* @return undefined
*/
export function init() {
getstr_func([
{ key: 'ok', component: 'core'},
{ key: 'confirm', component: 'core'},
]).then((s) => {
const strOk = s[0];
const strConfirm = s[1];
const els = document.querySelectorAll('.path-local-treestudyplan a.m-action-confirm');
els.forEach((el) => {
el.addEventListener('click', (e) => {
e.preventDefault();
let $link = $(e.currentTarget);
let href = $link.attr('data-actionhref');
let text = $link.attr('data-confirmtext');
let oktext = $link.attr('data-confirmbtn');
debug.info("Ok", oktext);
if (undefined == oktext) { oktext = str.get_string('ok'); }
let title = $link.attr('data-confirmtitle');
debug.info("Title", title);
if (undefined == title) { title = str.get_string('confirm'); }
debug.info("Link, href, text", $link, href, text);
const link = e.currentTarget;
let href = link.getAttribute('data-actionhref');
let text = link.getAttribute('data-confirmtext');
let oktext = link.getAttribute('data-confirmbtn');
if (undefined == oktext) {
oktext = strOk;
}
let title = link.getAttribute('data-confirmtitle');
if (undefined == title) {
title = strConfirm;
}
ModalFactory.create({
type: ModalFactory.types.SAVE_CANCEL,
@ -38,14 +55,11 @@ function ($, str, ajax, ModalFactory, ModalEvents,
root.on(ModalEvents.save, function () {
window.location = href;
});
$(modal.modal).css("max-width", "345px");
modal.modal[0].style["max-width"] = "345px";
modal.show();
return modal;
});
});
},
};
return self;
});
});
});
}

View File

@ -70,7 +70,7 @@ export function init(contextid,categoryid) {
call([{
methodname: 'local_treestudyplan_list_studyplans',
args: {context_id: contextid}
}])[0].done(function(response){
}])[0].then(function(response){
const timingval = { present: 0, past: 1, future: 2};
response.sort((a,b) => {
const timinga = studyplanTiming(a);
@ -98,11 +98,11 @@ export function init(contextid,categoryid) {
}
}
}
}).fail(notification.exception);
}).catch(notification.exception);
call([{
methodname: 'local_treestudyplan_list_used_categories',
args: { operation: 'view'}
}])[0].done(function(response){
args: { operation: 'view', refcontext_id: contextid}
}])[0].then(function(response){
const contexts = [];
for(const ix in response){
if(response[ix].studyplancount >0){
@ -110,7 +110,7 @@ export function init(contextid,categoryid) {
}
}
app.usedcontexts = contexts;
}).fail(notification.exception);
}).catch(notification.exception);
},
computed: {
dropdown_title(){
@ -150,7 +150,7 @@ export function init(contextid,categoryid) {
call([{
methodname: 'local_treestudyplan_get_studyplan_map',
args: { id: studyplan.id}
}])[0].done(function(response){
}])[0].then(function(response){
app.activestudyplan = ProcessStudyplan(response,true);
app.displayedstudyplan = app.activestudyplan;
app.loadingstudyplan = false;
@ -158,7 +158,7 @@ export function init(contextid,categoryid) {
call([{
methodname: 'local_treestudyplan_all_associated',
args: { studyplan_id: studyplan.id}
}])[0].done(function(response){
}])[0].then(function(response){
app.associatedstudents = response;
if(studentid){
for(const student of app.associatedstudents){
@ -168,9 +168,9 @@ export function init(contextid,categoryid) {
}
}
}
}).fail(notification.exception);
}).catch(notification.exception);
}).fail(function(error){
}).catch(function(error){
notification.exception(error);
app.loadingstudyplan = false;
});
@ -182,12 +182,12 @@ export function init(contextid,categoryid) {
call([{
methodname: 'local_treestudyplan_get_user_studyplan',
args: { userid: student.id, studyplanid: app.activestudyplan.id}
}])[0].done(function(response){
}])[0].then(function(response){
app.studentstudyplan = ProcessStudyplan(response,false);
app.displayedstudyplan = app.studentstudyplan;
app.loadingstudyplan = false;
window.location.hash = app.activestudyplan.id + "-" + student.id;
}).fail(function(error){
}).catch(function(error){
notification.exception(error);
app.loadingstudyplan = false;
});

View File

@ -348,7 +348,7 @@ export default {
call([{
methodname: `local_treestudyplan_list_${this.verified_type}_studyplans`,
args: this.call_args(),
}])[0].done(function(response){
}])[0].then(function(response){
console.info("Loaded: plans",response);
const plans = { future: [], present: [], past: [], };
@ -385,7 +385,7 @@ export default {
}
}
}
}).fail(notification.exception);
}).catch(notification.exception);
},
selectStudyplan(plan) {
const self = this;
@ -395,10 +395,10 @@ export default {
args: this.call_args({
studyplanid: plan.id,
}),
}])[0].done(function(response){
}])[0].then(function(response){
self.selectedstudyplan = ProcessStudyplan(response);
self.loadingstudyplan = false;
}).fail(notification.exception);
}).catch(notification.exception);
},
deselectStudyplan() {
this.selectedstudyplan = null;
@ -2057,7 +2057,7 @@ export default {
'include': newValue,
'required': g.required,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
requiredChanged(newValue,g){
call([{
@ -2067,7 +2067,7 @@ export default {
'include': g.selected,
'required': newValue,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
},
template: `

View File

@ -314,9 +314,9 @@ export default {
studyplan_id: this.value.id,
scale_id: this.force_scales.selected_scale,
}
}])[0].done(function(response){
}])[0].then(function(response){
self.force_scales.result = response;
}).fail(notification.exception);
}).catch(notification.exception);
}
});
},
@ -331,10 +331,10 @@ export default {
page_id: this.selectedpage.id,
format: format,
},
}])[0].done(function(response){
}])[0].then(function(response){
download(self.value.shortname+".page."+format,response.content,response.format);
}).fail(notification.exception);
}).catch(notification.exception);
},
export_plan(){
const self = this;
@ -344,9 +344,9 @@ export default {
studyplan_id: this.value.id,
format: "json",
},
}])[0].done(function(response){
}])[0].then(function(response){
download(self.value.shortname+".plan.json",response.content,response.format);
}).fail(notification.exception);
}).catch(notification.exception);
},
bulk_course_timing() {
const self = this;
@ -355,7 +355,7 @@ export default {
args: {
page_id: this.selectedpage.id,
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
// Reloading the webpage saves trouble reloading the specific page updated.
location.reload();
@ -363,7 +363,7 @@ export default {
this.$bvModal.msgBoxOk(response.msg, {title: "Could not set bulk course timing"} );
debug.error("Could not set bulk course timing: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
},
import_studylines(){
//const self = this;
@ -375,14 +375,14 @@ export default {
content: content,
format: "application/json",
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
location.reload();
} else {
this.$bvModal.msgBoxOk(response.msg, {title: "Import failed"} );
debug.error("Import failed: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
}, "application/json");
},
import_pages(){
@ -395,14 +395,14 @@ export default {
content: content,
format: "application/json",
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
location.reload();
} else {
this.$bvModal.msgBoxOk(response.msg, {title: "Import failed"} );
debug.error("Import failed: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
}, "application/json");
},
purge_studyplan(){
@ -412,14 +412,14 @@ export default {
id: this.value.id,
force: true,
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
location.reload();
} else {
this.$bvModal.msgBoxOk(response.msg, {title: "Could not delete plan "} );
debug.error("Could not delete plan: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
},
purge_studyplanpage(){
if (this.selectedpage) {
@ -429,14 +429,14 @@ export default {
id: this.selectedpage.id,
force: true,
},
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success){
location.reload();
} else {
this.$bvModal.msgBoxOk(response.msg, {title: "Could not delete page"} );
debug.error("Could not delete page: ",response.msg);
}
}).fail(notification.exception);
}).catch(notification.exception);
}
},
cascade_cohortsync(){
@ -446,10 +446,10 @@ export default {
args: {
studyplan_id: this.value.id,
},
}])[0].done(function(response){
}])[0].then(function(response){
self.$bvModal.msgBoxOk(response.success?self.text.success$core:self.text.error$core,
{ title: self.text.advanced_cascade_cohortsync});
}).fail(notification.exception);
}).catch(notification.exception);
},
modal_close(){
this.force_scales.result = [];
@ -622,11 +622,11 @@ export default {
call([{
methodname: 'local_treestudyplan_get_studyplan_map',
args: { id: self.value.id}
}])[0].done(function(response){
}])[0].then(function(response){
self.value = ProcessStudyplan(response,true);
debug.info('studyplan processed');
self.$emit('input',self.value);
}).fail(function(error){
}).catch(function(error){
notification.exception(error);
});
} else {
@ -798,18 +798,18 @@ export default {
call([{
methodname: 'local_treestudyplan_associated_users',
args: { studyplan_id: self.value.id,}
}])[0].done(function(response){
}])[0].then(function(response){
self.association.users = response.map(self.userOptionModel);
self.loading.users = false;
}).fail(notification.exception);
}).catch(notification.exception);
call([{
methodname: 'local_treestudyplan_associated_cohorts',
args: { studyplan_id: self.value.id,}
}])[0].done(function(response){
}])[0].then(function(response){
self.association.cohorts = response.map(self.cohortOptionModel);
self.loading.cohorts = false;
}).fail(notification.exception);
}).catch(notification.exception);
},
searchCohorts(searchtext){
const self = this;
@ -819,9 +819,9 @@ export default {
call([{
methodname: 'local_treestudyplan_list_cohort',
args: { like: searchtext, exclude_id: self.value.id}
}])[0].done(function(response){
}])[0].then(function(response){
self.search.cohorts = response.map(self.cohortOptionModel);
}).fail(notification.exception);
}).catch(notification.exception);
}
else {
self.search.cohorts = [];
@ -876,9 +876,9 @@ export default {
call([{
methodname: 'local_treestudyplan_find_user',
args: { like: searchtext, exclude_id: self.value.id}
}])[0].done(function(response){
}])[0].then(function(response){
self.search.users = response.map(self.userOptionModel);
}).fail(notification.exception);
}).catch(notification.exception);
}
else {
self.search.users = [];
@ -1102,21 +1102,21 @@ export default {
call([{
methodname: 'local_treestudyplan_edit_period',
args: args
}])[0].done(function(response){
}])[0].then(function(response){
objCopy(self.value,response,PERIOD_EDITOR_FIELDS);
self.$emit('input',self.value);
self.$emit('edited',self.value);
}).fail(notification.exception);
}).catch(notification.exception);
},
refresh(){
const self = this;
call([{
methodname: 'local_treestudyplan_get_period',
args: { 'id': this.value.id },
}])[0].done(function(response){
}])[0].then(function(response){
objCopy(self.value,response,PERIOD_EDITOR_FIELDS);
self.$emit('input',self.value);
}).fail(notification.exception);
}).catch(notification.exception);
},
add_day(date,days) {
if( days === undefined ){
@ -1384,12 +1384,12 @@ export default {
'color': newlineinfo.color,
'sequence': page.studylines.length,
}
}])[0].done(function(response){
}])[0].then(function(response){
page.studylines.push(response);
newlineinfo.name = '';
newlineinfo.shortname = '';
newlineinfo.color = "#dddddd";
}).fail(notification.exception);
}).catch(notification.exception);
},
editLineStart(line) {
Object.assign(this.edit.studyline.data,line);
@ -1405,11 +1405,11 @@ export default {
'name': editedline.name,
'shortname': editedline.shortname,
'color': editedline.color,}
}])[0].done(function(response){
}])[0].then(function(response){
originalline['name'] = response['name'];
originalline['shortname'] = response['shortname'];
originalline['color'] = response['color'];
}).fail(notification.exception);
}).catch(notification.exception);
},
deleteLine(page,line) {
const self=this;
@ -1425,12 +1425,12 @@ export default {
call([{
methodname: 'local_treestudyplan_delete_studyline',
args: { 'id': line.id, }
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success == true){
let index = page.studylines.indexOf(line);
page.studylines.splice(index, 1);
}
}).fail(notification.exception);
}).catch(notification.exception);
}
});
});
@ -1448,8 +1448,8 @@ export default {
call([{
methodname: 'local_treestudyplan_reorder_studylines',
args: { 'sequence': sequence }
}])[0].done(function(response){
}).fail(notification.exception);
}])[0].then(function(response){
}).catch(notification.exception);
},
deletePlan(studyplan){
const self=this;
@ -1465,11 +1465,11 @@ export default {
call([{
methodname: 'local_treestudyplan_delete_studyplan',
args: { 'id': studyplan.id, force: true}
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success == true){
self.$root.$emit("studyplanRemoved",studyplan);
}
}).fail(notification.exception);
}).catch(notification.exception);
}
});
});
@ -1480,11 +1480,11 @@ export default {
call([{
methodname: 'local_treestudyplan_delete_studyitem',
args: { 'id': item.id, }
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success == true){
event.source.$emit('cut',event);
}
}).fail(notification.exception);
}).catch(notification.exception);
},
showslot(page,line,index, layeridx, type){
@ -2116,7 +2116,7 @@ export default {
'continuation_id':null,
}
}
}])[0].done((response) => {
}])[0].then((response) => {
let item = response;
self.relocateStudyItem(item).done(()=>{
self.value.push(item);
@ -2131,7 +2131,7 @@ export default {
});
ItemEventBus.$emit('coursechange');
});
}).fail(notification.exception);
}).catch(notification.exception);
}
else if(event.type.type == "filter") {
debug.info("Adding new filter compenent");
@ -2145,14 +2145,14 @@ export default {
"badge_id": event.data.badge?event.data.badge.id:undefined,
}
}
}])[0].done((response) => {
}])[0].then((response) => {
let item = response;
self.relocateStudyItem(item).done(()=>{
item.layer = this.layer;
self.value.push(item);
self.$emit("input",self.value);
});
}).fail(notification.exception);
}).catch(notification.exception);
}
}
},
@ -2174,7 +2174,7 @@ export default {
return call([{
methodname: 'local_treestudyplan_reorder_studyitems',
args: { 'items': [iteminfo] } // function was designed to relocate multiple items at once, hence the array
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
onDragEnter(event){
this.hover.component = event.data;
@ -2406,7 +2406,7 @@ export default {
course_id: this.value.course.id,
span: this.value.span,
}
}])[0].fail(notification.exception).done((response) => {
}])[0].catch(notification.exception).done((response) => {
self.value.course.startdate = response.startdate;
self.value.course.enddate = response.enddate;
self.value.course.timing = response.timing;
@ -2420,7 +2420,7 @@ export default {
args: { id: self.value.id,
span: span
}
}])[0].fail(notification.exception).done((response) => {
}])[0].catch(notification.exception).done((response) => {
self.value.span = response.span;
self.$emit('input',self.value);
self.$nextTick(() => {
@ -2637,11 +2637,11 @@ export default {
call([{
methodname: 'local_treestudyplan_connect_studyitems',
args: { 'from_id': from_id, 'to_id': to_id }
}])[0].done((response)=>{
}])[0].then((response)=>{
let conn = {'id': response.id, 'from_id': response.from_id, 'to_id': response.to_id};
ItemEventBus.$emit("createdConnection",conn);
this.value.connections.in.push(conn);
}).fail(notification.exception);
}).catch(notification.exception);
},
redrawLine(conn){
const lineColor = "var(--success)";
@ -2670,7 +2670,7 @@ export default {
call([{
methodname: 'local_treestudyplan_disconnect_studyitems',
args: { 'from_id': conn.from_id, 'to_id': conn.to_id }
}])[0].done((response)=>{
}])[0].then((response)=>{
if(response.success){
this.removeLine(conn);
// send disconnect event on message bus, so the connection on the other end can delete it too
@ -2679,7 +2679,7 @@ export default {
let index = self.value.connections.out.indexOf(conn);
self.value.connections.out.splice(index, 1);
}
}).fail(notification.exception);
}).catch(notification.exception);
},
highlight(conn){
if(this.lines[conn.to_id]){
@ -2697,7 +2697,7 @@ export default {
args: { 'id': this.value.id,
'conditions': this.value.conditions,
'continuation_id': this.value.continuation_id,}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
doShowContext(event) {
if(this.hasContext){
@ -2802,11 +2802,11 @@ export default {
call([{
methodname: 'local_treestudyplan_delete_studyitem',
args: { 'id': self.value.id, }
}])[0].done(function(response){
}])[0].then(function(response){
if(response.success == true){
self.$emit("deleted",{ data: self.value });
}
}).fail(notification.exception);
}).catch(notification.exception);
}
}).catch(err => {
debug.console.error(err);
@ -3125,7 +3125,7 @@ export default {
'include': newValue,
'required': g.required,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
requiredChanged(newValue,g){
call([{
@ -3135,7 +3135,7 @@ export default {
'include': g.selected,
'required': newValue,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
updateConditions() {
call([{
@ -3143,7 +3143,7 @@ export default {
args: { 'id': this.value.id,
'conditions': this.value.conditions,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
},
created() {
@ -3290,7 +3290,7 @@ export default {
'include': newValue,
'required': g.required,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
requiredChanged(newValue,g){
call([{
@ -3300,7 +3300,7 @@ export default {
'include': g.selected,
'required': newValue,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
},
created() {
@ -3497,7 +3497,7 @@ export default {
'item_id': this.item.id,
'required': newValue,
}
}])[0].fail(notification.exception);
}])[0].catch(notification.exception);
},
},
template: `
@ -3759,9 +3759,9 @@ export default {
call([{
methodname: 'local_treestudyplan_get_category',
args: { "id": this.value.id}
}])[0].done(function(response){
}])[0].then(function(response){
self.$emit('input', response);
}).fail(notification.exception);
}).catch(notification.exception);
}
}
},

View File

@ -200,7 +200,8 @@ class courseservice extends \external_api {
}
/**
* [Description for list_accessible_categories]
* List all categories the user has access to
* Used in the studyplan edit form
* @param string $operation
* @return array
*/
@ -280,6 +281,7 @@ class courseservice extends \external_api {
public static function list_used_categories_parameters() : \external_function_parameters {
return new \external_function_parameters( [
"operation" => new \external_value(PARAM_TEXT, 'type of operation ["view"|"edit"]', VALUE_DEFAULT),
"refcontext_id" => new \external_value(PARAM_INT, 'id of reference context', VALUE_DEFAULT),
]);
}
@ -293,33 +295,84 @@ class courseservice extends \external_api {
/**
* List all categories available to the current user for editing or viewing studyplans
* @param string $operation The operation to scan usage for [edit, view]
* @param int $refctxid Reference context id
* @return array
*/
public static function list_used_categories($operation = 'edit') {
public static function list_used_categories($operation = 'edit', $refctxid = 0) {
global $DB;
if ($operation == "edit") {
$capability = self::CAP_EDIT;
} else { // Operation == "view" || default.
$capability = self::CAP_VIEW;
}
$contextcounts = [];
$contextids = [];
$rs = $DB->get_recordset_sql("SELECT DISTINCT context_id, COUNT(*) as num FROM {local_treestudyplan}
GROUP BY context_id");
foreach ($rs as $r) {
$contextids[$r->context_id] = $r->num;
$contextcounts[$r->context_id] = $r->num;
$contextids[] = $r->context_id;
}
$rs->close();
// Now filter the categories that the user has acces to by the used context id's.
// (That should filter out irrelevant stuff).
$cats = static::categories_by_capability($capability);
$cats = [];
// If the reference context id is not in the list, push it there
if ($refctxid > 1 && !in_array($refctxid, $contextids)) {
try {
$refctx = \context::instance_by_id($refctxid);
$refpath = $refctx->get_parent_context_ids(true);
$found = false;
foreach ($refpath as $i => $pid) {
$idx = array_search($pid,$contextids);
if($idx !== false) {
$contextids = array_merge(
array_slice($contextids, 0, $idx+1),
array_reverse(array_slice($refpath,0,$i)),
array_slice($contextids, $idx+1, count($contextids) - 1)
) ;
$found = true;
break;
}
}
if(!$found) {
array_unshift($contextids,$refctxid);
}
} catch(\dml_missing_record_exception $x) {
// ignore context
}
}
// we only have to check the contexts having a study plan for access permissions
foreach ($contextids as $ctxid ) {
try {
$ctx = \context::instance_by_id($ctxid);
if (has_capability($capability, $ctx)) {
if ($ctx->contextlevel == CONTEXT_SYSTEM) {
$cat = \core_course_category::top();
} else if ($ctx->contextlevel == CONTEXT_COURSECAT) {
$cat = \core_course_category::get($ctx->instanceid);
}
$cats[] = $cat;
if ($operation == "edit" && $ctxid == $refctxid) {
// Include direct children for navigation purposes
foreach ($cat->get_children() as $ccat) {
$cats[] = $ccat;
}
}
}
} catch (\dml_missing_record_exception $x) {
// ignore context
}
}
$list = [];
foreach ($cats as $cat) {
$count = 0;
$ctxid = $cat->get_context()->id;
if (array_key_exists($ctxid, $contextids)) {
$count = $contextids[$ctxid];
if (array_key_exists($ctxid, $contextcounts)) {
$count = $contextcounts[$ctxid];
}
$o = static::map_category($cat, true);
@ -327,15 +380,17 @@ class courseservice extends \external_api {
$list[] = $o;
}
return $list;
}
/**
* List all categories available to the current user for editing or viewing studyplans and add information about their usage
* (Not a webservice function)
* @param string $operation
* @param int $refctxid Reference context id
* @return stdClass[]
*/
public static function list_accessible_categories_with_usage($operation = 'edit') {
public static function list_accessible_categories_with_usage($operation = 'edit', $refctxid = 0) {
global $DB;
if ($operation == "edit") {
$capability = self::CAP_EDIT;
@ -343,24 +398,74 @@ class courseservice extends \external_api {
$capability = self::CAP_VIEW;
}
// Retrieve context ids used.
$contextcounts = [];
$contextids = [];
$rs = $DB->get_recordset_sql("SELECT DISTINCT context_id, COUNT(*) as num FROM {local_treestudyplan}
GROUP BY context_id");
foreach ($rs as $r) {
$contextids[$r->context_id] = $r->num;
$contextcounts[$r->context_id] = $r->num;
$contextids[] = $r->context_id;
}
$rs->close();
// Now filter the categories that the user has acces to by the used context id's.
// (That should filter out irrelevant stuff).
$cats = static::categories_by_capability($capability);
$cats = [];
// If the reference context id is not in the list, push it there
if ($refctxid > 1 && !in_array($refctxid, $contextids)) {
try {
$refctx = \context::instance_by_id($refctxid);
$refpath = $refctx->get_parent_context_ids(true);
$found = false;
foreach ($refpath as $i => $pid) {
$idx = array_search($pid,$contextids);
if($idx !== false) {
$contextids = array_merge(
array_slice($contextids, 0, $idx+1),
array_reverse(array_slice($refpath,0,$i)),
array_slice($contextids, $idx+1, count($contextids) - 1)
) ;
$found = true;
break;
}
}
if(!$found) {
array_unshift($contextids,$refctxid);
}
} catch(\dml_missing_record_exception $x) {
// ignore context
}
}
// we only have to check these contexts for access permissions
foreach ($contextids as $ctxid ) {
try {
$ctx = \context::instance_by_id($ctxid);
if (has_capability($capability, $ctx)) {
if ($ctx->contextlevel == CONTEXT_SYSTEM) {
$cat = \core_course_category::top();
} else if ($ctx->contextlevel == CONTEXT_COURSECAT) {
$cat = \core_course_category::get($ctx->instanceid);
}
$cats[] = $cat;
if ($operation == "view" && $ctxid == $refctxid) {
// Include direct children for navigation purposes
foreach ($cat->get_children() as $ccat) {
$cats[] = $ccat;
}
}
}
} catch (\dml_missing_record_exception $x) {
// ignore context
}
}
$list = [];
foreach ($cats as $cat) {
$count = 0;
$ctxid = $cat->get_context()->id;
if (array_key_exists($ctxid, $contextids)) {
$count = $contextids[$ctxid];
if (array_key_exists($ctxid, $contextcounts)) {
$count = $contextcounts[$ctxid];
}
$o = new \stdClass();
$o->cat = $cat;

View File

@ -200,6 +200,8 @@ class studyplan {
/* The associated context cannot be found.
Probably the category was removed, but the studyplan was not.
Revert the studyplan back to the system context to avoid lost studyplans.
Note that the daily cleanup task calls this function to make sure
studyplans without a valid context are not lost.
*/
$this->context = \context_system::instance();
$this->r->context_id = $this->context->id;

62
classes/task/cleanup.php Normal file
View File

@ -0,0 +1,62 @@
<?php
// This file is part of the Studyplan plugin for Moodle
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* Background task to refresh the list of associaded teachers with studyplans
* @package local_treestudyplan
* @copyright 2023 P.M. Kuipers
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_treestudyplan\task;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot.'/course/externallib.php');
use local_treestudyplan\studyplan;
use local_treestudyplan\teachingfinder;
/**
* Background task to refresh the list of associaded teachers with studyplans
*/
class cleanup extends \core\task\scheduled_task {
/**
* Maximum time a result is valid before refreshing
* @var int
*/
const CACHE_TIME = 4 * 60 * 60; // 2 hours.
/**
* Return the task's name as shown in admin screens.
*
* @return string
*/
public function get_name() {
return get_string('cleanup_name', 'local_treestudyplan');
}
/**
* Execute the task.
*/
public function execute() {
\mtrace("Verify studyplan contexts exist");
$studyplans = studyplan::find_all();
foreach ($studyplans as $plan) {
// Context call automatically reverts studyplan to system context if the context cannot be found.
$plan->context();
}
}
}

View File

@ -40,5 +40,14 @@ $tasks = [
'month' => '*',
'dayofweek' => '*',
],
[
'classname' => 'local_treestudyplan\task\cleanup',
'blocking' => 0,
'minute' => 'R',
'hour' => 'R',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
],
];

View File

@ -82,7 +82,7 @@ $PAGE->requires->js_call_amd('local_treestudyplan/page-edit-plan', 'init', [$stu
"editMode" => $PAGE->user_is_editing()
]]);
$catlist = courseservice::list_accessible_categories_with_usage("edit");
$catlist = courseservice::list_accessible_categories_with_usage("edit", $studyplancontext->id);
/**
* Shortcut function to provide translations

View File

@ -41,7 +41,6 @@ $PAGE->set_heading(get_string('manage_invites', 'local_treestudyplan'));
// Load javascripts.
$PAGE->requires->js_call_amd('local_treestudyplan/page-invitemanager', 'init');
$PAGE->requires->js_call_amd('local_treestudyplan/buttonlinks', 'init');
// Retrieve list of courses that the student is enrolled in.
$sent = optional_param('sent', '', PARAM_INT);

View File

@ -131,6 +131,7 @@ for ($i=1;$i<=5;$i++) {
$string["autocohortsync_name"] = 'Study plan automatic cohort sync cascading';
$string["refreshteacherlist_name"] = "Refresh teacher's study plan list";
$string["cleanup_name"] = "Regular maintenance tasks for study plans";
$string["no_form_data"] = "The provided information was incorrect. Likely you uploaded an icon in an unsupported format. Please check your input data and try again.";

View File

@ -131,6 +131,7 @@ for ($i=1;$i<=5;$i++) {
$string["autocohortsync_name"] = 'Studyplan automatisch site-group synchronisatie doorzetten';
$string["refreshteacherlist_name"] = "Ververs lijst van studieplannen voor leraar";
$string["cleanup_name"] = "Dagelijkse onderhoudtaak voor studieplannen";
$string["no_form_data"] = "Er is iets misgegaan met de ingevoerde gegevens. Waarschijnlijk heb je een afbeelding ingevoegd in een formaat dat niet ondersteund wordt. Controleer je gegevens en probeer het opnieuw.";

View File

@ -22,7 +22,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
$plugin->version = 2023121304; // YYYYMMDDHH (year, month, day, iteration).
$plugin->version = 2023121306; // YYYYMMDDHH (year, month, day, iteration).
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
$plugin->release = "1.1.0";