From a717acf4e482e161438ac7428e9ac49330c45e65 Mon Sep 17 00:00:00 2001 From: PMKuipers Date: Fri, 9 Feb 2024 14:48:15 +0100 Subject: [PATCH] Added foundation for overview report --- amd/build/page-studyplan-report.min.js | 3 + amd/build/page-studyplan-report.min.js.map | 1 + amd/build/page-view-plan copy.min.js | 3 + amd/build/page-view-plan copy.min.js.map | 1 + amd/src/page-studyplan-report.js | 65 +++++++++++ classes/reportservice.php | 125 +++++++++++++++++++++ db/services.php | 36 ++++++ studyplan-report.php | 90 +++++++++++++++ version.php | 2 +- 9 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 amd/build/page-studyplan-report.min.js create mode 100644 amd/build/page-studyplan-report.min.js.map create mode 100644 amd/build/page-view-plan copy.min.js create mode 100644 amd/build/page-view-plan copy.min.js.map create mode 100644 amd/src/page-studyplan-report.js create mode 100644 classes/reportservice.php create mode 100644 studyplan-report.php diff --git a/amd/build/page-studyplan-report.min.js b/amd/build/page-studyplan-report.min.js new file mode 100644 index 0000000..3dc977b --- /dev/null +++ b/amd/build/page-studyplan-report.min.js @@ -0,0 +1,3 @@ +define("local_treestudyplan/page-studyplan-report",["exports","core/ajax","core/notification","./vue/vue","./util/debugger","./util/string-helper","./studyplan-processor","./util/date-helper","./treestudyplan-components","./modedit-modal","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_ajax,_notification,_vue,_debugger,_stringHelper,_studyplanProcessor,_dateHelper,_treestudyplanComponents,_modeditModal,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(studyplanid,period){studyplanid=void 0!==studyplanid&&Number.isInteger(Number(studyplanid))?Number(studyplanid):0;new _vue.default({el:"#root",data:{},async mounted(){},computed:{},methods:{}})},_notification=_interopRequireDefault(_notification),_vue=_interopRequireDefault(_vue),_debugger=_interopRequireDefault(_debugger),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents),_modeditModal=_interopRequireDefault(_modeditModal),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_modeditModal.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);new _debugger.default("treestudyplanviewer"),(0,_stringHelper.load_strings)({studyplan:{studyplan_select_placeholder:"studyplan_select_placeholder"}})})); + +//# sourceMappingURL=page-studyplan-report.min.js.map \ No newline at end of file diff --git a/amd/build/page-studyplan-report.min.js.map b/amd/build/page-studyplan-report.min.js.map new file mode 100644 index 0000000..8e33fcd --- /dev/null +++ b/amd/build/page-studyplan-report.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"page-studyplan-report.min.js","sources":["../src/page-studyplan-report.js"],"sourcesContent":["/*eslint no-var: \"error\" */\n/*eslint no-unused-vars: \"off\" */\n/*eslint linebreak-style: \"off\" */\n/*eslint no-trailing-spaces: \"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 {call} from 'core/ajax';\nimport notification from 'core/notification';\n\nimport Vue from './vue/vue';\n\nimport Debugger from './util/debugger';\nimport {load_strings} from './util/string-helper';\nimport {ProcessStudyplan} from './studyplan-processor';\nimport {studyplanTiming} from './util/date-helper';\n\nimport TSComponents from './treestudyplan-components';\nimport ModalComponents from './modedit-modal';\nVue.use(ModalComponents);\n\nimport PortalVue from './portal-vue/portal-vue.esm';\nVue.use(PortalVue);\nimport BootstrapVue from './bootstrap-vue/bootstrap-vue';\nVue.use(BootstrapVue);\n\n\nlet debug = new Debugger(\"treestudyplanviewer\");\n\nlet strings = load_strings({\n studyplan: {\n studyplan_select_placeholder: 'studyplan_select_placeholder',\n },\n});\n\n/**\n * Initialize the Page\n * @param {Number} studyplanid The id of the studyplan we need to view \n * @param {Number} period The id of the studyplan we need to view \n */\nexport function init(studyplanid,period) {\n // Make sure the id's are numeric and integer\n if (undefined === studyplanid || !Number.isInteger(Number(studyplanid)) ){ \n studyplanid = 0;\n } else {\n studyplanid = Number(studyplanid);\n } // ensure a numeric value instead of string.\n\n const app = new Vue({\n el: '#root',\n data: {\n\n },\n async mounted() {\n \n },\n computed: {\n \n },\n methods: {\n \n },\n });\n}\n"],"names":["studyplanid","period","undefined","Number","isInteger","Vue","el","data","computed","methods","use","ModalComponents","PortalVue","BootstrapVue","Debugger","studyplan","studyplan_select_placeholder"],"mappings":"onBAyCqBA,YAAYC,QAKzBD,iBAHAE,IAAcF,aAAgBG,OAAOC,UAAUD,OAAOH,cAGxCG,OAAOH,aAFP,EAKN,IAAIK,aAAI,CAChBC,GAAI,QACJC,KAAM,qBAMNC,SAAU,GAGVC,QAAS,qXAxCbC,IAAIC,oCAGJD,IAAIE,iCAEJF,IAAIG,uBAGI,IAAIC,kBAAS,wBAEX,8BAAa,CACvBC,UAAW,CACPC,6BAA8B"} \ No newline at end of file diff --git a/amd/build/page-view-plan copy.min.js b/amd/build/page-view-plan copy.min.js new file mode 100644 index 0000000..8c180a1 --- /dev/null +++ b/amd/build/page-view-plan copy.min.js @@ -0,0 +1,3 @@ +define("local_treestudyplan/page-view-plan copy",["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_available_categories",args:{operation:"view",refcontext_id:contextid}}])[0].then((function(response){const contexts=[];for(const ix in response){const cat=response[ix];(cat.studyplancount>0||cat.context_id==contextid)&&contexts.push(cat)}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(ctxid){const params=new URLSearchParams(location.search);params.delete("categoryid"),params.set("contextid",ctxid),setTimeout((()=>{window.location.href=window.location.pathname+"?"+params.toString()}),50)},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_grouped",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,student&&(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 copy.min.js.map \ No newline at end of file diff --git a/amd/build/page-view-plan copy.min.js.map b/amd/build/page-view-plan copy.min.js.map new file mode 100644 index 0000000..35c700c --- /dev/null +++ b/amd/build/page-view-plan copy.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"page-view-plan copy.min.js","sources":["../src/page-view-plan copy.js"],"sourcesContent":["/*eslint no-var: \"error\" */\n/*eslint no-unused-vars: \"off\" */\n/*eslint linebreak-style: \"off\" */\n/*eslint no-trailing-spaces: \"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 {call} from 'core/ajax';\nimport notification from 'core/notification';\n\nimport Vue from './vue/vue';\n\nimport Debugger from './util/debugger';\nimport {load_strings} from './util/string-helper';\nimport {ProcessStudyplan} from './studyplan-processor';\nimport {studyplanTiming} from './util/date-helper';\n\nimport RVComponents from './report-viewer-components';\nVue.use(RVComponents);\nimport TSComponents from './treestudyplan-components';\nimport ModalComponents from './modedit-modal';\nVue.use(ModalComponents);\n\nimport PortalVue from './portal-vue/portal-vue.esm';\nVue.use(PortalVue);\nimport BootstrapVue from './bootstrap-vue/bootstrap-vue';\nVue.use(BootstrapVue);\n\n\nlet debug = new Debugger(\"treestudyplanviewer\");\n\nlet strings = load_strings({\n studyplan: {\n studyplan_select_placeholder: 'studyplan_select_placeholder',\n },\n});\n\n/**\n * Initialize the Page\n * @param {int} contextid The context we should attempt to work in (1:1 related to the category)\n * @param {int} categoryid The category we shoud attempt to work in (1:1 related to the context)\n */\nexport function init(contextid,categoryid) {\n // Make sure the id's are numeric and integer\n if(undefined === contextid || !Number.isInteger(Number(contextid)) || contextid < 1 ){ contextid = 1;}\n else { contextid = Number(contextid);} // ensure a numeric value instead of string\n if(undefined === categoryid || !Number.isInteger(Number(categoryid))){ categoryid = 0;}\n else { categoryid = Number(categoryid);} // ensure a numeric value instead of string\n\n const in_systemcontext = (contextid <= 1);\n\n let app = new Vue({\n el: '#root',\n data: {\n displayedstudyplan: null,\n activestudyplan: null,\n associatedstudents: [],\n selectedstudent: null,\n studentstudyplan: null,\n loadingstudyplan: false,\n studyplans: [],\n text: strings.studyplan,\n toolbox: {\n right: true,\n },\n usedcontexts: [],\n },\n async mounted() {\n call([{\n methodname: 'local_treestudyplan_list_studyplans',\n args: {context_id: contextid}\n }])[0].then(function(response){\n const timingval = { present: 0, past: 1, future: 2};\n response.sort((a,b) => {\n const timinga = studyplanTiming(a);\n const timingb = studyplanTiming(b);\n\n const t = timingval[timinga] - timingval[timingb];\n if(t == 0){\n // sort by name if timing is equal\n return a.name.localeCompare(b.name);\n }\n else {\n return t;\n }\n });\n app.studyplans = response;\n // load studyplan from hash if applicable\n const hash = window.location.hash.replace('#','');\n const parts = hash.split(\"-\");\n\n if(!!parts && parts.length > 0){\n for(let idx in app.studyplans){\n if(app.studyplans[idx].id == parts[0]){\n app.selectStudyplan(app.studyplans[idx],parts[1]);\n break;\n }\n }\n }\n }).catch(notification.exception);\n call([{\n methodname: 'local_treestudyplan_list_available_categories',\n args: { operation: 'view', refcontext_id: contextid}\n }])[0].then(function(response){\n const contexts = [];\n for(const ix in response){\n const cat = response[ix];\n if(cat.studyplancount > 0 || cat.context_id == contextid){\n contexts.push(cat);\n }\n }\n app.usedcontexts = contexts;\n }).catch(notification.exception);\n },\n computed: {\n dropdown_title(){\n if(this.activestudyplan && this.activestudyplan.name){\n return this.activestudyplan.name;\n }\n else{\n return this.text.studyplan_select_placeholder;\n }\n },\n contextid(){\n return contextid;\n }\n },\n methods: {\n switchContext(ctxid){\n const params = new URLSearchParams(location.search);\n params.delete('categoryid');\n params.set('contextid', ctxid);\n setTimeout(() => {\n // Reload page in a timeout to give other form javasccript the change to remove the beforeunload handler.\n window.location.href = window.location.pathname + \"?\" + params.toString();\n },50);\n },\n closeStudyplan() {\n app.activestudyplan = null;\n app.associatedstudents = [];\n app.studentstudyplan = [];\n app.displayedstudyplan = null;\n window.location.hash = '';\n },\n\n selectStudyplan(studyplan,studentid){\n // fetch studyplan\n app.loadingstudyplan = true;\n app.activestudyplan = null;\n app.associatedstudents = [];\n app.selectedstudent = null;\n app.studentstudyplan = null;\n call([{\n methodname: 'local_treestudyplan_get_studyplan_map',\n args: { id: studyplan.id}\n }])[0].then(function(response){\n app.activestudyplan = ProcessStudyplan(response,true);\n app.displayedstudyplan = app.activestudyplan;\n app.loadingstudyplan = false;\n window.location.hash = app.activestudyplan.id;\n call([{\n methodname: 'local_treestudyplan_all_associated_grouped',\n args: { studyplan_id: studyplan.id}\n }])[0].then(function(response){\n app.associatedstudents = response;\n if(studentid){\n for(const student of app.associatedstudents){\n if(student.id == studentid){\n app.showStudentView(student);\n break;\n }\n }\n }\n }).catch(notification.exception);\n\n }).catch(function(error){\n notification.exception(error);\n app.loadingstudyplan = false;\n });\n },\n showStudentView(student){\n app.selectedstudent = student;\n app.studentstudyplan = null;\n if (student) {\n app.loadingstudyplan = true;\n call([{\n methodname: 'local_treestudyplan_get_user_studyplan',\n args: { userid: student.id, studyplanid: app.activestudyplan.id}\n }])[0].then(function(response){\n app.studentstudyplan = ProcessStudyplan(response,false);\n app.displayedstudyplan = app.studentstudyplan;\n app.loadingstudyplan = false;\n window.location.hash = app.activestudyplan.id + \"-\" + student.id;\n }).catch(function(error){\n notification.exception(error);\n app.loadingstudyplan = false;\n });\n }\n\n },\n showOverview(){\n app.selectedstudent = null;\n app.studentstudyplan = null;\n app.displayedstudyplan = app.activestudyplan;\n window.location.hash = app.activestudyplan.id;\n }\n\n },\n });\n}\n"],"names":["contextid","categoryid","undefined","Number","isInteger","app","Vue","el","data","displayedstudyplan","activestudyplan","associatedstudents","selectedstudent","studentstudyplan","loadingstudyplan","studyplans","text","strings","studyplan","toolbox","right","usedcontexts","methodname","args","context_id","then","response","timingval","present","past","future","sort","a","b","timinga","timingb","t","name","localeCompare","parts","window","location","hash","replace","split","length","idx","id","selectStudyplan","catch","notification","exception","operation","refcontext_id","contexts","ix","cat","studyplancount","push","computed","dropdown_title","this","studyplan_select_placeholder","methods","switchContext","ctxid","params","URLSearchParams","search","delete","set","setTimeout","href","pathname","toString","closeStudyplan","studentid","studyplan_id","student","showStudentView","error","userid","studyplanid","showOverview","use","RVComponents","ModalComponents","PortalVue","BootstrapVue","Debugger"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/page-studyplan-report.js b/amd/src/page-studyplan-report.js new file mode 100644 index 0000000..6901584 --- /dev/null +++ b/amd/src/page-studyplan-report.js @@ -0,0 +1,65 @@ +/*eslint no-var: "error" */ +/*eslint no-unused-vars: "off" */ +/*eslint linebreak-style: "off" */ +/*eslint no-trailing-spaces: "off" */ +/*eslint-env es6*/ +// Put this file in path/to/plugin/amd/src +// You can call it anything you like + +import {call} from 'core/ajax'; +import notification from 'core/notification'; + +import Vue from './vue/vue'; + +import Debugger from './util/debugger'; +import {load_strings} from './util/string-helper'; +import {ProcessStudyplan} from './studyplan-processor'; +import {studyplanTiming} from './util/date-helper'; + +import TSComponents from './treestudyplan-components'; +import ModalComponents from './modedit-modal'; +Vue.use(ModalComponents); + +import PortalVue from './portal-vue/portal-vue.esm'; +Vue.use(PortalVue); +import BootstrapVue from './bootstrap-vue/bootstrap-vue'; +Vue.use(BootstrapVue); + + +let debug = new Debugger("treestudyplanviewer"); + +let strings = load_strings({ + studyplan: { + studyplan_select_placeholder: 'studyplan_select_placeholder', + }, +}); + +/** + * Initialize the Page + * @param {Number} studyplanid The id of the studyplan we need to view + * @param {Number} period The id of the studyplan we need to view + */ +export function init(studyplanid,period) { + // Make sure the id's are numeric and integer + if (undefined === studyplanid || !Number.isInteger(Number(studyplanid)) ){ + studyplanid = 0; + } else { + studyplanid = Number(studyplanid); + } // ensure a numeric value instead of string. + + const app = new Vue({ + el: '#root', + data: { + + }, + async mounted() { + + }, + computed: { + + }, + methods: { + + }, + }); +} diff --git a/classes/reportservice.php b/classes/reportservice.php new file mode 100644 index 0000000..515ee16 --- /dev/null +++ b/classes/reportservice.php @@ -0,0 +1,125 @@ +. +/** + * Webservice class for handling studyplan reports + * @package local_treestudyplan + * @copyright 2023 P.M. Kuipers + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_treestudyplan; +defined('MOODLE_INTERNAL') || die(); + +use local_treestudyplan\local\helpers\webservicehelper; + +require_once($CFG->libdir.'/externallib.php'); + +/** + * Webservice class for handling studyplan reports + */ +class reportservice extends \external_api { + /** + * Capability required to view studyplans (for other users) + * @var string + */ + const CAP_VIEW = "local/treestudyplan:viewuserreports"; + + + public static function get_report_structure_parameters() : \external_function_parameters { + return new \external_function_parameters([ + "pageid" => new \external_value(PARAM_INT, 'id of studyplan page'), + "firstperiod" => new \external_value(PARAM_INT, 'first period to include in report',VALUE_DEFAULT), + "lastperiod" => new \external_value(PARAM_INT, 'last perioe to include in report',VALUE_DEFAULT), + ]); + } + + /** + * Return value description for webservice function list_user_studyplans + */ + public static function get_report_structure_returns() : \external_description { + return new \external_single_structure([ + ]); + } + + /** + * Get studyplan page structure for a report + * @param int $pageid ID of user to check specific info for + * @param int|null $firstperiod First period to include in report + * @param int|null $lastperiod Last period to include in report + * @return object + */ + public static function get_report_structure($pageid,$firstperiod=null,$lastperiod=null) { + + } + + public static function get_report_data_parameters() : \external_function_parameters { + return new \external_function_parameters([ + "pageid" => new \external_value(PARAM_INT, 'id of studyplan page'), + "userid" => new \external_value(PARAM_INT, 'id of user'), + "firstperiod" => new \external_value(PARAM_INT, 'first period to include in report',VALUE_DEFAULT), + "lastperiod" => new \external_value(PARAM_INT, 'last period to include in report',VALUE_DEFAULT), + + ]); + } + + /** + * Return value description for webservice function list_user_studyplans + */ + public static function get_report_data_returns() : \external_description { + return new \external_single_structure([ + ]); + } + + /** + * Get studyplan page structure for a report + * @param int $pageid ID of user to check specific info for + * @param int $userid ID of user to check specific info for + * @param int|null $firstperiod First period to include in report + * @param int|null $lastperiod Last period to include in report + * @return object + */ + public static function get_report_data($pageid,$userid,$firstperiod=null,$lastperiod=null) { + + } + + public static function get_report_details_parameters() : \external_function_parameters { + return new \external_function_parameters([ + "itemid" => new \external_value(PARAM_INT, 'id of studyitem'), + "userid" => new \external_value(PARAM_INT, 'id of user'), + ]); + } + + /** + * Return value description for webservice function list_user_studyplans + */ + public static function get_report_details_returns() : \external_description { + return new \external_single_structure([ + ]); + } + + /** + * Get study item details for a user + * @param int $itemid ID of study item + * @param int $userid ID of user to check specific info for + * @return array + */ + public static function get_report_details($itemid,$userid) { + + } + + + +} diff --git a/db/services.php b/db/services.php index 40c32d4..37a086e 100644 --- a/db/services.php +++ b/db/services.php @@ -314,6 +314,9 @@ $functions = [ 'capabilities' => 'local/treestudyplan:editstudyplan', 'loginrequired' => true, ], + /*************************** + * Category mapping + ***************************/ 'local_treestudyplan_map_categories' => [ // Web service function name. 'classname' => '\local_treestudyplan\courseservice', // Class containing the external function. 'methodname' => 'map_categories', // External function name. @@ -368,6 +371,9 @@ $functions = [ 'capabilities' => 'local/treestudyplan:viewuserreports', 'loginrequired' => true, ], + /*************************** + * Studyplan functions + ***************************/ 'local_treestudyplan_list_aggregators' => [ // Web service function name. 'classname' => '\local_treestudyplan\studyplanservice', // Class containing the external function. 'methodname' => 'list_aggregators', // External function name. @@ -674,4 +680,34 @@ $functions = [ 'capabilities' => '', 'loginrequired' => true, ], + /*************************** + * Studyplan report functions + ***************************/ + 'local_treestudyplan_get_report_structure' => [ // Web service function name. + 'classname' => '\local_treestudyplan\reportservice', // Class containing the external function. + 'methodname' => 'get_report_structure', // External function name. + 'description' => 'Retrieve studyplan report structure', + 'type' => 'read', // Database rights of the web service function (read, write). + 'ajax' => true, + 'capabilities' => 'local/treestudyplan:viewuserreports', + 'loginrequired' => true, + ], + 'local_treestudyplan_get_report_data' => [ // Web service function name. + 'classname' => '\local_treestudyplan\reportservice', // Class containing the external function. + 'methodname' => 'get_report_data', // External function name. + 'description' => 'Retrieve studyplan report data for student ', + 'type' => 'read', // Database rights of the web service function (read, write). + 'ajax' => true, + 'capabilities' => 'local/treestudyplan:viewuserreports', + 'loginrequired' => true, + ], + 'local_treestudyplan_get_report_details' => [ // Web service function name. + 'classname' => '\local_treestudyplan\reportservice', // Class containing the external function. + 'methodname' => 'get_report_details', // External function name. + 'description' => 'Retrieve studyplan report details for student ', + 'type' => 'read', // Database rights of the web service function (read, write). + 'ajax' => true, + 'capabilities' => 'local/treestudyplan:viewuserreports', + 'loginrequired' => true, + ], ]; diff --git a/studyplan-report.php b/studyplan-report.php new file mode 100644 index 0000000..d3de46d --- /dev/null +++ b/studyplan-report.php @@ -0,0 +1,90 @@ +. +/** + * Report + * @package local_treestudyplan + * @copyright 2023 P.M. Kuipers + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once("../../config.php"); + +use local_treestudyplan\contextinfo; +use \local_treestudyplan\courseservice; +use \local_treestudyplan\studyplan; +use \local_treestudyplan\studyplanpage; + +require_once($CFG->libdir.'/weblib.php'); + +$PAGE->set_url("/local/treestudyplan/studyplan-report.php", array()); +require_login(); + +// Figure out the context (category or system, based on either category or context parameter). +$pageid = required_param('page', 0, PARAM_INT); // Category id. +$page = studyplanpage::find_by_id($pageid); +$studyplan = $page->studyplan(); +$context = $studyplan->context(); +$contexname = (new contextinfo($studyplancontext))->pathstr(); + +$firstperiod = optional_param('firstperiod', 0, PARAM_INT); // First period to show +$lastperiod = optional_param('lastperiod', 0, PARAM_INT); // Last periode to show + + + +$PAGE->set_pagelayout('base'); +//$PAGE->set_context($studyplancontext); +$PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan')." - ".$contextname); +$PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan')." - ".$contextname); + +if(!has_capability('local/treestudyplan:viewuserreports', $studyplancontext)) { + throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","",$contextname); +} + +// Load javascripts and specific css. +$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/bootstrap-vue/bootstrap-vue.css')); +if ($CFG->debugdeveloper) { + $PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css')); +} +$PAGE->requires->js_call_amd('local_treestudyplan/page-studyplan-report', 'init', [$studyplan->id(), $page->id(), $firstperiod, $lastperiod]); + + +/** + * Shortcut function to provide translations + * + * @param mixed $str Translation key + * @param null|string[] $param Parameters to pass to translation + * @param string $plugin Location to search for translation strings + * @return string Translation of key + */ +function t($str, $param = null, $plugin = 'local_treestudyplan') { + print get_string($str, $plugin, $param); +} + +print $OUTPUT->header(); +?> +
+
+
+ Loading... +
+
+
+ +
+
+footer(); diff --git a/version.php b/version.php index c081e1c..bb94b9d 100644 --- a/version.php +++ b/version.php @@ -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 = 2024020702; // YYYYMMDDHH (year, month, day, iteration). +$plugin->version = 2024020900; // YYYYMMDDHH (year, month, day, iteration). $plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11). $plugin->release = "1.1.0";