Implemented backend for studyplan-reports and start of frontend
This commit is contained in:
parent
0e4cf45a80
commit
9f69b7bc15
2
amd/build/page-studyplan-report.min.js
vendored
2
amd/build/page-studyplan-report.min.js
vendored
|
@ -1,3 +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"}})}));
|
||||
define("local_treestudyplan/page-studyplan-report",["exports","core/ajax","core/notification","./vue/vue","./util/debugger","./util/string-helper","./studyplan-report-components","./modedit-modal","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_ajax,_notification,_vue,_debugger,_stringHelper,_studyplanReportComponents,_modeditModal,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(studyplanid,pageid,firstperiod,lastperiod){if(void 0===pageid||!Number.isInteger(Number(pageid))||void 0===studyplanid||!Number.isInteger(Number(studyplanid)))return void debug.error("Did Error: studyplan id and page id not provided as integer numbers to script.",studyplanid,pageid,firstperiod,lastperiod);studyplanid=Number(studyplanid),pageid=Number(pageid);new _vue.default({el:"#root",data:{structure:null},async mounted(){},created(){this.loadStructure()},computed:{},methods:{loadStructure(){const self=this;this.structure=null,(0,_ajax.call)([{methodname:"local_treestudyplan_get_report_structure",args:{pageid:pageid}}])[0].then((function(response){self.structure=response})).catch(_notification.default.exception)}}})},_notification=_interopRequireDefault(_notification),_vue=_interopRequireDefault(_vue),_debugger=_interopRequireDefault(_debugger),_studyplanReportComponents=_interopRequireDefault(_studyplanReportComponents),_modeditModal=_interopRequireDefault(_modeditModal),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_studyplanReportComponents.default),_vue.default.use(_modeditModal.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);let debug=new _debugger.default("treestudyplanviewer");(0,_stringHelper.load_strings)({studyplan:{studyplan_select_placeholder:"studyplan_select_placeholder"}})}));
|
||||
|
||||
//# sourceMappingURL=page-studyplan-report.min.js.map
|
|
@ -1 +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\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":"onBAuCqBA,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"}
|
||||
{"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\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';\n\nimport SRComponents from './studyplan-report-components';\nVue.use(SRComponents);\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} pageid The id of the studyplan page we need to view \n * @param {Number} firstperiod The number of the first period to view\n * @param {Number} lastperiod The number of the last period to view \n */\nexport function init(studyplanid, pageid, firstperiod, lastperiod) {\n if (undefined === pageid || !Number.isInteger(Number(pageid)) ||\n undefined === studyplanid || !Number.isInteger(Number(studyplanid))) {\n debug.error(\"Did Error: studyplan id and page id not provided as integer numbers to script.\",\n studyplanid, pageid, firstperiod, lastperiod);\n return; // Do not continue if plan and page are not proper integers\n }\n // Ensure a numeric value instead of string.\n studyplanid = Number(studyplanid);\n pageid = Number(pageid);\n\n // Startup app.\n const app = new Vue({\n el: '#root',\n data: {\n structure: null,\n },\n async mounted() {\n \n },\n created() {\n this.loadStructure();\n },\n computed: {\n \n },\n methods: {\n loadStructure() {\n const self = this;\n this.structure = null; // Starts loading icon. Hides old data.\n call([{\n methodname: 'local_treestudyplan_get_report_structure',\n args: { pageid: pageid}\n }])[0].then(function(response){\n self.structure = response;\n }).catch(notification.exception);\n }\n },\n });\n}\n"],"names":["studyplanid","pageid","firstperiod","lastperiod","undefined","Number","isInteger","debug","error","Vue","el","data","structure","created","loadStructure","computed","methods","self","this","methodname","args","then","response","catch","notification","exception","use","SRComponents","ModalComponents","PortalVue","BootstrapVue","Debugger","studyplan","studyplan_select_placeholder"],"mappings":"4iBAwCqBA,YAAaC,OAAQC,YAAaC,oBAC/CC,IAAcH,SAAWI,OAAOC,UAAUD,OAAOJ,eACjDG,IAAcJ,cAAgBK,OAAOC,UAAUD,OAAOL,0BACtDO,MAAMC,MAAM,iFACRR,YAAaC,OAAQC,YAAaC,YAI1CH,YAAcK,OAAOL,aACrBC,OAASI,OAAOJ,QAGJ,IAAIQ,aAAI,CAChBC,GAAI,QACJC,KAAM,CACFC,UAAW,wBAKfC,eACSC,iBAETC,SAAU,GAGVC,QAAS,CACLF,sBACUG,KAAOC,UACRN,UAAY,oBACZ,CAAC,CACFO,WAAY,2CACZC,KAAM,CAAEnB,OAAQA,WAChB,GAAGoB,MAAK,SAASC,UACjBL,KAAKL,UAAYU,YAClBC,MAAMC,sBAAaC,mYA5DlCC,IAAIC,iDAEJD,IAAIE,oCAGJF,IAAIG,iCAEJH,IAAII,2BAGJvB,MAAQ,IAAIwB,kBAAS,wBAEX,8BAAa,CACvBC,UAAW,CACPC,6BAA8B"}
|
2
amd/build/page-view-plan.min.js
vendored
2
amd/build/page-view-plan.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
amd/build/studyplan-report-components.min.js
vendored
Normal file
3
amd/build/studyplan-report-components.min.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
define("local_treestudyplan/studyplan-report-components",["exports","./simpleline/simpleline","core/str","./util/string-helper","./util/date-helper","core/ajax","core/notification","./util/svgarc","./util/debugger","core/config","./studyplan-processor","./treestudyplan-components","core/edit_switch"],(function(_exports,_simpleline,_str,_stringHelper,_dateHelper,_ajax,_notification,_svgarc,_debugger,_config,_studyplanProcessor,_treestudyplanComponents,_edit_switch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_notification=_interopRequireDefault(_notification),_debugger=_interopRequireDefault(_debugger),_config=_interopRequireDefault(_config),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents);Math.PI;var _default={install(Vue){Vue.use(_treestudyplanComponents.default);new _debugger.default("treestudyplan-viewer"),(0,_stringHelper.load_strings)({report:{loading:"loadinghelp@core",studyplan_past:"studyplan_past",studyplan_present:"studyplan_present",studyplan_future:"studyplan_future",back:"back"},invalid:{error:"error"},grading:{ungraded:"ungraded",graded:"graded",allgraded:"allgraded",unsubmitted:"unsubmitted",nogrades:"nogrades",unknown:"unknown"},completion:{completed:"completion_completed",incomplete:"completion_incomplete",completed_pass:"completion_passed",completed_fail:"completion_failed",ungraded:"ungraded",aggregation_all:"aggregation_all",aggregation_any:"aggregation_any",aggregation_one:"aggregation_one",aggregation_overall_all:"aggregation_overall_all",aggregation_overall_any:"aggregation_overall_any",aggregation_overall_one:"aggregation_overall_one",completion_not_configured:"completion_not_configured",configure_completion:"configure_completion",view_completion_report:"view_completion_report",completion_incomplete:"completion_incomplete",completion_failed:"completion_failed",completion_pending:"completion_pending",completion_progress:"completion_progress",completion_completed:"completion_completed",completion_good:"completion_good",completion_excellent:"completion_excellent",view_feedback:"view_feedback",coursetiming_past:"coursetiming_past",coursetiming_present:"coursetiming_present",coursetiming_future:"coursetiming_future",required_goal:"required_goal",student_not_tracked:"student_not_tracked",completion_not_enabled:"completion_not_enabled"},badge:{share_badge:"share_badge",dateissued:"dateissued",dateexpire:"dateexpire",badgeinfo:"badgeinfo",badgeissuedstats:"badgeissuedstats",completion_incomplete:"completion_incomplete_badge",completion_completed:"completion_completed_badge",completioninfo:"completioninfo",badgedisabled:"badgedisabled"},course:{completion_incomplete:"completion_incomplete",completion_failed:"completion_failed",completion_pending:"completion_pending",completion_progress:"completion_progress",completion_completed:"completion_completed",completion_good:"completion_good",completion_excellent:"completion_excellent",view_feedback:"view_feedback",coursetiming_past:"coursetiming_past",coursetiming_present:"coursetiming_present",coursetiming_future:"coursetiming_future",required_goal:"required_goal",student_not_tracked:"student_not_tracked",not_enrolled:"not_enrolled"},competency:{competency_not_configured:"competency_not_configured",configure_competency:"configure_competency",when:"when",required:"required",points:"points@core_grades",heading:"competency_heading",details:"competency_details",results:"results",unrated:"unrated",progress:"completion_progress",view_feedback:"view_feedback"},pageinfo:{edit:"period_edit",fullname:"studyplan_name",shortname:"studyplan_shortname",startdate:"studyplan_startdate",enddate:"studyplan_enddate",description:"studyplan_description",duration:"studyplan_duration",details:"studyplan_details"}});Vue.component("q-studyplanreport",{props:{structure:{type:Object}},data:()=>({students:[],studentresults:{},sorting:{name:"asc"}}),created(){this.loadStudents()},computed:{},methods:{loadStudents(){const self=this;(0,_ajax.call)([{methodname:"local_treestudyplan_all_associated_grouped",args:{studyplan_id:this.structure.studyplan.id}}])[0].then((function(response){self.students=response;for(const group of self.students)for(const student of group.users)self.studentresults[student.id]={loading:!0,results:[]},(0,_ajax.call)([{methodname:"local_treestudyplan_get_report_data",args:{pageid:self.structure.page.id,userid:student.id,firstperiod:self.structure.firstperiod,lastperiod:self.structure.lastperiod}}])[0].then((function(response){self.studentresults[student.id].loading=!1,self.studentresults[student.id].results=response})).catch(_notification.default.exception)})).catch(_notification.default.exception)}},mounted(){},updated(){},template:"\n <div>\n \n </div>\n "})}};return _exports.default=_default,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=studyplan-report-components.min.js.map
|
1
amd/build/studyplan-report-components.min.js.map
Normal file
1
amd/build/studyplan-report-components.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
amd/build/vue/vue.min.js
vendored
2
amd/build/vue/vue.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -11,10 +11,9 @@ 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 SRComponents from './studyplan-report-components';
|
||||
Vue.use(SRComponents);
|
||||
import ModalComponents from './modedit-modal';
|
||||
Vue.use(ModalComponents);
|
||||
|
||||
|
@ -35,29 +34,47 @@ let strings = load_strings({
|
|||
/**
|
||||
* 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
|
||||
* @param {Number} pageid The id of the studyplan page we need to view
|
||||
* @param {Number} firstperiod The number of the first period to view
|
||||
* @param {Number} lastperiod The number of the last period 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 {
|
||||
export function init(studyplanid, pageid, firstperiod, lastperiod) {
|
||||
if (undefined === pageid || !Number.isInteger(Number(pageid)) ||
|
||||
undefined === studyplanid || !Number.isInteger(Number(studyplanid))) {
|
||||
debug.error("Did Error: studyplan id and page id not provided as integer numbers to script.",
|
||||
studyplanid, pageid, firstperiod, lastperiod);
|
||||
return; // Do not continue if plan and page are not proper integers
|
||||
}
|
||||
// Ensure a numeric value instead of string.
|
||||
studyplanid = Number(studyplanid);
|
||||
} // ensure a numeric value instead of string.
|
||||
pageid = Number(pageid);
|
||||
|
||||
// Startup app.
|
||||
const app = new Vue({
|
||||
el: '#root',
|
||||
data: {
|
||||
|
||||
structure: null,
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
},
|
||||
created() {
|
||||
this.loadStructure();
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
loadStructure() {
|
||||
const self = this;
|
||||
this.structure = null; // Starts loading icon. Hides old data.
|
||||
call([{
|
||||
methodname: 'local_treestudyplan_get_report_structure',
|
||||
args: { pageid: pageid}
|
||||
}])[0].then(function(response){
|
||||
self.structure = response;
|
||||
}).catch(notification.exception);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -165,13 +165,15 @@ export function init(contextid,categoryid) {
|
|||
}])[0].then(function(response){
|
||||
app.associatedstudents = response;
|
||||
if(studentid){
|
||||
for(const student of app.associatedstudents){
|
||||
for(const group of app.associatedstudents) {
|
||||
for(const student of group.users){
|
||||
if(student.id == studentid){
|
||||
app.showStudentView(student);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch(notification.exception);
|
||||
|
||||
}).catch(function(error){
|
||||
|
|
207
amd/src/studyplan-report-components.js
Normal file
207
amd/src/studyplan-report-components.js
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*eslint no-var: "error"*/
|
||||
/*eslint no-console: "off"*/
|
||||
/*eslint no-unused-vars: warn */
|
||||
/*eslint max-len: ["error", { "code": 160 }] */
|
||||
/*eslint-disable no-trailing-spaces */
|
||||
/*eslint-env es6*/
|
||||
// Put this file in path/to/plugin/amd/src
|
||||
|
||||
import {SimpleLine} from './simpleline/simpleline';
|
||||
import {get_strings} from 'core/str';
|
||||
import {load_strings} from './util/string-helper';
|
||||
import {format_date,studyplanPageTiming,studyplanTiming} from './util/date-helper';
|
||||
import {call} from 'core/ajax';
|
||||
import notification from 'core/notification';
|
||||
import {svgarcpath} from './util/svgarc';
|
||||
import Debugger from './util/debugger';
|
||||
import Config from 'core/config';
|
||||
import {ProcessStudyplan, ProcessStudyplanPage, objCopy} from './studyplan-processor';
|
||||
import TSComponents from './treestudyplan-components';
|
||||
import {eventTypes as editSwEventTypes} from 'core/edit_switch';
|
||||
|
||||
// Make π available as a constant
|
||||
const π = Math.PI;
|
||||
// Gravity value for arrow lines - determines how much a line is pulled in the direction of the start/end before changing direction
|
||||
const LINE_GRAVITY = 1.3;
|
||||
|
||||
|
||||
export default {
|
||||
install(Vue/*,options*/){
|
||||
Vue.use(TSComponents);
|
||||
let debug = new Debugger("treestudyplan-viewer");
|
||||
|
||||
let strings = load_strings({
|
||||
report: {
|
||||
loading: "loadinghelp@core",
|
||||
studyplan_past: "studyplan_past",
|
||||
studyplan_present: "studyplan_present",
|
||||
studyplan_future: "studyplan_future",
|
||||
back: "back",
|
||||
},
|
||||
invalid: {
|
||||
error: 'error',
|
||||
},
|
||||
grading: {
|
||||
ungraded: "ungraded",
|
||||
graded: "graded",
|
||||
allgraded: "allgraded",
|
||||
unsubmitted: "unsubmitted",
|
||||
nogrades: "nogrades",
|
||||
unknown: "unknown",
|
||||
},
|
||||
completion: {
|
||||
completed: "completion_completed",
|
||||
incomplete: "completion_incomplete",
|
||||
completed_pass: "completion_passed",
|
||||
completed_fail: "completion_failed",
|
||||
ungraded: "ungraded",
|
||||
aggregation_all: "aggregation_all",
|
||||
aggregation_any: "aggregation_any",
|
||||
aggregation_one: "aggregation_one",
|
||||
aggregation_overall_all: "aggregation_overall_all",
|
||||
aggregation_overall_any: "aggregation_overall_any",
|
||||
aggregation_overall_one: "aggregation_overall_one",
|
||||
completion_not_configured: "completion_not_configured",
|
||||
configure_completion: "configure_completion",
|
||||
view_completion_report: "view_completion_report",
|
||||
completion_incomplete: "completion_incomplete",
|
||||
completion_failed: "completion_failed",
|
||||
completion_pending: "completion_pending",
|
||||
completion_progress: "completion_progress",
|
||||
completion_completed: "completion_completed",
|
||||
completion_good: "completion_good",
|
||||
completion_excellent: "completion_excellent",
|
||||
view_feedback: "view_feedback",
|
||||
coursetiming_past: "coursetiming_past",
|
||||
coursetiming_present: "coursetiming_present",
|
||||
coursetiming_future: "coursetiming_future",
|
||||
required_goal: "required_goal",
|
||||
student_not_tracked: "student_not_tracked",
|
||||
completion_not_enabled: "completion_not_enabled",
|
||||
},
|
||||
badge: {
|
||||
share_badge: "share_badge",
|
||||
dateissued: "dateissued",
|
||||
dateexpire: "dateexpire",
|
||||
badgeinfo: "badgeinfo",
|
||||
badgeissuedstats: "badgeissuedstats",
|
||||
completion_incomplete: "completion_incomplete_badge",
|
||||
completion_completed: "completion_completed_badge",
|
||||
completioninfo: "completioninfo",
|
||||
badgedisabled: "badgedisabled"
|
||||
},
|
||||
course: {
|
||||
completion_incomplete: "completion_incomplete",
|
||||
completion_failed: "completion_failed",
|
||||
completion_pending: "completion_pending",
|
||||
completion_progress: "completion_progress",
|
||||
completion_completed: "completion_completed",
|
||||
completion_good: "completion_good",
|
||||
completion_excellent: "completion_excellent",
|
||||
view_feedback: "view_feedback",
|
||||
coursetiming_past: "coursetiming_past",
|
||||
coursetiming_present: "coursetiming_present",
|
||||
coursetiming_future: "coursetiming_future",
|
||||
required_goal: "required_goal",
|
||||
student_not_tracked: "student_not_tracked",
|
||||
not_enrolled: "not_enrolled",
|
||||
},
|
||||
competency: {
|
||||
competency_not_configured: "competency_not_configured",
|
||||
configure_competency: "configure_competency",
|
||||
when: "when",
|
||||
required: "required",
|
||||
points: "points@core_grades",
|
||||
heading: "competency_heading",
|
||||
details: "competency_details",
|
||||
results: "results",
|
||||
unrated: "unrated",
|
||||
progress: "completion_progress",
|
||||
view_feedback: "view_feedback",
|
||||
},
|
||||
pageinfo: {
|
||||
edit: 'period_edit',
|
||||
fullname: 'studyplan_name',
|
||||
shortname: 'studyplan_shortname',
|
||||
startdate: 'studyplan_startdate',
|
||||
enddate: 'studyplan_enddate',
|
||||
description: 'studyplan_description',
|
||||
duration: 'studyplan_duration',
|
||||
details: 'studyplan_details',
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/************************************
|
||||
* *
|
||||
* Treestudyplan Viewer components *
|
||||
* *
|
||||
************************************/
|
||||
|
||||
Vue.component('q-studyplanreport', {
|
||||
props: {
|
||||
structure: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
students: [],
|
||||
studentresults: {},
|
||||
|
||||
sorting: {
|
||||
name: "asc",
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.loadStudents();
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
loadStudents() {
|
||||
const self = this;
|
||||
call([{
|
||||
methodname: 'local_treestudyplan_all_associated_grouped',
|
||||
args: { studyplan_id: this.structure.studyplan.id}
|
||||
}])[0].then(function(response){
|
||||
self.students = response;
|
||||
for(const group of self.students) {
|
||||
for(const student of group.users){
|
||||
self.studentresults[student.id] = {
|
||||
loading: true,
|
||||
results: [],
|
||||
};
|
||||
call([{
|
||||
methodname: 'local_treestudyplan_get_report_data',
|
||||
args: { pageid: self.structure.page.id,
|
||||
userid: student.id,
|
||||
firstperiod: self.structure.firstperiod,
|
||||
lastperiod: self.structure.lastperiod,
|
||||
}
|
||||
}])[0].then(function(response){
|
||||
self.studentresults[student.id].loading = false;
|
||||
self.studentresults[student.id].results = response;
|
||||
}).catch(notification.exception);
|
||||
}
|
||||
}
|
||||
}).catch(notification.exception);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
updated() {
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
||||
|
||||
|
||||
},
|
||||
};
|
11907
amd/src/vue/vue.js
11907
amd/src/vue/vue.js
File diff suppressed because one or more lines are too long
|
@ -100,6 +100,49 @@ class badgeinfo {
|
|||
return is_numeric($id) && $DB->record_exists('badge', array('id' => $id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Webservice structure for editor info
|
||||
* @param int $value Webservice requirement constant
|
||||
*/
|
||||
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
|
||||
return new \external_single_structure([
|
||||
"id" => new \external_value(PARAM_INT, 'id of badge'),
|
||||
"infolink" => new \external_value(PARAM_RAW, 'badge issue information link', VALUE_OPTIONAL),
|
||||
"name" => new \external_value(PARAM_RAW, 'badge name'),
|
||||
"status" => new \external_value(PARAM_TEXT, 'badge status'),
|
||||
"locked" => new \external_value(PARAM_TEXT, 'badge lock status'),
|
||||
"description" => new \external_value(PARAM_RAW, 'badge description'),
|
||||
"imageurl" => new \external_value(PARAM_RAW, 'url of badge image'),
|
||||
"active" => new \external_value(PARAM_BOOL, 'badge is available'),
|
||||
], "Badge basic info", $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice model for editor info
|
||||
* @param int[] $studentlist List of user id's to use for checking issueing progress within a study plan
|
||||
* @return array Webservice data model
|
||||
*/
|
||||
public function simple_model() {
|
||||
if ($this->badge->type == BADGE_TYPE_SITE) {
|
||||
$context = \context_system::instance();
|
||||
} else {
|
||||
$context = \context_course::instance($this->badge->courseid);
|
||||
}
|
||||
$model = [
|
||||
'id' => $this->badge->id,
|
||||
'infolink' => (new \moodle_url('/badges/overview.php', ['id' => $this->badge->id]))->out(false),
|
||||
'name' => $this->badge->name,
|
||||
'status' => self::STATUSINFO[$this->badge->status],
|
||||
'locked' => self::LOCKEDINFO[$this->badge->status],
|
||||
'description' => $this->badge->description,
|
||||
'imageurl' => \moodle_url::make_pluginfile_url($context->id,
|
||||
'badges', 'badgeimage', $this->badge->id, '/', 'f1')->out(false),
|
||||
"active" => $this->badge->is_active(),
|
||||
];
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice structure for editor info
|
||||
* @param int $value Webservice requirement constant
|
||||
|
|
|
@ -36,6 +36,10 @@ use stdClass;
|
|||
*/
|
||||
class premium extends \external_api {
|
||||
|
||||
// Toggle the variable below to enable support for premium stuff.
|
||||
// If set to false, all premium features will be enabled and no premium settings panel will be visible.
|
||||
private static $premium_supported = false;
|
||||
|
||||
private static $premiumcrt = "-----BEGIN CERTIFICATE-----
|
||||
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
|
||||
CzAJBgNVBAYTAk5MMRYwFAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRowGAYDVQQKDBFN
|
||||
|
@ -59,6 +63,11 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
|||
|
||||
private static $cachedpremiumstatus = null;
|
||||
|
||||
public static function supported() {
|
||||
return self::$premium_supported;
|
||||
}
|
||||
|
||||
|
||||
private static function decrypt($encrypted) {
|
||||
// Get the public key.
|
||||
$key = \openssl_get_publickey(self::$premiumcrt);
|
||||
|
@ -130,8 +139,12 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
|||
* @return bool
|
||||
*/
|
||||
public static function enabled() {
|
||||
if (self::$premium_supported) {
|
||||
$status = self::premiumStatus();
|
||||
return $status->enabled;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,9 @@ namespace local_treestudyplan;
|
|||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use local_treestudyplan\local\helpers\webservicehelper;
|
||||
use local_treestudyplan\period;
|
||||
use local_treestudyplan\studyplan;
|
||||
use local_treestudyplan\studyplanpage;
|
||||
|
||||
require_once($CFG->libdir.'/externallib.php');
|
||||
|
||||
|
@ -42,7 +45,7 @@ class reportservice extends \external_api {
|
|||
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),
|
||||
"lastperiod" => new \external_value(PARAM_INT, 'last period to include in report',VALUE_DEFAULT),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -51,6 +54,17 @@ class reportservice extends \external_api {
|
|||
*/
|
||||
public static function get_report_structure_returns() : \external_description {
|
||||
return new \external_single_structure([
|
||||
"periods" => new \external_multiple_structure(new \external_single_structure([
|
||||
"period" => period::structure(),
|
||||
"lines" => new \external_multiple_structure(new \external_single_structure([
|
||||
"line" => studyline::simple_structure(),
|
||||
"items" => new \external_multiple_structure(studyitem::editor_structure(), "Information per studyitem"),
|
||||
])),
|
||||
])),
|
||||
"firstperiod" => new \external_value(PARAM_INT, 'first period included in report'),
|
||||
"lastperiod" => new \external_value(PARAM_INT, 'last period included in report'),
|
||||
"studyplan" => studyplan::simple_structure(),
|
||||
"page" => studyplanpage::simple_structure(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -62,7 +76,57 @@ class reportservice extends \external_api {
|
|||
* @return object
|
||||
*/
|
||||
public static function get_report_structure($pageid,$firstperiod=null,$lastperiod=null) {
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
webservicehelper::require_capabilities(self::CAP_VIEW,$page->studyplan()->context());
|
||||
|
||||
$plan = $page->studyplan();
|
||||
if (empty($firstperiod)) {
|
||||
$firstperiod = 1;
|
||||
}
|
||||
if (empty($lastperiod)) {
|
||||
// Index for periods starts at 1, so the period count is same as length
|
||||
$lastperiod = $page->periods();
|
||||
}
|
||||
|
||||
$model = [
|
||||
"studyplan" => $plan->simple_model(),
|
||||
"page" => $page->simple_model(),
|
||||
"firstperiod" => $firstperiod,
|
||||
"lastperiod" => $lastperiod,
|
||||
"periods" => [],
|
||||
];
|
||||
|
||||
// Find all relevant parts in this order
|
||||
|
||||
for($i = $firstperiod; $i <= $lastperiod; $i++) {
|
||||
$period = period::find($page, $i);
|
||||
$pmodel = [
|
||||
'period' => $period->model(),
|
||||
'lines' => [],
|
||||
];
|
||||
|
||||
$lines = studyline::find_page_children($page);
|
||||
foreach ($lines as $line) {
|
||||
$lmodel = [
|
||||
"line" => $line->simple_model(),
|
||||
"items" => [],
|
||||
];
|
||||
$items = studyitem::search_studyline_children($line,$i,studyitem::COURSE);
|
||||
if (count($items) > 0) {
|
||||
foreach ($items as $item) {
|
||||
$lmodel["items"][] = $item->editor_model();
|
||||
}
|
||||
|
||||
// Only include the line if it has actual children - saves us from muddying up the report.
|
||||
$pmodel['lines'][] = $lmodel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$model["periods"][] = $pmodel;
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public static function get_report_data_parameters() : \external_function_parameters {
|
||||
|
@ -79,22 +143,48 @@ class reportservice extends \external_api {
|
|||
* Return value description for webservice function list_user_studyplans
|
||||
*/
|
||||
public static function get_report_data_returns() : \external_description {
|
||||
return new \external_single_structure([
|
||||
]);
|
||||
return new \external_multiple_structure(studyitem::user_structure(), "Information per studyitem");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
webservicehelper::require_capabilities(self::CAP_VIEW,$page->studyplan()->context());
|
||||
$plan = $page->studyplan();
|
||||
if (!$plan->has_linked_user($userid)) {
|
||||
throw new \moodle_exception("error:usernotassociated","local_treestudyplan");
|
||||
}
|
||||
|
||||
if (empty($firstperiod)) {
|
||||
$firstperiod = 1;
|
||||
}
|
||||
if (empty($lastperiod)) {
|
||||
// Index for periods starts at 1, so the period count is same as length
|
||||
$lastperiod = $page->periods();
|
||||
}
|
||||
|
||||
$model = [];
|
||||
|
||||
//TODO: Build report structure
|
||||
|
||||
for($i = $firstperiod; $i <= $lastperiod; $i++) {
|
||||
$lines = studyline::find_page_children($page);
|
||||
foreach ($lines as $line) {
|
||||
$items = studyitem::search_studyline_children($line,$i,studyitem::COURSE);
|
||||
if (count($items) > 0) {
|
||||
foreach ($items as $item) {
|
||||
$model[] = $item->user_model($userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $model;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function get_report_details_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters([
|
||||
"itemid" => new \external_value(PARAM_INT, 'id of studyitem'),
|
||||
|
@ -106,8 +196,7 @@ class reportservice extends \external_api {
|
|||
* Return value description for webservice function list_user_studyplans
|
||||
*/
|
||||
public static function get_report_details_returns() : \external_description {
|
||||
return new \external_single_structure([
|
||||
]);
|
||||
return studyitem::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,7 +206,13 @@ class reportservice extends \external_api {
|
|||
* @return array
|
||||
*/
|
||||
public static function get_report_details($itemid,$userid) {
|
||||
|
||||
$item = studyitem::find_by_id($itemid);
|
||||
$plan = $item->studyline()->studyplan();
|
||||
webservicehelper::require_capabilities(self::CAP_VIEW,$plan->context());
|
||||
if (!$plan->has_linked_user($userid)) {
|
||||
throw new \moodle_exception("error:usernotassociated","local_treestudyplan");
|
||||
}
|
||||
return $item->user_model($userid);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -166,6 +166,47 @@ class studyitem {
|
|||
return is_numeric($id) && $DB->record_exists(self::TABLE, array('id' => $id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice structure for simple info
|
||||
* @param int $value Webservice requirement constant
|
||||
*/
|
||||
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
|
||||
return new \external_single_structure([
|
||||
"id" => new \external_value(PARAM_INT, 'id of study item'),
|
||||
"type" => new \external_value(PARAM_TEXT, 'shortname of study item'),
|
||||
"slot" => new \external_value(PARAM_INT, 'slot in the study plan'),
|
||||
"layer" => new \external_value(PARAM_INT, 'layer in the slot'),
|
||||
"span" => new \external_value(PARAM_INT, 'how many periods the item spans'),
|
||||
"course" => courseinfo::simple_structure(VALUE_OPTIONAL),
|
||||
"badge" => badgeinfo::simple_structure(VALUE_OPTIONAL),
|
||||
],"",$value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice model for editor info
|
||||
* @return array Webservice data model
|
||||
*/
|
||||
public function simple_model() {
|
||||
global $DB;
|
||||
$model = [
|
||||
'id' => $this->r->id, // Id is needed in export model because of link references.
|
||||
'type' => $this->valid() ? $this->r->type : self::INVALID,
|
||||
'slot' => $this->r->slot,
|
||||
'layer' => $this->r->layer,
|
||||
'span' => $this->r->span,
|
||||
];
|
||||
$ci = $this->getcourseinfo();
|
||||
if (isset($ci)) {
|
||||
$model['course'] = $ci->simple_model();
|
||||
}
|
||||
if (is_numeric($this->r->badge_id) && $DB->record_exists('badge', array('id' => $this->r->badge_id))) {
|
||||
$badge = new \core_badges\badge($this->r->badge_id);
|
||||
$badgeinfo = new badgeinfo($badge);
|
||||
$model['badge'] = $badgeinfo->simple_model();
|
||||
}
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice structure for editor info
|
||||
* @param int $value Webservice requirement constant
|
||||
|
@ -185,8 +226,7 @@ class studyitem {
|
|||
'in' => new \external_multiple_structure(studyitemconnection::structure()),
|
||||
'out' => new \external_multiple_structure(studyitemconnection::structure()),
|
||||
]),
|
||||
]);
|
||||
|
||||
],"",$value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,6 +453,30 @@ class studyitem {
|
|||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all studyitems of a given type in a specific period in this line
|
||||
* @param studyline $line The studyline to search for
|
||||
* @param int $slot The slot to search in
|
||||
* @param int $type The type of items to include
|
||||
* @return studyitem[]
|
||||
*/
|
||||
public static function search_studyline_children(studyline $line,$slot,$type) : array {
|
||||
global $DB;
|
||||
$list = [];
|
||||
$ids = $DB->get_fieldset_select(
|
||||
self::TABLE, "id",
|
||||
"line_id = :line_id AND type = :type AND ( slot <= :slota AND ( slot + (span-1) >= :slotb ) ) ORDER BY layer",
|
||||
['line_id' => $line->id(), 'slota' => $slot, 'slotb' => $slot,'type' => $type]
|
||||
);
|
||||
foreach ($ids as $id) {
|
||||
$item = self::find_by_id($id, $line);
|
||||
$list[] = $item;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Webservice structure for linking between plans
|
||||
* @param int $value Webservice requirement constant
|
||||
|
|
|
@ -171,7 +171,35 @@ class studyline {
|
|||
studyitem::editor_structure(), 'filter items'),
|
||||
])
|
||||
)
|
||||
]);
|
||||
],"Study line editor structure",$value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice structure for simple info
|
||||
* @param int $value Webservice requirement constant
|
||||
*/
|
||||
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
|
||||
return new \external_single_structure([
|
||||
"id" => new \external_value(PARAM_INT, 'id of studyline'),
|
||||
"name" => new \external_value(PARAM_TEXT, 'shortname of studyline'),
|
||||
"shortname" => new \external_value(PARAM_TEXT, 'idnumber of studyline'),
|
||||
"color" => new \external_value(PARAM_TEXT, 'description of studyline'),
|
||||
"sequence" => new \external_value(PARAM_INT, 'order of studyline'),
|
||||
],"Study line simple structure",$value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Webservice model for simple info
|
||||
* @return array Webservice data model
|
||||
*/
|
||||
public function simple_model() : array {
|
||||
return [
|
||||
'id' => $this->r->id,
|
||||
'name' => $this->r->name,
|
||||
'shortname' => $this->r->shortname,
|
||||
'color' => $this->r->color,
|
||||
'sequence' => $this->r->sequence,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1575,6 +1575,10 @@ body.path-local-treestudyplan .editmode-switch-form > * {
|
|||
color: var(--danger);
|
||||
}
|
||||
|
||||
.path-local-treestudyplan-studyplan-report {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
|
||||
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
|
||||
justify-content: space-between;
|
||||
|
|
|
@ -434,6 +434,7 @@ $string["error:cannotviewcategory"] = 'Error: You do not have access to view thi
|
|||
$string["error:nostudyplanviewaccess"] = 'Error: You do not have access to view study plans in this category or context: {$a}';
|
||||
$string["error:nostudyplaneditaccess"] = 'Error: You do not have access to manage study plans in this category or context: {$a}';
|
||||
$string["error:nocategoriesvisible"] = 'Error: You have no viewing permissions in any category. Therefore the course list remains empty.';
|
||||
$string["error:usernotassociated"] = 'Error: Requested student is not associated with this studyplan';
|
||||
|
||||
$string["premium:never"] = 'never';
|
||||
$string["premium:anywhere"] = 'for use anywhere';
|
||||
|
|
|
@ -434,6 +434,7 @@ $string["error:cannotviewcategory"] = 'Fout: Je hebt geen rechten om deze catego
|
|||
$string["error:nostudyplanviewaccess"] = 'Fout: Je hebt geen rechten om studieplannen in deze categorie of context te bekijken: {$a}';
|
||||
$string["error:nostudyplaneditaccess"] = 'Fout: Je hebt geen rechten om studieplannen in deze categorie of context te beheren: {$a}';
|
||||
$string["error:nocategoriesvisible"] = 'Fout: Je kunt geen cursussen in een categorie bekijken. Daarom blijft de cursuslijst leeg';
|
||||
$string["error:usernotassociated"] = 'Fout: De gevraagde student is niet gekoppeld aan dit studieplan';
|
||||
|
||||
$string["premium:never"] = 'nooit';
|
||||
$string["premium:anywhere"] = 'voor gebruik overal';
|
||||
|
|
5
scss/studyplan-report.scss
Normal file
5
scss/studyplan-report.scss
Normal file
|
@ -0,0 +1,5 @@
|
|||
.path-local-treestudyplan-studyplan-report {
|
||||
font: inherit;
|
||||
|
||||
|
||||
}
|
|
@ -3,4 +3,5 @@
|
|||
@import "invitemanager.scss";
|
||||
@import "studyplan.scss";
|
||||
@import "studyplancard.scss";
|
||||
@import "studyplan-report.scss";
|
||||
@import "bootstraptweaking.scss";
|
|
@ -333,10 +333,10 @@ if ($hassiteconfig) {
|
|||
|
||||
/**************************************
|
||||
*
|
||||
* Settings page: Cohort sync
|
||||
* Settings page: Premium registration
|
||||
*
|
||||
*************************************/
|
||||
|
||||
if (\local_treestudyplan\premium::supported()) {
|
||||
$pagepremium = new admin_settingpage('local_treestudyplan_settings_premium',
|
||||
get_string('settingspage_premium', 'local_treestudyplan', null, true));
|
||||
|
||||
|
@ -361,5 +361,6 @@ if ($hassiteconfig) {
|
|||
|
||||
// Add settings page2 to the admin settings category.
|
||||
$ADMIN->add('local_treestudyplan', $pagepremium);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use local_treestudyplan\contextinfo;
|
|||
use \local_treestudyplan\courseservice;
|
||||
use \local_treestudyplan\studyplan;
|
||||
use \local_treestudyplan\studyplanpage;
|
||||
use \local_treestudyplan\premium;
|
||||
|
||||
require_once($CFG->libdir.'/weblib.php');
|
||||
|
||||
|
@ -33,11 +34,11 @@ $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.
|
||||
$pageid = required_param('page', PARAM_INT); // Category id.
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
$studyplan = $page->studyplan();
|
||||
$context = $studyplan->context();
|
||||
$contexname = (new contextinfo($studyplancontext))->pathstr();
|
||||
$contexname = (new contextinfo($context))->pathstr();
|
||||
|
||||
$firstperiod = optional_param('firstperiod', 0, PARAM_INT); // First period to show
|
||||
$lastperiod = optional_param('lastperiod', 0, PARAM_INT); // Last periode to show
|
||||
|
@ -49,7 +50,11 @@ $PAGE->set_pagelayout('base');
|
|||
$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)) {
|
||||
if (!premium::enabled()) {
|
||||
throw new \moodle_exception("error:nopremiumaccess","local_treestudyplan","",premium::statusdescription());
|
||||
}
|
||||
|
||||
if(!has_capability('local/treestudyplan:viewuserreports', $context)) {
|
||||
throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","",$contextname);
|
||||
}
|
||||
|
||||
|
@ -82,7 +87,12 @@ print $OUTPUT->header();
|
|||
</div>
|
||||
</div>
|
||||
<div v-cloak>
|
||||
|
||||
<div class='vue-loader' v-if="!structure">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<q-studyplanreport v-else :structure="structure" ></s-studyplanreport>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
|
|
@ -1575,6 +1575,10 @@ body.path-local-treestudyplan .editmode-switch-form > * {
|
|||
color: var(--danger);
|
||||
}
|
||||
|
||||
.path-local-treestudyplan-studyplan-report {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
|
||||
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
|
||||
justify-content: space-between;
|
||||
|
|
Loading…
Reference in New Issue
Block a user