Lot of work on student view with multiple pages, plans and plan progress
This commit is contained in:
parent
fe8d8d0a0f
commit
a208d0023a
2
amd/build/page-myreport.min.js
vendored
2
amd/build/page-myreport.min.js
vendored
|
@ -1,3 +1,3 @@
|
|||
define("local_treestudyplan/page-myreport",["exports","core/ajax","core/notification","./vue/vue","./report-viewer-components","./treestudyplan-components","./util/debugger","./studyplan-processor","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_ajax,_notification,_vue,_reportViewerComponents,_treestudyplanComponents,_debugger,_studyplanProcessor,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){var type=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"myreport",arg=arguments.length>1?arguments[1]:void 0,app=new _vue.default({el:"#root",data:{studyplans:[]},mounted:function(){var call_method,call_args;"invited"==type?(call_method="local_treestudyplan_get_invited_studyplan",call_args={invitekey:arg}):"other"==type?(call_method="local_treestudyplan_get_user_studyplans",call_args={userid:arg}):"teaching"==type?(call_method="local_treestudyplan_get_teaching_studyplans",call_args={}):(call_method="local_treestudyplan_get_own_studyplan",call_args={}),(0,_ajax.call)([{methodname:call_method,args:call_args}])[0].done((function(response){debug.info("Studyplans:",response);var timingval={future:0,present:1,past:2};response.sort((function(a,b){var timinga=_treestudyplanComponents.default.studyplanTiming(a),timingb=_treestudyplanComponents.default.studyplanTiming(b),t=timingval[timinga]-timingval[timingb];return 0==t&&0==(t=new Date(b.startdate).getTime()-new Date(a.startdate).getTime())&&(t=a.name.localeCompare(b.name)),t})),app.studyplans=(0,_studyplanProcessor.ProcessStudyplans)(response)})).fail(_notification.default.exception)},methods:{}})},_notification=_interopRequireDefault(_notification),_vue=_interopRequireDefault(_vue),_reportViewerComponents=_interopRequireDefault(_reportViewerComponents),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents),_debugger=_interopRequireDefault(_debugger),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_reportViewerComponents.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);var debug=new _debugger.default("treestudyplan-report")}));
|
||||
define("local_treestudyplan/page-myreport",["exports","./vue/vue","./report-viewer-components","./util/debugger","./portal-vue/portal-vue.esm","./bootstrap-vue/bootstrap-vue"],(function(_exports,_vue,_reportViewerComponents,_debugger,_portalVue,_bootstrapVue){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){let type=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"own",arg1=arguments.length>1?arguments[1]:void 0;new _vue.default({el:"#root",data:{studyplans:[],type:type,invitekey:"invited"==type?arg1:null,userid:"other"==type?arg1:null},methods:{}})},_vue=_interopRequireDefault(_vue),_reportViewerComponents=_interopRequireDefault(_reportViewerComponents),_debugger=_interopRequireDefault(_debugger),_portalVue=_interopRequireDefault(_portalVue),_bootstrapVue=_interopRequireDefault(_bootstrapVue),_vue.default.use(_reportViewerComponents.default),_vue.default.use(_portalVue.default),_vue.default.use(_bootstrapVue.default);new _debugger.default("treestudyplan-report")}));
|
||||
|
||||
//# sourceMappingURL=page-myreport.min.js.map
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"page-myreport.min.js","sources":["../src/page-myreport.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 no-console: \"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 RVComponents from './report-viewer-components';\nVue.use(RVComponents);\nimport TSComponents from './treestudyplan-components';\n\nimport Debugger from './util/debugger';\n\nimport {ProcessStudyplans} from './studyplan-processor';\n\n\nimport PortalVue from './portal-vue/portal-vue.esm';\nVue.use(PortalVue);\nimport BootstrapVue from './bootstrap-vue/bootstrap-vue';\nVue.use(BootstrapVue);\n\nlet debug = new Debugger(\"treestudyplan-report\");\n\n/**\n * Initialize the Page\n * @param {string} type Type of page to show\n * @param {Object} arg Arguments passed\n */\n export function init(type=\"myreport\",arg) {\n let app = new Vue({\n el: '#root',\n data: {\n \"studyplans\": [],\n },\n mounted() {\n let call_method;\n let call_args;\n if(type == \"invited\"){\n call_method = 'local_treestudyplan_get_invited_studyplan';\n call_args = {\"invitekey\": arg};\n }\n else if(type == \"other\"){\n call_method = 'local_treestudyplan_get_user_studyplans';\n call_args = {\"userid\": arg};\n }\n else if(type == \"teaching\"){\n call_method = 'local_treestudyplan_get_teaching_studyplans';\n call_args = {};\n }\n else{\n call_method = 'local_treestudyplan_get_own_studyplan';\n call_args = {};\n }\n call([{\n methodname: call_method,\n args: call_args\n }])[0].done(function(response){\n debug.info(\"Studyplans:\",response);\n const timingval = { future: 0, present: 1, past: 2, };\n response.sort((a,b) => {\n const timinga = TSComponents.studyplanTiming(a);\n const timingb = TSComponents.studyplanTiming(b);\n\n let t = timingval[timinga] - timingval[timingb];\n if(t == 0){\n // sort by start date if timing is equal\n t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime();\n\n if (t == 0) {\n // sort by name if timing is equal\n t = a.name.localeCompare(b.name);\n }\n }\n return t;\n });\n app.studyplans = ProcessStudyplans(response);\n }).fail(notification.exception);\n\n },\n\n methods: {\n\n },\n });\n\n}\n\n"],"names":["type","arg","app","Vue","el","data","mounted","call_method","call_args","methodname","args","done","response","debug","info","timingval","future","present","past","sort","a","b","timinga","TSComponents","studyplanTiming","timingb","t","Date","startdate","getTime","name","localeCompare","studyplans","fail","notification","exception","methods","use","RVComponents","PortalVue","BootstrapVue","Debugger"],"mappings":"ikBAmCsBA,4DAAK,WAAWC,2CAC9BC,IAAM,IAAIC,aAAI,CACdC,GAAI,QACJC,KAAM,YACY,IAElBC,uBACQC,YACAC,UACO,WAARR,MACCO,YAAc,4CACdC,UAAY,WAAcP,MAEd,SAARD,MACJO,YAAc,0CACdC,UAAY,QAAWP,MAEX,YAARD,MACJO,YAAc,8CACdC,UAAY,KAGZD,YAAc,wCACdC,UAAY,mBAEX,CAAC,CACFC,WAAYF,YACZG,KAAMF,aACN,GAAGG,MAAK,SAASC,UACjBC,MAAMC,KAAK,cAAcF,cACnBG,UAAY,CAAEC,OAAQ,EAAGC,QAAS,EAAGC,KAAM,GACjDN,SAASO,MAAK,SAACC,EAAEC,OACPC,QAAUC,iCAAaC,gBAAgBJ,GACvCK,QAAUF,iCAAaC,gBAAgBH,GAEzCK,EAAIX,UAAUO,SAAWP,UAAUU,gBAC/B,GAALC,GAIU,IAFTA,EAAI,IAAIC,KAAKN,EAAEO,WAAWC,UAAY,IAAIF,KAAKP,EAAEQ,WAAWC,aAIxDH,EAAIN,EAAEU,KAAKC,cAAcV,EAAES,OAG5BJ,KAEXxB,IAAI8B,YAAa,yCAAkBpB,aACpCqB,KAAKC,sBAAaC,YAIzBC,QAAS,yYAxEbC,IAAIC,8CASJD,IAAIE,iCAEJF,IAAIG,2BAEJ3B,MAAQ,IAAI4B,kBAAS"}
|
||||
{"version":3,"file":"page-myreport.min.js","sources":["../src/page-myreport.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 no-console: \"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 Vue from './vue/vue';\n\nimport RVComponents from './report-viewer-components';\nVue.use(RVComponents);\n\nimport Debugger from './util/debugger';\n\nimport PortalVue from './portal-vue/portal-vue.esm';\nVue.use(PortalVue);\nimport BootstrapVue from './bootstrap-vue/bootstrap-vue';\nVue.use(BootstrapVue);\n\nlet debug = new Debugger(\"treestudyplan-report\");\n\n/**\n * Initialize the Page\n * @param {string} type Type of page to show\n * @param {Object} arg1 Argument1 as passed\n */\n export function init(type=\"own\",arg1) {\n let app = new Vue({\n el: '#root',\n data: {\n \"studyplans\": [],\n \"type\": type,\n \"invitekey\": (type==\"invited\")?arg1:null,\n \"userid\": (type==\"other\")?arg1:null,\n },\n methods: {\n\n },\n });\n\n}\n\n"],"names":["type","arg1","Vue","el","data","methods","use","RVComponents","PortalVue","BootstrapVue","Debugger"],"mappings":"2aA4BsBA,4DAAK,MAAMC,4CACnB,IAAIC,aAAI,CACdC,GAAI,QACJC,KAAM,YACY,QACNJ,eACY,WAANA,KAAiBC,KAAK,YACnB,SAAND,KAAeC,KAAK,MAEnCI,QAAS,2QAzBbC,IAAIC,8CAKJD,IAAIE,iCAEJF,IAAIG,uBAEI,IAAIC,kBAAS"}
|
2
amd/build/report-viewer-components.min.js
vendored
2
amd/build/report-viewer-components.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
2
amd/build/studyplan-processor.min.js
vendored
2
amd/build/studyplan-processor.min.js
vendored
|
@ -1,3 +1,3 @@
|
|||
define("local_treestudyplan/studyplan-processor",["exports"],(function(_exports){function ProcessStudyplan(studyplan){for(var ip in studyplan.pages){ProcessStudyplanPage(studyplan.pages[ip])}return studyplan}function ProcessStudyplanPage(page){var connections={};for(var il in page.studylines){var line=page.studylines[il];for(var is in line.slots){var slot=line.slots[is];if(void 0!==slot.courses)for(var ic in slot.courses){var itm=slot.courses[ic];for(var idx in itm.connections.in){var conn=itm.connections.in[idx];conn.id in connections?itm.connections[idx]=connections[conn.id]:connections[conn.id]=conn}for(var _idx in itm.connections.out){var _conn=itm.connections.out[_idx];_conn.id in connections?itm.connections[_idx]=connections[_conn.id]:connections[_conn.id]=_conn}}if(void 0!==slot.filters)for(var ix in slot.filters){var _itm=slot.filters[ix];for(var _idx2 in _itm.connections.in){var _conn2=_itm.connections.in[_idx2];_conn2.id in connections?_itm.connections[_idx2]=connections[_conn2.id]:connections[_conn2.id]=_conn2}for(var _idx3 in _itm.connections.out){var _conn3=_itm.connections.out[_idx3];_conn3.id in connections?_itm.connections[_idx3]=connections[_conn3.id]:connections[_conn3.id]=_conn3}}}}return page}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.ProcessStudyplan=ProcessStudyplan,_exports.ProcessStudyplanPage=ProcessStudyplanPage,_exports.ProcessStudyplans=function(studyplans){for(var isx in studyplans){ProcessStudyplan(studyplans[isx])}return studyplans},_exports.objCopy=function(target,source,fields){for(var ix in fields){var field=fields[ix];target[field]=source[field]}},_exports.transportItem=function(target,source,identifier,param){param||(param="value");var item,itemindex;for(var ix in source)if(source[ix][param]==identifier){item=source[ix],itemindex=ix;break}item&&(target.push(item),source.splice(itemindex,1))}}));
|
||||
define("local_treestudyplan/studyplan-processor",["exports"],(function(_exports){function ProcessStudyplan(studyplan){for(const ip in studyplan.pages){ProcessStudyplanPage(studyplan.pages[ip])}return studyplan}function ProcessStudyplanPage(page){let connections={};for(const il in page.studylines){const line=page.studylines[il];for(const is in line.slots){const slot=line.slots[is];if(void 0!==slot.courses)for(const ic in slot.courses){const itm=slot.courses[ic];for(const idx in itm.connections.in){const conn=itm.connections.in[idx];conn.id in connections?itm.connections[idx]=connections[conn.id]:connections[conn.id]=conn}for(const idx in itm.connections.out){const conn=itm.connections.out[idx];conn.id in connections?itm.connections[idx]=connections[conn.id]:connections[conn.id]=conn}}if(void 0!==slot.filters)for(const ix in slot.filters){const itm=slot.filters[ix];for(const idx in itm.connections.in){const conn=itm.connections.in[idx];conn.id in connections?itm.connections[idx]=connections[conn.id]:connections[conn.id]=conn}for(const idx in itm.connections.out){const conn=itm.connections.out[idx];conn.id in connections?itm.connections[idx]=connections[conn.id]:connections[conn.id]=conn}}}}return page}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.ProcessStudyplan=ProcessStudyplan,_exports.ProcessStudyplanPage=ProcessStudyplanPage,_exports.ProcessStudyplans=function(studyplans){for(const isx in studyplans){ProcessStudyplan(studyplans[isx])}return studyplans},_exports.objCopy=function(target,source,fields){null==fields&&(fields=Object.getOwnPropertyNames(source));for(const ix in fields){const field=fields[ix];target[field]=source[field]}return target},_exports.transportItem=function(target,source,identifier,param){param||(param="value");let item,itemindex;for(const ix in source)if(source[ix][param]==identifier){item=source[ix],itemindex=ix;break}item&&(target.push(item),source.splice(itemindex,1))}}));
|
||||
|
||||
//# sourceMappingURL=studyplan-processor.min.js.map
|
File diff suppressed because one or more lines are too long
2
amd/build/treestudyplan-components.min.js
vendored
2
amd/build/treestudyplan-components.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
2
amd/build/util/date-helper.min.js
vendored
2
amd/build/util/date-helper.min.js
vendored
|
@ -1,3 +1,3 @@
|
|||
define("local_treestudyplan/util/date-helper",["exports"],(function(_exports){function format_date(d,short){d instanceof Date||(d=new Date(d));var monthformat="short";return short&&(monthformat="numeric"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.add_days=function(datestr,days){var date=new Date(datestr);return function(date){var d=new Date(date),month=""+(d.getMonth()+1),day=""+d.getDate(),year=d.getFullYear();month.length<2&&(month="0"+month);day.length<2&&(day="0"+day);return[year,month,day].join("-")}(new Date(date.getTime()+864e5*days))},_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);var dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date}));
|
||||
define("local_treestudyplan/util/date-helper",["exports"],(function(_exports){function format_date(d,short){d instanceof Date||(d=new Date(d));let monthformat="short";return short&&(monthformat="numeric"),d.toLocaleDateString(document.documentElement.lang,{year:"numeric",month:monthformat,day:"numeric"})}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.add_days=function(datestr,days){const date=new Date(datestr);return function(date){const d=new Date(date);let month=""+(d.getMonth()+1),day=""+d.getDate();const year=d.getFullYear();month.length<2&&(month="0"+month);day.length<2&&(day="0"+day);return[year,month,day].join("-")}(new Date(date.getTime()+864e5*days))},_exports.datespaninfo=function(first,last){first instanceof Date||(first=new Date(first));last instanceof Date||(last=new Date(last));first.setHours(0),first.setMinutes(0),first.setSeconds(0),first.setMilliseconds(0),last.setHours(23),last.setMinutes(59),last.setSeconds(59),last.setMilliseconds(999);const dayspan=Math.round((last-first+1)/864e5),years=Math.floor(dayspan/365),ydaysleft=dayspan%365,weeks=Math.floor(ydaysleft/7);return{first:first,last:last,totaldays:dayspan,years:years,weeks:weeks,days:ydaysleft%7,formatted:{first:format_date(first),last:format_date(last)}}},_exports.format_date=format_date,_exports.studyplanDates=function(plan){let earliestStart=null,latestEnd=null,openEnded=!1;for(const ix in plan.pages){const page=plan.pages[ix],s=new Date(page.startdate);if(page.enddate||(openEnded=!0),(!earliestStart||s<earliestStart)&&(earliestStart=s),page.enddate){const e=new Date(page.enddate);(!latestEnd||e>latestEnd)&&(latestEnd=e)}}return{start:earliestStart,end:openEnded?null:latestEnd}}}));
|
||||
|
||||
//# sourceMappingURL=date-helper.min.js.map
|
File diff suppressed because one or more lines are too long
|
@ -7,20 +7,13 @@
|
|||
// 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 RVComponents from './report-viewer-components';
|
||||
Vue.use(RVComponents);
|
||||
import TSComponents from './treestudyplan-components';
|
||||
|
||||
import Debugger from './util/debugger';
|
||||
|
||||
import {ProcessStudyplans} from './studyplan-processor';
|
||||
|
||||
|
||||
import PortalVue from './portal-vue/portal-vue.esm';
|
||||
Vue.use(PortalVue);
|
||||
import BootstrapVue from './bootstrap-vue/bootstrap-vue';
|
||||
|
@ -31,60 +24,17 @@ let debug = new Debugger("treestudyplan-report");
|
|||
/**
|
||||
* Initialize the Page
|
||||
* @param {string} type Type of page to show
|
||||
* @param {Object} arg Arguments passed
|
||||
* @param {Object} arg1 Argument1 as passed
|
||||
*/
|
||||
export function init(type="myreport",arg) {
|
||||
export function init(type="own",arg1) {
|
||||
let app = new Vue({
|
||||
el: '#root',
|
||||
data: {
|
||||
"studyplans": [],
|
||||
"type": type,
|
||||
"invitekey": (type=="invited")?arg1:null,
|
||||
"userid": (type=="other")?arg1:null,
|
||||
},
|
||||
mounted() {
|
||||
let call_method;
|
||||
let call_args;
|
||||
if(type == "invited"){
|
||||
call_method = 'local_treestudyplan_get_invited_studyplan';
|
||||
call_args = {"invitekey": arg};
|
||||
}
|
||||
else if(type == "other"){
|
||||
call_method = 'local_treestudyplan_get_user_studyplans';
|
||||
call_args = {"userid": arg};
|
||||
}
|
||||
else if(type == "teaching"){
|
||||
call_method = 'local_treestudyplan_get_teaching_studyplans';
|
||||
call_args = {};
|
||||
}
|
||||
else{
|
||||
call_method = 'local_treestudyplan_get_own_studyplan';
|
||||
call_args = {};
|
||||
}
|
||||
call([{
|
||||
methodname: call_method,
|
||||
args: call_args
|
||||
}])[0].done(function(response){
|
||||
debug.info("Studyplans:",response);
|
||||
const timingval = { future: 0, present: 1, past: 2, };
|
||||
response.sort((a,b) => {
|
||||
const timinga = TSComponents.studyplanTiming(a);
|
||||
const timingb = TSComponents.studyplanTiming(b);
|
||||
|
||||
let t = timingval[timinga] - timingval[timingb];
|
||||
if(t == 0){
|
||||
// sort by start date if timing is equal
|
||||
t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime();
|
||||
|
||||
if (t == 0) {
|
||||
// sort by name if timing is equal
|
||||
t = a.name.localeCompare(b.name);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
});
|
||||
app.studyplans = ProcessStudyplans(response);
|
||||
}).fail(notification.exception);
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ 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';
|
||||
|
||||
|
@ -23,12 +24,11 @@ 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");
|
||||
|
||||
debug.warn(Config);
|
||||
let lastCaller = null;
|
||||
/**
|
||||
* Scroll current period into view
|
||||
|
@ -49,6 +49,13 @@ export default {
|
|||
}
|
||||
|
||||
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',
|
||||
},
|
||||
|
@ -136,7 +143,8 @@ export default {
|
|||
startdate: 'studyplan_startdate',
|
||||
enddate: 'studyplan_enddate',
|
||||
description: 'studyplan_description',
|
||||
duration: 'studyplan_duration'
|
||||
duration: 'studyplan_duration',
|
||||
details: 'studyplan_details',
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -247,51 +255,180 @@ export default {
|
|||
|
||||
Vue.component('r-report', {
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
invitekey: {
|
||||
type: String,
|
||||
default() { return null;},
|
||||
},
|
||||
guestmode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
userid: {
|
||||
type: Number,
|
||||
default() { return 0;},
|
||||
},
|
||||
teachermode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
type: {
|
||||
type: String,
|
||||
default() { return "own";},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: strings.report,
|
||||
studyplans: {
|
||||
past: [],
|
||||
present: [],
|
||||
future: [],
|
||||
},
|
||||
|
||||
selectedstudyplan: null,
|
||||
loadingstudyplan: false,
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayedstudyplan(){
|
||||
if(this.selectedstudyplan){
|
||||
return this.selectedstudyplan;
|
||||
} else if(this.value && this.value.length > 0){
|
||||
return this.value[0];
|
||||
teachermode() {
|
||||
return (this.type =="teaching");
|
||||
},
|
||||
guestmode() {
|
||||
return (this.type == "invited");
|
||||
},
|
||||
verified_type() {
|
||||
if (! ["invited","other","teaching","own"].includes(this.type)) {
|
||||
return "own";
|
||||
} else {
|
||||
return null;
|
||||
return this.type;
|
||||
}
|
||||
},
|
||||
studyplancount() {
|
||||
return this.studyplans.past.length + this.studyplans.present.length + this.studyplans.future.length;
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.loadStudyplans();
|
||||
},
|
||||
|
||||
methods: {
|
||||
selectstudyplan(plan) {
|
||||
this.selectedstudyplan = plan;
|
||||
call_args(o) {
|
||||
const args = {};
|
||||
if (typeof o == 'object' && !Array.isArray(o) && o !== null) {
|
||||
objCopy(args,o);
|
||||
}
|
||||
|
||||
if(this.verified_type == "invited") {
|
||||
args["invitekey"] = this.invitekey;
|
||||
} else if(this.verified_type == "other") {
|
||||
args["userid"] = this.userid;
|
||||
}
|
||||
return args;
|
||||
},
|
||||
loadStudyplans() {
|
||||
const self = this;
|
||||
this.loading = true;
|
||||
call([{
|
||||
methodname: `local_treestudyplan_list_${this.verified_type}_studyplans`,
|
||||
args: this.call_args(),
|
||||
}])[0].done(function(response){
|
||||
debug.info("Studyplans:",response);
|
||||
|
||||
const plans = { future: [], present: [], past: [], };
|
||||
|
||||
for (const ix in response) {
|
||||
const plan = response[ix];
|
||||
const timing = TSComponents.studyplanTiming(plan);
|
||||
plans[timing].push(plan);
|
||||
}
|
||||
|
||||
for (const ix in plans) {
|
||||
debug.info(ix, plans[ix]);
|
||||
plans[ix].sort((a,b) => {
|
||||
const t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime();
|
||||
if (t == 0) {
|
||||
// sort by name if timing is equal
|
||||
t = a.name.localeCompare(b.name);
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
self.studyplans = plans;
|
||||
self.loading = false;
|
||||
|
||||
if (self.studyplans.present.length == 1) {
|
||||
// Directly show the current study plan if it's the only one
|
||||
self.selectStudyplan(self.studyplans.present[0]);
|
||||
} else {
|
||||
// If there is but a single studyplan, select it anyway, even if it is not current...
|
||||
if (this.studyplancount == 1) {
|
||||
if(self.studyplans.future.lengh > 0) {
|
||||
self.selectStudyplan(self.studyplans.future[0]);
|
||||
} else {
|
||||
self.selectStudyplan(self.studyplans.past[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(notification.exception);
|
||||
},
|
||||
selectStudyplan(plan) {
|
||||
const self = this;
|
||||
this.loadingstudyplan = true;
|
||||
call([{
|
||||
methodname: `local_treestudyplan_get_${this.verified_type}_studyplan`,
|
||||
args: this.call_args({
|
||||
studyplanid: plan.id,
|
||||
}),
|
||||
}])[0].done(function(response){
|
||||
debug.info("Detailed studyplan:",response);
|
||||
self.selectedstudyplan = ProcessStudyplan(response);
|
||||
self.loadingstudyplan = false;
|
||||
}).fail(notification.exception);
|
||||
},
|
||||
deselectStudyplan() {
|
||||
this.selectedstudyplan = null;
|
||||
this.loadStudyplans(); // Reload the list of studyplans.
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class='t-studyplan-container r-report-tabs'>
|
||||
<b-list-group horizontal>
|
||||
<b-list-group-item
|
||||
v-for="(studyplan,planindex) in value"
|
||||
:key="studyplan.id"
|
||||
:active="displayedstudyplan && studyplan.id == displayedstudyplan.id"
|
||||
button
|
||||
@click="selectstudyplan(studyplan)"
|
||||
>{{studyplan.name}}</b-list-group-item>
|
||||
</b-list-group>
|
||||
<r-studyplan v-if='displayedstudyplan' v-model='displayedstudyplan' :guestmode='guestmode' :teachermode='teachermode'></r-studyplan>
|
||||
<div v-if='loading' class="vue-loader spinner-border text-primary" role="status"></div>
|
||||
<template v-else>
|
||||
<div v-if='!loadingstudyplan && selectedstudyplan'>
|
||||
<div class="mb-2">
|
||||
<a href='#' @click='deselectStudyplan'><h5 class="d-inline"><i class="fa fa-chevron-left"></i> {{ text.back }}</h5></a>
|
||||
<h4 class="d-inline ml-3">{{ selectedstudyplan.name}}
|
||||
<s-studyplan-details
|
||||
class="mb-2"
|
||||
size="sm"
|
||||
v-model="selectedstudyplan"
|
||||
v-if="selectedstudyplan.description"
|
||||
><i class='fa fa-info-circle'></i></s-studyplan-details></h4>
|
||||
</div>
|
||||
<r-studyplan
|
||||
v-model='selectedstudyplan'
|
||||
:guestmode='guestmode'
|
||||
:teachermode='teachermode'
|
||||
></r-studyplan>
|
||||
</div>
|
||||
<div v-else-if='loadingstudyplan' class="vue-loader spinner-border text-primary" role="status">
|
||||
<span class="sr-only">{{ text.loading }}</span>
|
||||
</div>
|
||||
<div v-else class='t-studyplan-notselected'>
|
||||
<template v-for="timing in ['present', 'past', 'future']">
|
||||
<template v-if="studyplans[timing].length > 0">
|
||||
<h4>{{ text["studyplan_"+timing]}}:</h4>
|
||||
<b-card-group deck>
|
||||
<s-studyplan-card
|
||||
v-for='(studyplan, planindex) in studyplans[timing]'
|
||||
:key='studyplan.id'
|
||||
v-model='studyplans[timing][planindex]'
|
||||
open
|
||||
@open='selectStudyplan(studyplan)'
|
||||
></s-studyplan-card>
|
||||
</b-card-group>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
@ -415,7 +552,7 @@ export default {
|
|||
:title-item-class="'s-studyplanpage-tab '+ page.timing"
|
||||
><template #title>
|
||||
<span v-b-tooltip.hover :title='page.fullname'>{{page.shortname}}</span>
|
||||
<a href="#" v-b-modal="'studyplanpage-info-'+page.id" variant='info'
|
||||
<a href="#" v-b-modal="'studyplanpage-info-'+page.id" class='text-info'
|
||||
v-if='pageindex == selectedpageindex'
|
||||
><i class='fa fa-info-circle'></i></a>
|
||||
</template>
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
/*eslint no-console: "off"*/
|
||||
/**
|
||||
* Copy fields from one object to another
|
||||
* @param {Object} target The target to move to
|
||||
* @param {Object} source The source to move from
|
||||
* @param {Object} target The target to copy to
|
||||
* @param {Object} source The source to copy from
|
||||
* @param {Array} fields The field names to copy
|
||||
* @returns {Object} The map with strings loaded in
|
||||
* @returns {Object} Reference to target
|
||||
*/
|
||||
export function objCopy(target,source,fields){
|
||||
if ( fields === undefined || fields === null) {
|
||||
fields = Object.getOwnPropertyNames(source);
|
||||
}
|
||||
for(const ix in fields) {
|
||||
const field = fields[ix];
|
||||
target[field] = source[field];
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,20 +5,23 @@
|
|||
// Put this file in path/to/plugin/amd/src
|
||||
|
||||
import {load_strings} from './util/string-helper';
|
||||
import {format_date} from './util/date-helper';
|
||||
import {format_date, studyplanDates} from './util/date-helper';
|
||||
|
||||
export default {
|
||||
studyplanTiming(a) {
|
||||
studyplanTiming(plan) {
|
||||
const now = new Date().getTime();
|
||||
let timing = 'future';
|
||||
if(new Date(a.startdate).getTime() < now){
|
||||
if(a.enddate && now > new Date(a.enddate).getTime()) {
|
||||
timing = 'past';
|
||||
|
||||
const dates = studyplanDates(plan);
|
||||
|
||||
if(dates.start < now){
|
||||
if( dates.end && now > dates.end) {
|
||||
return 'past';
|
||||
} else {
|
||||
timing = 'present';
|
||||
return 'present';
|
||||
}
|
||||
} else {
|
||||
return 'future';
|
||||
}
|
||||
return timing;
|
||||
},
|
||||
|
||||
install(Vue/*,options*/){
|
||||
|
@ -29,6 +32,10 @@ export default {
|
|||
idnumber: "studyplan_idnumber",
|
||||
description: "studyplan_description",
|
||||
completed: "completed",
|
||||
details: "studyplan_details",
|
||||
},
|
||||
details: {
|
||||
details: "studyplan_details",
|
||||
}
|
||||
});
|
||||
// Create new eventbus for interaction between item components
|
||||
|
@ -63,16 +70,12 @@ export default {
|
|||
}
|
||||
return timing;
|
||||
},
|
||||
startdate(){
|
||||
return format_date(this.value.pages[0].startdate);
|
||||
},
|
||||
enddate(){
|
||||
if(this.value.pages[0].enddate){
|
||||
return format_date(this.value.pages[0].enddate);
|
||||
}
|
||||
else {
|
||||
return this.text.noenddate;
|
||||
}
|
||||
dates(){
|
||||
const dates = studyplanDates(this.value);
|
||||
return {
|
||||
start: format_date(dates.start),
|
||||
end: (dates.end)?format_date(dates.end):this.text.noenddate,
|
||||
};
|
||||
},
|
||||
width_completed() {
|
||||
if(this.value.progress) {
|
||||
|
@ -139,22 +142,13 @@ export default {
|
|||
</div>
|
||||
<slot></slot>
|
||||
<template #footer>
|
||||
<span :class="'t-timing-'+timing" v-html="startdate + ' - '+ enddate"></span>
|
||||
<span :class="'t-timing-'+timing" v-html="dates.start + ' - '+ dates.end"></span>
|
||||
<span class="s-studyplan-card-buttons">
|
||||
<slot name='footer'></slot>
|
||||
<template v-if='value.description'>
|
||||
<b-button variant="primary" v-b-modal="'modal-description-'+value.id"
|
||||
><i class='fa fa-info-circle'></i> {{ text.description }}</b-button>
|
||||
<b-modal
|
||||
:title="value.name"
|
||||
scrollable
|
||||
centered
|
||||
ok-only
|
||||
size="xl"
|
||||
:id="'modal-description-'+value.id"
|
||||
><span v-html="value.description"></span>
|
||||
</b-modal>
|
||||
</template>
|
||||
<s-studyplan-details
|
||||
v-model="value"
|
||||
v-if="value.description"
|
||||
><i class='fa fa-info-circle'></i></s-studyplan-details>
|
||||
<b-button style="float:right;" v-if='open' variant='primary'
|
||||
@click.prevent='onOpenClick($event)'>{{ text.open }}</b-button>
|
||||
</span>
|
||||
|
@ -271,5 +265,59 @@ export default {
|
|||
});
|
||||
|
||||
|
||||
Vue.component('s-studyplan-details', {
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default() { return "info"; }
|
||||
},
|
||||
pill: {
|
||||
type: Boolean,
|
||||
default() { return false; }
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default() { return "";}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: strings.details,
|
||||
};
|
||||
},
|
||||
template: `
|
||||
<span>
|
||||
<b-button
|
||||
:size="size"
|
||||
:pill="pill"
|
||||
:variant="variant"
|
||||
v-b-modal="'modal-description-'+value.id"
|
||||
><slot><i class='fa fa-info-circle'></i>
|
||||
{{ text.details}}</slot>
|
||||
</b-button>
|
||||
<b-modal
|
||||
:title="value.name"
|
||||
scrollable
|
||||
centered
|
||||
ok-only
|
||||
content-class="s-studyplan-details"
|
||||
:id="'modal-description-'+value.id"
|
||||
>
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col cols="4"><img :src='value.icon'></b-col>
|
||||
<b-col cols="8" class="pl-1">
|
||||
<span v-html="value.description"></span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
</b-modal>
|
||||
</span>
|
||||
`,
|
||||
});
|
||||
|
||||
}
|
||||
};
|
|
@ -91,4 +91,37 @@ export function add_days(datestr,days) {
|
|||
const date = new Date(datestr);
|
||||
const newdate = new Date(date.getTime() + (days * 86400000) ); // Add n days in ms.
|
||||
return dateYYYYMMDD(newdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine start and end dates of a studyplan
|
||||
* @param {*} plan
|
||||
* @returns
|
||||
*/
|
||||
export function studyplanDates(plan) {
|
||||
let earliestStart = null;
|
||||
let latestEnd = null;
|
||||
let openEnded = false;
|
||||
for(const ix in plan.pages) {
|
||||
const page = plan.pages[ix];
|
||||
const s = new Date(page.startdate);
|
||||
if (! page.enddate) {
|
||||
openEnded = true; // One of the pages has no end date set...
|
||||
}
|
||||
|
||||
if (!earliestStart || s < earliestStart) {
|
||||
earliestStart = s;
|
||||
}
|
||||
|
||||
if ( page.enddate ) {
|
||||
const e = new Date(page.enddate);
|
||||
if (!latestEnd || e > latestEnd) {
|
||||
latestEnd = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
start: earliestStart,
|
||||
end: (openEnded)?null:latestEnd,
|
||||
};
|
||||
}
|
|
@ -300,14 +300,12 @@ class courseinfo {
|
|||
* @param bool $usecorecompletioninfo Whether to use corecompletion info instead of custom selected gradables
|
||||
* @return array Webservice data model
|
||||
*/
|
||||
public function editor_model(studyitem $studyitem = null, $usecorecompletioninfo = false) {
|
||||
global $DB;
|
||||
public function editor_model($usecorecompletioninfo = false) {
|
||||
$contextinfo = new contextinfo($this->context);
|
||||
|
||||
$timing = $this->timing();
|
||||
|
||||
if (isset($studyitem)) {
|
||||
$numenrolled = $this->count_enrolled_students($studyitem->studyline()->studyplan()->find_linked_userids());
|
||||
if (isset($this->studyitem)) {
|
||||
$numenrolled = $this->count_enrolled_students($this->studyitem->studyline()->studyplan()->find_linked_userids());
|
||||
} else {
|
||||
$numenrolled = 0;
|
||||
}
|
||||
|
@ -330,18 +328,18 @@ class courseinfo {
|
|||
'numenrolled' => $numenrolled,
|
||||
];
|
||||
|
||||
if (!$usecorecompletioninfo) {
|
||||
$gradables = gradeinfo::list_course_gradables($this->course, $studyitem ? $studyitem : $this->studyitem );
|
||||
|
||||
foreach ($gradables as $gradable) {
|
||||
$info['grades'][] = $gradable->editor_model($studyitem ? $studyitem : $this->studyitem);
|
||||
if (isset($this->studyitem)) {
|
||||
if (!$usecorecompletioninfo) {
|
||||
$gradables = gradeinfo::list_course_gradables($this->course, $this->studyitem );
|
||||
foreach ($gradables as $gradable) {
|
||||
$info['grades'][] = $gradable->editor_model($this->studyitem);
|
||||
}
|
||||
} else {
|
||||
$cc = new corecompletioninfo($this->course, $this->studyitem);
|
||||
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
|
||||
$info['completion'] = $cc->editor_model($studentlist);
|
||||
}
|
||||
} else if (isset($this->studyitem)) {
|
||||
$cc = new corecompletioninfo($this->course, $this->studyitem);
|
||||
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
|
||||
$info['completion'] = $cc->editor_model($studentlist);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
@ -441,16 +439,17 @@ class courseinfo {
|
|||
'enrolled' => $this->is_enrolled_student($userid),
|
||||
];
|
||||
|
||||
if (!$usecorecompletioninfo) {
|
||||
$gradables = gradeinfo::list_studyitem_gradables($this->studyitem);
|
||||
foreach ($gradables as $gi) {
|
||||
$info['grades'][] = $gi->user_model($userid);
|
||||
if (isset($this->studyitem)) {
|
||||
if (!$usecorecompletioninfo) {
|
||||
$gradables = gradeinfo::list_studyitem_gradables($this->studyitem);
|
||||
foreach ($gradables as $gi) {
|
||||
$info['grades'][] = $gi->user_model($userid);
|
||||
}
|
||||
} else if (isset($this->studyitem)) {
|
||||
$cc = new corecompletioninfo($this->course, $this->studyitem);
|
||||
$info['completion'] = $cc->user_model($userid);
|
||||
}
|
||||
} else if (isset($this->studyitem)) {
|
||||
$cc = new corecompletioninfo($this->course, $this->studyitem);
|
||||
$info['completion'] = $cc->user_model($userid);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
|
49
classes/debug.php
Normal file
49
classes/debug.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?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/>.
|
||||
/**
|
||||
* Ease of debugging tools
|
||||
* @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();
|
||||
|
||||
class debug {
|
||||
/**
|
||||
* @param $object Object to dump
|
||||
* @param $filename File to write to
|
||||
* @return any The object
|
||||
*/
|
||||
public static function &dump(&$object,$filename="/tmp/debug.log") {
|
||||
$f = fopen($filename,"a+");
|
||||
fwrite($f,\json_encode($object,JSON_PRETTY_PRINT )."\n");
|
||||
fclose($f);
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $object Object to dump
|
||||
* @param $filename File to write to
|
||||
* @return any The object
|
||||
*/
|
||||
public static function write($text,$filename="/tmp/debug.log") {
|
||||
$f = fopen($filename,"a+");
|
||||
fwrite($f,$text."\n");
|
||||
fclose($f);
|
||||
}
|
||||
}
|
|
@ -69,7 +69,6 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
|
|||
*/
|
||||
protected function initialize($configstr) {
|
||||
// First initialize with the defaults.
|
||||
|
||||
foreach (["thresh_excellent", "thresh_good", "thresh_completed", "thresh_progress", ] as $key) {
|
||||
$val = intval(get_config('local_treestudyplan', "bistate_{$key}"));
|
||||
if ($val >= 0 && $val <= 100) {
|
||||
|
@ -174,13 +173,22 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
|
|||
$totalrequired = 0;
|
||||
$requiredmet = 0;
|
||||
|
||||
$minprogress = ($this->accept_pending_as_submitted) ? completion::PENDING : completion::PROGRESS;
|
||||
$minprogress = ($this->cfg()->accept_pending_as_submitted) ? completion::PENDING : completion::PROGRESS;
|
||||
|
||||
foreach ($completions as $index => $c) {
|
||||
|
||||
$completed += ($c >= completion::COMPLETED) ? 1 : 0;
|
||||
$progress += ($c >= $minprogress) ? 1 : 0;
|
||||
$failed += ($c <= completion::FAILED) ? 1 : 0;
|
||||
|
||||
if (in_array($index,$required)) {
|
||||
// Not using count($required) to prevent nonexistant indices in the required list from messing things up.
|
||||
$totalrequired += 1;
|
||||
if ($c >= completion::COMPLETED) {
|
||||
$requiredmet += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$started = $progress + $failed;
|
||||
$allrequiredmet = ($requiredmet >= $totalrequired);
|
||||
|
@ -193,11 +201,11 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
|
|||
if ($total == 0) {
|
||||
return completion::INCOMPLETE;
|
||||
}
|
||||
if ($fractioncompleted >= $this->thresh_excellent && $allrequiredmet) {
|
||||
if ($fractioncompleted >= $this->cfg()->thresh_excellent && $allrequiredmet) {
|
||||
return completion::EXCELLENT;
|
||||
} else if ($fractioncompleted >= $this->thresh_good && $allrequiredmet) {
|
||||
} else if ($fractioncompleted >= $this->cfg()->thresh_good && $allrequiredmet) {
|
||||
return completion::GOOD;
|
||||
} else if ($fractioncompleted >= $this->thresh_completed && $allrequiredmet) {
|
||||
} else if ($fractioncompleted >= $this->cfg()->thresh_completed && $allrequiredmet) {
|
||||
return completion::COMPLETED;
|
||||
} else if ($started == 0) {
|
||||
return completion::INCOMPLETE;
|
||||
|
@ -238,7 +246,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
|
|||
|
||||
// Combine the aquired completions into one.
|
||||
$result = self::aggregate_binary_goals($completions, $required);
|
||||
if ($this->use_failed && $result == completion::PROGRESS && $coursefinished) {
|
||||
if ($this->cfg()->use_failed && $result == completion::PROGRESS && $coursefinished) {
|
||||
return completion::FAILED;
|
||||
} else {
|
||||
return $result;
|
||||
|
|
|
@ -34,21 +34,7 @@ use \local_treestudyplan\completion;
|
|||
class core_aggregator extends \local_treestudyplan\aggregator {
|
||||
/** @var bool */
|
||||
public const DEPRECATED = false;
|
||||
/** @var array */
|
||||
private $agcfg = null;
|
||||
|
||||
/**
|
||||
* Retrieve or initialize current config object
|
||||
* @return stdClass
|
||||
*/
|
||||
private function cfg() {
|
||||
if (empty($this->agcfg)) {
|
||||
$this->agcfg = (object)[
|
||||
'accept_pending_as_submitted' => false, // Also count ungraded but submitted .
|
||||
];
|
||||
}
|
||||
return $this->agcfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new instance of aggregation method
|
||||
|
@ -64,22 +50,7 @@ class core_aggregator extends \local_treestudyplan\aggregator {
|
|||
* @param string $configstr Aggregation configuration string
|
||||
*/
|
||||
protected function initialize($configstr) {
|
||||
// First initialize with the defaults.
|
||||
foreach (["accept_pending_as_submitted"] as $key) {
|
||||
$this->cfg()->$key = boolval(get_config('local_treestudyplan', "bistate_{$key}"));
|
||||
}
|
||||
|
||||
// Next, decode json.
|
||||
$config = \json_decode($configstr, true);
|
||||
|
||||
if (is_array($config)) {
|
||||
// Copy all valid config settings to this item.
|
||||
foreach (["accept_pending_as_submitted"] as $key) {
|
||||
if (array_key_exists($key, $config)) {
|
||||
$this->cfg()->$key = boolval($config[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,9 +58,7 @@ class core_aggregator extends \local_treestudyplan\aggregator {
|
|||
* @return string Configuration string
|
||||
*/
|
||||
public function config_string() {
|
||||
return json_encode([
|
||||
"accept_pending_as_submitted" => $this->cfg()->accept_pending_as_submitted,
|
||||
]);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,11 +122,7 @@ class core_aggregator extends \local_treestudyplan\aggregator {
|
|||
|
||||
if ($completion->is_enabled() && $completion->is_tracked_user($userid)) {
|
||||
if ($completion->is_course_complete($userid)) {
|
||||
// Now, the trick is to determine what constitutes excellent and good completion....
|
||||
// TODO: Determine excellent and maybe good completion.
|
||||
// Option: Use course end grade to determine that...
|
||||
// Probably needs a config value in the aggregator....
|
||||
|
||||
// Completed is completed
|
||||
return completion::COMPLETED;
|
||||
} else {
|
||||
// Check if the course is over or not, if it is over, display failed.
|
||||
|
|
|
@ -37,12 +37,13 @@ class studentstudyplanservice extends \external_api {
|
|||
* @var string
|
||||
*/
|
||||
const CAP_VIEWOTHER = "local/treestudyplan:viewuserreports";
|
||||
|
||||
/************************
|
||||
* *
|
||||
* list_user_studyplans *
|
||||
* *
|
||||
************************/
|
||||
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function list_user_studyplans
|
||||
*/
|
||||
|
@ -74,57 +75,12 @@ class studentstudyplanservice extends \external_api {
|
|||
foreach ($studyplans as $studyplan) {
|
||||
// Only include studyplans in the context the user has permissions for.
|
||||
if (webservicehelper::has_capabilities(self::CAP_VIEWOTHER, $studyplan->context(), false)) {
|
||||
$list[] = $studyplan->simple_model();
|
||||
$list[] = $studyplan->simple_model($userid);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* get_user_studyplans *
|
||||
* *
|
||||
************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_user_studyplans
|
||||
*/
|
||||
public static function get_user_studyplans_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"userid" => new \external_value(PARAM_INT, 'id of user'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_user_studyplans
|
||||
*/
|
||||
public static function get_user_studyplans_returns() : \external_description {
|
||||
return new \external_multiple_structure(
|
||||
studyplan::user_structure()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full studyplans for a specific user
|
||||
* @param int $userid ID of user to check specific info for
|
||||
* @return array
|
||||
*/
|
||||
public static function get_user_studyplans($userid) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$studyplans = studyplan::find_for_user($userid);
|
||||
|
||||
$map = [];
|
||||
foreach ($studyplans as $studyplan) {
|
||||
// Only include studyplans in the context the user has permissions for.
|
||||
if (webservicehelper::has_capabilities(self::CAP_VIEWOTHER, $studyplan->context(), false)) {
|
||||
$map[] = $studyplan->user_model($userid);
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* get_user_studyplan *
|
||||
|
@ -160,7 +116,49 @@ class studentstudyplanservice extends \external_api {
|
|||
$studyplan = studyplan::find_by_id($studyplanid);
|
||||
webservicehelper::require_capabilities(self::CAP_VIEWOTHER, $studyplan->context());
|
||||
|
||||
if ($studyplan->has_linked_user($userid)) {
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return $studyplan->user_model($userid);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* get_user_page *
|
||||
* *
|
||||
************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_user_page
|
||||
*/
|
||||
public static function get_user_page_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"userid" => new \external_value(PARAM_INT, 'id of user'),
|
||||
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_user_page
|
||||
*/
|
||||
public static function get_user_page_returns() : \external_description {
|
||||
return studyplan::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific studyplan page for a given user
|
||||
* @param int $userid ID of user to check specific info for
|
||||
* @param int $pageid ID of studyplan to view
|
||||
* @return array
|
||||
*/
|
||||
public static function get_user_page($userid, $pageid) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$studyplan = studyplan::find_by_id($pageid);
|
||||
webservicehelper::require_capabilities(self::CAP_VIEWOTHER, $studyplan->context());
|
||||
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return $studyplan->user_model($userid);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -169,35 +167,35 @@ class studentstudyplanservice extends \external_api {
|
|||
|
||||
/****************************
|
||||
* *
|
||||
* get_invited_studyplan *
|
||||
* list_invited_studyplan *
|
||||
* *
|
||||
****************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_invited_studyplan
|
||||
* Parameter description for webservice function list_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_studyplan_parameters() : \external_function_parameters {
|
||||
public static function list_invited_studyplans_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_invited_studyplan
|
||||
* Return value description for webservice function list_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_studyplan_returns() : \external_description {
|
||||
public static function list_invited_studyplans_returns() : \external_description {
|
||||
return new \external_multiple_structure(
|
||||
studyplan::user_structure()
|
||||
studyplan::simple_structure()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get studyplan based on invite key
|
||||
* List available studyplans based on invite key
|
||||
* @param int $invitekey Invitation key
|
||||
* @return array
|
||||
*/
|
||||
public static function get_invited_studyplan($invitekey) {
|
||||
global $CFG, $DB;
|
||||
public static function list_invited_studyplans($invitekey) {
|
||||
global $DB;
|
||||
|
||||
$invite = $DB->get_record_select(
|
||||
"local_treestudyplan_invit",
|
||||
|
@ -214,12 +212,126 @@ class studentstudyplanservice extends \external_api {
|
|||
|
||||
$userid = $invite->user_id;
|
||||
|
||||
$map = [];
|
||||
$list = [];
|
||||
$studyplans = studyplan::find_for_user($userid);
|
||||
foreach ($studyplans as $studyplan) {
|
||||
$map[] = $studyplan->user_model($userid);
|
||||
// Only include studyplans in the context the user has permissions for.
|
||||
if (webservicehelper::has_capabilities(self::CAP_VIEWOTHER, $studyplan->context(), false)) {
|
||||
$list[] = $studyplan->simple_model($userid);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/****************************
|
||||
* *
|
||||
* get_invited_studyplan *
|
||||
* *
|
||||
****************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_studyplan_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
|
||||
"studyplanid" => new \external_value(PARAM_INT, 'studyplan_id'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_studyplan_returns() : \external_description {
|
||||
return studyplan::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get studyplan based on invite key and studyplan id
|
||||
* @param string $invitekey Invitation key
|
||||
* @param int $studyplanid ID of the studyplan to retrieve
|
||||
* @return array
|
||||
*/
|
||||
public static function get_invited_studyplan($invitekey,$studyplanid) {
|
||||
global $DB;
|
||||
|
||||
$invite = $DB->get_record_select(
|
||||
"local_treestudyplan_invit",
|
||||
$DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"),
|
||||
['invitekey' => $invitekey]
|
||||
);
|
||||
|
||||
if (empty($invite)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Validate context now.
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
|
||||
$studyplan = studyplan::find_by_id($studyplanid);
|
||||
$userid = $invite->user_id;
|
||||
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return $studyplan->user_model($userid);
|
||||
} else {
|
||||
throw new \moodle_exception("Invitation's user is not linked to this studyplan");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************
|
||||
* *
|
||||
* get_invited_page *
|
||||
* *
|
||||
****************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_page_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
|
||||
"pageid" => new \external_value(PARAM_INT, 'studyplan page id'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_invited_studyplan
|
||||
*/
|
||||
public static function get_invited_page_returns() : \external_description {
|
||||
return studyplanpage::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get studyplan based on invite key and studyplan id
|
||||
* @param string $invitekey Invitation key
|
||||
* @param int $pageid ID of the studyplan to retrieve
|
||||
* @return array
|
||||
*/
|
||||
public static function get_invited_page($invitekey,$pageid) {
|
||||
global $DB;
|
||||
|
||||
$invite = $DB->get_record_select(
|
||||
"local_treestudyplan_invit",
|
||||
$DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"),
|
||||
['invitekey' => $invitekey]
|
||||
);
|
||||
|
||||
if (empty($invite)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Validate context now.
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
$studyplan = $page->studyplan();
|
||||
$userid = $invite->user_id;
|
||||
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return $page->user_model($userid);
|
||||
} else {
|
||||
throw new \moodle_exception("Invitation's user is not linked to this studyplan");
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
/************************
|
||||
|
@ -255,8 +367,9 @@ class studentstudyplanservice extends \external_api {
|
|||
$list = [];
|
||||
$studyplans = studyplan::find_for_user($userid);
|
||||
foreach ($studyplans as $studyplan) {
|
||||
$list[] = $studyplan->simple_model();
|
||||
$list[] = $studyplan->simple_model($userid);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
@ -271,7 +384,7 @@ class studentstudyplanservice extends \external_api {
|
|||
*/
|
||||
public static function get_own_studyplan_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"id" => new \external_value(PARAM_INT, 'id of specific studyplan to provide', VALUE_DEFAULT),
|
||||
"studyplanid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'),
|
||||
] );
|
||||
}
|
||||
|
||||
|
@ -279,17 +392,15 @@ class studentstudyplanservice extends \external_api {
|
|||
* Return value description for webservice function get_own_studyplan
|
||||
*/
|
||||
public static function get_own_studyplan_returns() : \external_description {
|
||||
return new \external_multiple_structure(
|
||||
studyplan::user_structure()
|
||||
);
|
||||
return studyplan::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all studyplans for current user or a specific one
|
||||
* @param int $id Optional id of specific studyplan
|
||||
* Get a studyplans for the current user
|
||||
* @param int $studyplanid Id of specific studyplan
|
||||
* @return array
|
||||
*/
|
||||
public static function get_own_studyplan($id = null) {
|
||||
public static function get_own_studyplan($studyplanid) {
|
||||
global $USER;
|
||||
|
||||
// Validate this call in the system context.
|
||||
|
@ -297,45 +408,79 @@ class studentstudyplanservice extends \external_api {
|
|||
|
||||
$userid = $USER->id;
|
||||
|
||||
$studyplans = studyplan::find_for_user($userid);
|
||||
$studyplan = studyplan::find_by_id($studyplanid);
|
||||
|
||||
if (isset($id) && $id > 0) {
|
||||
if (isset($studyplans[$id])) {
|
||||
$studyplan = $studyplans[$id];
|
||||
return [$studyplan->user_model($userid)];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return debug::dump($studyplan->user_model($userid));
|
||||
} else {
|
||||
$map = [];
|
||||
foreach ($studyplans as $studyplan) {
|
||||
$map[] = $studyplan->user_model($userid);
|
||||
}
|
||||
return $map;
|
||||
throw new \moodle_exception("You do not have access to this studyplan");
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* get_own_page *
|
||||
* *
|
||||
************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_own_page
|
||||
*/
|
||||
public static function get_own_page_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"pageid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_own_page
|
||||
*/
|
||||
public static function get_own_page_returns() : \external_description {
|
||||
return studyplan::user_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get studyplanpage for current user
|
||||
* @param int $pagid ID of specific studyplan page
|
||||
* @return array
|
||||
*/
|
||||
public static function get_own_page($pageid) {
|
||||
global $USER;
|
||||
|
||||
// Validate this call in the system context.
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
|
||||
$userid = $USER->id;
|
||||
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
$studyplan = $page->studyplan();
|
||||
|
||||
if ($studyplan->exist_for_user($userid)) {
|
||||
return $page->user_model($userid);
|
||||
} else {
|
||||
throw new \moodle_exception("You do not have access to this studyplan page");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************
|
||||
* *
|
||||
* get_teaching_studyplans *
|
||||
* list_teaching_studyplans *
|
||||
* *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_teaching_studyplans
|
||||
* Parameter description for webservice function list_teaching_studyplans
|
||||
*/
|
||||
public static function get_teaching_studyplans_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"id" => new \external_value(PARAM_INT, 'id of specific studyplan to provide', VALUE_DEFAULT),
|
||||
] );
|
||||
public static function list_teaching_studyplans_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_teaching_studyplans
|
||||
* Return value description for webservice function list_teaching_studyplans
|
||||
*/
|
||||
public static function get_teaching_studyplans_returns() : \external_description {
|
||||
public static function list_teaching_studyplans_returns() : \external_description {
|
||||
return new \external_multiple_structure(
|
||||
studyplan::editor_structure()
|
||||
studyplan::simple_structure()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -344,26 +489,101 @@ class studentstudyplanservice extends \external_api {
|
|||
* @param int $id Optional specific id of studyplan
|
||||
* @return array
|
||||
*/
|
||||
public static function get_teaching_studyplans($id = null) {
|
||||
global $CFG, $DB, $USER;
|
||||
public static function list_teaching_studyplans() {
|
||||
global $USER;
|
||||
$userid = $USER->id;
|
||||
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
$studyplans = teachingfinder::list_my_plans();
|
||||
|
||||
if (isset($id) && $id > 0) {
|
||||
if (isset($studyplans[$id])) {
|
||||
$studyplan = $studyplans[$id];
|
||||
return [$studyplan->editor_model($userid)];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
$list = [];
|
||||
foreach ($studyplans as $studyplan) {
|
||||
$list[] = $studyplan->simple_model($userid);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/***************************
|
||||
* *
|
||||
* get_teaching_studyplan *
|
||||
* *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_teaching_studyplan
|
||||
*/
|
||||
public static function get_teaching_studyplan_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"studyplanid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide', VALUE_DEFAULT),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_teaching_studyplan
|
||||
*/
|
||||
public static function get_teaching_studyplan_returns() : \external_description {
|
||||
return studyplan::editor_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all or one studyplan the current user is teaching in
|
||||
* @param int $studyplanid ID of studyplan to retrieve
|
||||
* @return array
|
||||
*/
|
||||
public static function get_teaching_studyplan($studyplanid) {
|
||||
global $USER;
|
||||
$userid = $USER->id;
|
||||
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
$studyplan = studyplan::find_by_id($studyplanid);
|
||||
|
||||
if (teachingfinder::am_teaching_studyplan($studyplan)) {
|
||||
return $studyplan->editor_model();
|
||||
} else {
|
||||
$map = [];
|
||||
foreach ($studyplans as $studyplan) {
|
||||
$map[] = $studyplan->editor_model($userid);
|
||||
}
|
||||
return $map;
|
||||
throw new \moodle_exception("You are not teaching in this studyplan");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************
|
||||
* *
|
||||
* get_teaching_page *
|
||||
* *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* Parameter description for webservice function get_teaching_page
|
||||
*/
|
||||
public static function get_teaching_page_parameters() : \external_function_parameters {
|
||||
return new \external_function_parameters( [
|
||||
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan page to provide', VALUE_DEFAULT),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value description for webservice function get_teaching_page
|
||||
*/
|
||||
public static function get_teaching_page_returns() : \external_description {
|
||||
return studyplanpage::editor_structure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all or one studyplan the current user is teaching in
|
||||
* @param int $studyplanid ID of studyplan to retrieve
|
||||
* @return array
|
||||
*/
|
||||
public static function get_teaching_page($pageid) {
|
||||
global $USER;
|
||||
$userid = $USER->id;
|
||||
|
||||
\external_api::validate_context(\context_system::instance());
|
||||
$page = studyplanpage::find_by_id($pageid);
|
||||
$studyplan = $page->studyplan();
|
||||
|
||||
if (teachingfinder::am_teaching_studyplan($studyplan)) {
|
||||
return $page->editor_model();
|
||||
} else {
|
||||
throw new \moodle_exception("You are not teaching in this studyplan");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ class studyitem {
|
|||
if ($mode == "export") {
|
||||
$model['course'] = $ci->shortname();
|
||||
} else {
|
||||
$model['course'] = $ci->editor_model($this, $this->aggregator->usecorecompletioninfo());
|
||||
$model['course'] = $ci->editor_model($this->aggregator->usecorecompletioninfo());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace local_treestudyplan;
|
|||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/externallib.php');
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
/**
|
||||
* Model class for study plan
|
||||
*/
|
||||
|
@ -159,7 +160,7 @@ class studyplan {
|
|||
* Return description with all file references resolved
|
||||
*/
|
||||
public function description() {
|
||||
$text = file_rewrite_pluginfile_urls(
|
||||
$text = \file_rewrite_pluginfile_urls(
|
||||
// The content of the text stored in the database.
|
||||
$this->r->description,
|
||||
// The pluginfile URL which will serve the request.
|
||||
|
@ -222,6 +223,7 @@ class studyplan {
|
|||
"aggregation_info" => aggregator::basic_structure(),
|
||||
"pages" => new \external_multiple_structure(studyplanpage::simple_structure(), 'pages'),
|
||||
"progress" => new \external_value(PARAM_FLOAT,"fraction of completed modules",VALUE_OPTIONAL),
|
||||
"amteaching" => new \external_value(PARAM_BOOL,"Current user is teaching one or more courses in this studyplan",VALUE_OPTIONAL),
|
||||
], 'Basic studyplan info', $value);
|
||||
}
|
||||
|
||||
|
@ -229,13 +231,14 @@ class studyplan {
|
|||
* Webservice model for basic info
|
||||
* @return array Webservice data model
|
||||
*/
|
||||
public function simple_model() {
|
||||
public function simple_model($userid=null) {
|
||||
global $USER;
|
||||
$pages = [];
|
||||
foreach ($this->pages() as $p) {
|
||||
$pages[] = $p->simple_model();
|
||||
}
|
||||
|
||||
return [
|
||||
$model = [
|
||||
'id' => $this->r->id,
|
||||
'name' => $this->r->name,
|
||||
'shortname' => $this->r->shortname,
|
||||
|
@ -248,9 +251,12 @@ class studyplan {
|
|||
'aggregation_config' => $this->aggregator->config_string(),
|
||||
'aggregation_info' => $this->aggregator->basic_model(),
|
||||
'pages' => $pages,
|
||||
// Next line is for development debugging only.
|
||||
//"progress" => (\rand(0,100) / 100),
|
||||
];
|
||||
if(isset($userid)) {
|
||||
$model["progress"] = $this->scanuserprogress($userid);
|
||||
$model['amteaching'] = teachingfinder::is_teaching_studyplan($this,$userid);
|
||||
}
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -510,13 +516,13 @@ class studyplan {
|
|||
public static function exist_for_user($userid) : bool {
|
||||
global $DB;
|
||||
$count = 0;
|
||||
$sql = "SELECT s.* FROM {local_treestudyplan} s
|
||||
$sql = "SELECT COUNT(s.id) FROM {local_treestudyplan} s
|
||||
INNER JOIN {local_treestudyplan_cohort} j ON j.studyplan_id = s.id
|
||||
INNER JOIN {cohort_members} cm ON j.cohort_id = cm.cohortid
|
||||
WHERE cm.userid = :userid";
|
||||
$count += $DB->count_records_sql($sql, ['userid' => $userid]);
|
||||
|
||||
$sql = "SELECT s.* FROM {local_treestudyplan} s
|
||||
$sql = "SELECT COUNT(s.id) FROM {local_treestudyplan} s
|
||||
INNER JOIN {local_treestudyplan_user} j ON j.studyplan_id = s.id
|
||||
WHERE j.user_id = :userid";
|
||||
$count += $DB->count_records_sql($sql, ['userid' => $userid]);
|
||||
|
@ -624,6 +630,7 @@ class studyplan {
|
|||
}
|
||||
// Now average it out over the amount of pages
|
||||
$progress = $progress / count($pages);
|
||||
return $progress;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace local_treestudyplan;
|
|||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/externallib.php');
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
/**
|
||||
* Studyplan page management class
|
||||
*/
|
||||
|
@ -147,7 +148,7 @@ class studyplanpage {
|
|||
* @return string
|
||||
*/
|
||||
public function description() {
|
||||
$text = file_rewrite_pluginfile_urls(
|
||||
$text = \file_rewrite_pluginfile_urls(
|
||||
// The content of the text stored in the database.
|
||||
$this->r->description,
|
||||
// The pluginfile URL which will serve the request.
|
||||
|
|
|
@ -35,7 +35,8 @@ class teachingfinder {
|
|||
|
||||
|
||||
/**
|
||||
* List all studyplans the vurrent user is teaching
|
||||
* List all studyplans the current user is teaching
|
||||
* (Updates the cache if no results are found the first time)
|
||||
* @return studyplan[] List of studyplans
|
||||
*/
|
||||
public static function list_my_plans() {
|
||||
|
@ -46,7 +47,7 @@ class teachingfinder {
|
|||
if (count($records) == 0) {
|
||||
// Initiate a search if the cache is empty.
|
||||
self::update_teaching_cache($userid);
|
||||
$DB->get_records(self::TABLE, ['teacher_id' => $userid]);
|
||||
$records = $DB->get_records(self::TABLE, ['teacher_id' => $userid]);
|
||||
}
|
||||
$list = [];
|
||||
foreach ($records as $r) {
|
||||
|
@ -55,6 +56,74 @@ class teachingfinder {
|
|||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is teaching in a specific studyplan
|
||||
* (Does not update the cache if results are 0)
|
||||
* @param studyplan $plan Studyplan to check
|
||||
* @return bool If teaching in this plan
|
||||
*/
|
||||
public static function is_teaching_studyplan(studyplan $plan,$userid) {
|
||||
global $DB;
|
||||
$count = $DB->count_records(self::TABLE, ['teacher_id' => $userid, "studyplan_id" => $plan->id()]);
|
||||
return ($count > 0)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is teaching courses in any studyplan
|
||||
* (Does not update the cache if results are 0)
|
||||
* @param studyplan $plan Studyplan to check
|
||||
* @return bool If teaching in this plan
|
||||
*/
|
||||
public static function is_teaching($userid) {
|
||||
global $DB;
|
||||
$count = $DB->count_records(self::TABLE, ['teacher_id' => $userid]);
|
||||
return ($count > 0)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if current user is teaching in a specific studyplan
|
||||
* (Does not update the cache if results are 0)
|
||||
* @param studyplan $plan Studyplan to check
|
||||
* @return bool If teaching in this plan
|
||||
*/
|
||||
public static function am_teaching_studyplan(studyplan $plan) {
|
||||
global $USER;
|
||||
return self::is_teaching_studyplan($plan,$USER->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current user is teaching courses in any studyplan
|
||||
* (Does not update the cache if results are 0)
|
||||
* @param studyplan $plan Studyplan to check
|
||||
* @return bool If teaching in this plan
|
||||
*/
|
||||
public static function am_teaching() {
|
||||
global $USER;
|
||||
return self::is_teaching($USER->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is teaching in a specific course
|
||||
* @param int $courseid ID of the course
|
||||
* @param int $userid ID of the user
|
||||
* @return bool True if teaching in the course
|
||||
*/
|
||||
public static function is_teaching_course($courseid, $userid) {
|
||||
$coursecontext = \context_course::instance($courseid);
|
||||
return is_enrolled($coursecontext, $userid, 'mod/assign:grade');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current user is teaching in a specific course
|
||||
* @param int $courseid ID of the course
|
||||
* @return bool True if teaching in the course
|
||||
*/
|
||||
public static function am_teaching_course($courseid) {
|
||||
global $USER;
|
||||
return self::is_teaching_course($courseid,$USER->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find The active studyplan pages where the specified user is a teacher
|
||||
* (Has the mod/assign::grade capability in one of the linked courses)
|
||||
|
@ -82,8 +151,7 @@ class teachingfinder {
|
|||
|
||||
$linked = false;
|
||||
foreach ($courseids as $cid) {
|
||||
$coursecontext = \context_course::instance($cid);
|
||||
if (is_enrolled($coursecontext, $userid, 'mod/assign:grade')) {
|
||||
if (self::is_teaching_course($cid, $userid)) {
|
||||
$linked = true;
|
||||
break; // No need to search further.
|
||||
}
|
||||
|
|
|
@ -1299,7 +1299,9 @@
|
|||
border-color: #aaa;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-page-edit,
|
||||
.features-treestudyplan .s-studyplan-page-edit {
|
||||
.path-local-treestudyplan .t-tab-extra,
|
||||
.features-treestudyplan .s-studyplan-page-edit,
|
||||
.features-treestudyplan .t-tab-extra {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 0.5em;
|
||||
|
@ -1307,8 +1309,8 @@
|
|||
|
||||
.path-local-treestudyplan .card.s-studyplan-card,
|
||||
.features-treestudyplan .card.s-studyplan-card {
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
min-width: 400px;
|
||||
max-width: 400px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header,
|
||||
|
@ -1376,8 +1378,8 @@
|
|||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-card-info > :last-child,
|
||||
.features-treestudyplan .s-studyplan-card-info > :last-child {
|
||||
.path-local-treestudyplan .s-studyplan-card-info > :last-child:not(:only-child),
|
||||
.features-treestudyplan .s-studyplan-card-info > :last-child:not(:only-child) {
|
||||
margin-top: auto;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-card-progressbar,
|
||||
|
@ -1419,6 +1421,11 @@
|
|||
font-size: 80%;
|
||||
color: var(--gray);
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-details img,
|
||||
.features-treestudyplan .s-studyplan-details img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
|
||||
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
|
||||
|
|
201
db/services.php
201
db/services.php
|
@ -23,35 +23,7 @@
|
|||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$services = [
|
||||
"Competency listing" => [
|
||||
'functions' => [
|
||||
'local_treestudyplan_get_studyplan_map',
|
||||
'local_treestudyplan_get_studyline_map',
|
||||
'local_treestudyplan_add_studyplan',
|
||||
'local_treestudyplan_add_studyline',
|
||||
'local_treestudyplan_edit_studyplan',
|
||||
'local_treestudyplan_edit_studyline',
|
||||
'local_treestudyplan_delete_studyplan',
|
||||
'local_treestudyplan_delete_studyline',
|
||||
'local_treestudyplan_reorder_studylines',
|
||||
'local_treestudyplan_get_studyitem',
|
||||
'local_treestudyplan_add_studyitem',
|
||||
'local_treestudyplan_edit_studyitem',
|
||||
'local_treestudyplan_reorder_studyitems',
|
||||
'local_treestudyplan_delete_studyitem',
|
||||
'local_treestudyplan_connect_studyitems',
|
||||
'local_treestudyplan_disconnect_studyitems',
|
||||
'local_treestudyplan_get_user_studyplan_map',
|
||||
'local_treestudyplan_map_courses',
|
||||
'local_treestudyplan_export_studyplan',
|
||||
'local_treestudyplan_import_studyplan',
|
||||
],
|
||||
'requiredcapability' => 'local/treestudyplan:configure',
|
||||
'shortname' => 'local_treestudyplan_cohorts',
|
||||
'restrictedusers' => 0,
|
||||
'enabled' => 0,
|
||||
'ajax' => true,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
$functions = [
|
||||
|
@ -323,60 +295,6 @@ $functions = [
|
|||
'capabilities' => 'local/treestudyplan:editstudyplan',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_user_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_user_studyplans', // External function name.
|
||||
'description' => 'List user studyplans',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_user_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_user_studyplans', // External function name.
|
||||
'description' => 'Retrieve user studyplan',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_user_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_user_studyplan', // External function name.
|
||||
'description' => 'Retrieve user studyplan',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_invited_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_invited_studyplan', // External function name.
|
||||
'description' => 'Retrieve user studyplan based on invite',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => false,
|
||||
],
|
||||
'local_treestudyplan_list_own_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_own_studyplans', // External function name.
|
||||
'description' => 'List own studyplans',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_own_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_own_studyplan', // External function name.
|
||||
'description' => 'Retrieve own studyplan',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_map_categories' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\courseservice', // Class containing the external function.
|
||||
'methodname' => 'map_categories', // External function name.
|
||||
|
@ -521,15 +439,6 @@ $functions = [
|
|||
'capabilities' => 'local/treestudyplan:editstudyplan',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_teaching_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_teaching_studyplans', // External function name.
|
||||
'description' => 'Get the studyplans I currently teach in',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_accessible_categories' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\courseservice', // Class containing the external function.
|
||||
'methodname' => 'list_accessible_categories', // External function name.
|
||||
|
@ -628,4 +537,112 @@ $functions = [
|
|||
'ajax' => true,
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_user_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_user_studyplans', // External function name.
|
||||
'description' => 'List user studyplans',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_user_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_user_studyplan', // External function name.
|
||||
'description' => 'Retrieve user studyplan',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_user_page' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_user_page', // External function name.
|
||||
'description' => 'Retrieve user studyplan page',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_invited_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_invited_studyplans', // External function name.
|
||||
'description' => 'List studyplans for user from invite',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_invited_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_invited_studyplan', // External function name.
|
||||
'description' => 'Retrieve studyplan for user from invite',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_invited_page' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_invited_page', // External function name.
|
||||
'description' => 'Retrieve studyplan page for user from invite',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_own_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_own_studyplans', // External function name.
|
||||
'description' => 'List studyplans for current user',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_own_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_own_studyplan', // External function name.
|
||||
'description' => 'Retrieve studyplan for current user',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_own_page' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_own_page', // External function name.
|
||||
'description' => 'Retrieve studyplan page for current user',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_list_teaching_studyplans' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'list_teaching_studyplans', // External function name.
|
||||
'description' => 'List studyplans for current user as teacher',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_teaching_studyplan' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_teaching_studyplan', // External function name.
|
||||
'description' => 'Retrieve studyplan for current user as teacher',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
'local_treestudyplan_get_teaching_page' => [ // Web service function name.
|
||||
'classname' => '\local_treestudyplan\studentstudyplanservice', // Class containing the external function.
|
||||
'methodname' => 'get_teaching_page', // External function name.
|
||||
'description' => 'Retrieve studyplan page for current user as teacher',
|
||||
'type' => 'read', // Database rights of the web service function (read, write).
|
||||
'ajax' => true,
|
||||
'capabilities' => '',
|
||||
'loginrequired' => true,
|
||||
],
|
||||
];
|
||||
|
|
|
@ -83,7 +83,7 @@ if (empty($invite)) {
|
|||
</div>
|
||||
</div>
|
||||
<div v-cloak>
|
||||
<r-report v-model="studyplans" :guestmode="true"></r-report>
|
||||
<r-report type="invited" :invitekey="invitekey"></r-report>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ $string["studyplan_idnumber"] = 'ID Number';
|
|||
$string["studyplan_idnumber_ph"] = '';
|
||||
$string["studyplan_description"] = 'Description';
|
||||
$string["studyplan_description_ph"] = '';
|
||||
$string["studyplan_details"] = 'About';
|
||||
$string["studyplan_slots"] = 'Number of periods in plan';
|
||||
$string["studyplan_startdate"] = 'Start date of plan';
|
||||
$string["studyplan_enddate"] = 'End date of plan';
|
||||
|
@ -208,8 +209,12 @@ $string["grade_points"] = 'Maximum grade points';
|
|||
|
||||
$string["view_feedback"] = 'View feedback';
|
||||
$string["coursetiming_past"] = "Past course";
|
||||
$string["coursetiming_present"] = "Active course";
|
||||
$string["coursetiming_present"] = "Current course";
|
||||
$string["coursetiming_future"] = "Upcoming course";
|
||||
$string["studyplan_past"] = "Past study plans";
|
||||
$string["studyplan_present"] = "Current study plans";
|
||||
$string["studyplan_future"] = "Upcoming study plans";
|
||||
|
||||
|
||||
$string["link_myreport"] = "My study plan";
|
||||
$string["link_viewplan"] = "Study plans";
|
||||
|
|
|
@ -127,6 +127,7 @@ $string["studyplan_shortname_ph"] = '';
|
|||
$string["studyplan_idnumber"] = 'Opleidings-ID';
|
||||
$string["studyplan_idnumber_ph"] = '';
|
||||
$string["studyplan_description"] = 'Beschrijving';
|
||||
$string["studyplan_details"] = 'Meer info';
|
||||
$string["studyplan_description_ph"] = '';
|
||||
$string["studyplan_slots"] = 'Aantal periodes in studieplan';
|
||||
$string["studyplan_startdate"] = 'Startdatum';
|
||||
|
@ -208,6 +209,10 @@ $string["coursetiming_past"] = "Eerdere cursus";
|
|||
$string["coursetiming_present"] = "Actieve cursus";
|
||||
$string["coursetiming_future"] = "Toekomstige cursus";
|
||||
|
||||
$string["studyplan_past"] = "Eerdere studieplannen";
|
||||
$string["studyplan_present"] = "Actieve studieplannen";
|
||||
$string["studyplan_future"] = "Toekomstige studieplannen";
|
||||
|
||||
$string["link_myreport"] = "Mijn studieplan";
|
||||
$string["link_viewplan"] = "Studieplannen";
|
||||
$string["link_editplan"] = "Studieplannen beheren";
|
||||
|
|
21
myreport.php
21
myreport.php
|
@ -25,6 +25,8 @@ require_once("../../config.php");
|
|||
require_once($CFG->libdir.'/weblib.php');
|
||||
|
||||
use local_treestudyplan;
|
||||
use local_treestudyplan\studyplan;
|
||||
use local_treestudyplan\teachingfinder;
|
||||
|
||||
$systemcontext = context_system::instance();
|
||||
|
||||
|
@ -34,9 +36,11 @@ require_login();
|
|||
$PAGE->set_pagelayout('base');
|
||||
$PAGE->set_context($systemcontext);
|
||||
|
||||
$teachermode = has_capability("local/treestudyplan:viewuserreports", $systemcontext);
|
||||
//$teachermode = has_capability("local/treestudyplan:viewuserreports", $systemcontext);
|
||||
$am_teaching = teachingfinder::is_teaching($USER->id);
|
||||
$have_plans = studyplan::exist_for_user($USER->id);
|
||||
|
||||
if ($teachermode) {
|
||||
if ($am_teaching) {
|
||||
$PAGE->set_title(get_string('myreport_teachermode', 'local_treestudyplan'));
|
||||
$PAGE->set_heading(get_string('myreport_teachermode', 'local_treestudyplan'));
|
||||
} else {
|
||||
|
@ -49,7 +53,7 @@ $PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/boot
|
|||
if ($CFG->debugdeveloper) {
|
||||
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css'));
|
||||
}
|
||||
$PAGE->requires->js_call_amd('local_treestudyplan/page-myreport', 'init', [$teachermode ? 'teaching' : 'myreport']);
|
||||
$PAGE->requires->js_call_amd('local_treestudyplan/page-myreport', 'init', [$am_teaching ? 'teaching' : 'own']);
|
||||
|
||||
/**
|
||||
* Shortcut function to provide translations
|
||||
|
@ -67,9 +71,9 @@ print $OUTPUT->header();
|
|||
|
||||
print '<div class="m-buttonbar" style="margin-bottom: 1em; text-align: right;">';
|
||||
|
||||
if (!$teachermode) {
|
||||
if (!$am_teaching) {
|
||||
print '<a class="btn btn-primary" href="invitations.php" id="manage_invites">';
|
||||
print '<i class="fa fa-share"></i>'.t('manage_invites').'</a>';
|
||||
print ' <i class="fa fa-share"></i> '.t('manage_invites').'</a>';
|
||||
}
|
||||
|
||||
print "</div>";
|
||||
|
@ -80,7 +84,12 @@ print " <span class='sr-only'>Loading...</span>";
|
|||
print " </div>";
|
||||
print " </div>";
|
||||
print " <div v-cloak>";
|
||||
print " <r-report v-model='studyplans' " . ($teachermode ? "teachermode" : "")." ></r-report>";
|
||||
if ($am_teaching) {
|
||||
print " <r-report type='teaching' teachermode ></r-report>";
|
||||
} else {
|
||||
print " <r-report type='own' ></r-report>";
|
||||
|
||||
}
|
||||
print " </div>";
|
||||
print "</div>";
|
||||
|
||||
|
|
|
@ -1112,7 +1112,8 @@
|
|||
border-color: #aaa;
|
||||
}
|
||||
|
||||
.s-studyplan-page-edit {
|
||||
.s-studyplan-page-edit,
|
||||
.t-tab-extra {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 0.5em;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
.path-local-treestudyplan, .features-treestudyplan {
|
||||
.card.s-studyplan-card {
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
min-width: 400px;
|
||||
max-width: 400px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,8 @@
|
|||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
gap: 5px;
|
||||
|
||||
|
||||
}
|
||||
.s-studyplan-card-titlebuttons {
|
||||
margin-left: auto;
|
||||
|
@ -68,7 +70,7 @@
|
|||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
> :last-child {
|
||||
> :last-child:not(:only-child) {
|
||||
margin-top: auto;
|
||||
}
|
||||
}
|
||||
|
@ -109,5 +111,12 @@
|
|||
font-size: 80%;
|
||||
color: var(--gray);
|
||||
}
|
||||
.s-studyplan-details {
|
||||
img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
17
styles.css
17
styles.css
|
@ -1299,7 +1299,9 @@
|
|||
border-color: #aaa;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-page-edit,
|
||||
.features-treestudyplan .s-studyplan-page-edit {
|
||||
.path-local-treestudyplan .t-tab-extra,
|
||||
.features-treestudyplan .s-studyplan-page-edit,
|
||||
.features-treestudyplan .t-tab-extra {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 0.5em;
|
||||
|
@ -1307,8 +1309,8 @@
|
|||
|
||||
.path-local-treestudyplan .card.s-studyplan-card,
|
||||
.features-treestudyplan .card.s-studyplan-card {
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
min-width: 400px;
|
||||
max-width: 400px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header,
|
||||
|
@ -1376,8 +1378,8 @@
|
|||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-card-info > :last-child,
|
||||
.features-treestudyplan .s-studyplan-card-info > :last-child {
|
||||
.path-local-treestudyplan .s-studyplan-card-info > :last-child:not(:only-child),
|
||||
.features-treestudyplan .s-studyplan-card-info > :last-child:not(:only-child) {
|
||||
margin-top: auto;
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-card-progressbar,
|
||||
|
@ -1419,6 +1421,11 @@
|
|||
font-size: 80%;
|
||||
color: var(--gray);
|
||||
}
|
||||
.path-local-treestudyplan .s-studyplan-details img,
|
||||
.features-treestudyplan .s-studyplan-details img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
.path-local-treestudyplan .b-modal-justify-footer-between .modal-footer,
|
||||
.features-treestudyplan .b-modal-justify-footer-between .modal-footer {
|
||||
|
|
|
@ -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 = 2023111001; // YYYYMMDDHH (year, month, day, iteration).
|
||||
$plugin->version = 2023111202; // YYYYMMDDHH (year, month, day, iteration).
|
||||
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
|
||||
|
||||
$plugin->release = "1.1.0-b";
|
||||
|
|
|
@ -122,8 +122,13 @@ print $OUTPUT->header();
|
|||
:value='studyplan.id'
|
||||
>{{ studyplan.name }}</b-form-select-option>
|
||||
</b-form-select>
|
||||
<b-button v-if="activestudyplan" variant='primary' v-b-toggle.toolbox-sidebar
|
||||
<s-studyplan-details
|
||||
v-model="displayedstudyplan"
|
||||
v-if="displayedstudyplan && displayedstudyplan.description"
|
||||
></s-studyplan-details>
|
||||
<b-button class="ml-1" v-if="activestudyplan" variant='primary' v-b-toggle.toolbox-sidebar
|
||||
><?php t('selectstudent_btn') ?></b-button>
|
||||
|
||||
</div>
|
||||
<div class='t-studyplan-container'>
|
||||
<h2 v-if='displayedstudyplan&& selectedstudent'
|
||||
|
|
Loading…
Reference in New Issue
Block a user