Polished up my report view

This commit is contained in:
PMKuipers 2023-11-13 22:18:28 +01:00
parent a208d0023a
commit 4a97078405
17 changed files with 114 additions and 55 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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));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}}})); 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"})}function studyplanDates(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}}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=studyplanDates,_exports.studyplanPageTiming=function(page){const now=(new Date).getTime(),start=new Date(page.startdate),end=page.enddate?new Date(page.enddate):null;return start<now?end&&now>end?"past":"present":"future"},_exports.studyplanTiming=function(plan){const now=(new Date).getTime(),dates=studyplanDates(plan);return dates.start<now?dates.end&&now>dates.end?"past":"present":"future"}}));
//# sourceMappingURL=date-helper.min.js.map //# sourceMappingURL=date-helper.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -14,6 +14,7 @@ import Vue from './vue/vue';
import Debugger from './util/debugger'; import Debugger from './util/debugger';
import {load_strings} from './util/string-helper'; import {load_strings} from './util/string-helper';
import {ProcessStudyplan} from './studyplan-processor'; import {ProcessStudyplan} from './studyplan-processor';
import {studyplanTiming} from './util/date-helper';
import RVComponents from './report-viewer-components'; import RVComponents from './report-viewer-components';
Vue.use(RVComponents); Vue.use(RVComponents);
@ -72,8 +73,8 @@ export function init(contextid,categoryid) {
}])[0].done(function(response){ }])[0].done(function(response){
const timingval = { present: 0, past: 1, future: 2}; const timingval = { present: 0, past: 1, future: 2};
response.sort((a,b) => { response.sort((a,b) => {
const timinga = TSComponents.studyplanTiming(a); const timinga = studyplanTiming(a);
const timingb = TSComponents.studyplanTiming(b); const timingb = studyplanTiming(b);
const t = timingval[timinga] - timingval[timingb]; const t = timingval[timinga] - timingval[timingb];
if(t == 0){ if(t == 0){

View File

@ -9,7 +9,7 @@
import {SimpleLine} from './simpleline/simpleline'; import {SimpleLine} from './simpleline/simpleline';
import {get_strings} from 'core/str'; import {get_strings} from 'core/str';
import {load_strings} from './util/string-helper'; import {load_strings} from './util/string-helper';
import {format_date} from './util/date-helper'; import {format_date,studyplanPageTiming,studyplanTiming} from './util/date-helper';
import {call} from 'core/ajax'; import {call} from 'core/ajax';
import notification from 'core/notification'; import notification from 'core/notification';
import {svgarcpath} from './util/svgarc'; import {svgarcpath} from './util/svgarc';
@ -328,18 +328,16 @@ export default {
methodname: `local_treestudyplan_list_${this.verified_type}_studyplans`, methodname: `local_treestudyplan_list_${this.verified_type}_studyplans`,
args: this.call_args(), args: this.call_args(),
}])[0].done(function(response){ }])[0].done(function(response){
debug.info("Studyplans:",response);
const plans = { future: [], present: [], past: [], }; const plans = { future: [], present: [], past: [], };
for (const ix in response) { for (const ix in response) {
const plan = response[ix]; const plan = response[ix];
const timing = TSComponents.studyplanTiming(plan); const timing = studyplanTiming(plan);
plans[timing].push(plan); plans[timing].push(plan);
} }
for (const ix in plans) { for (const ix in plans) {
debug.info(ix, plans[ix]);
plans[ix].sort((a,b) => { plans[ix].sort((a,b) => {
const t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime(); const t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime();
if (t == 0) { if (t == 0) {
@ -378,7 +376,6 @@ export default {
studyplanid: plan.id, studyplanid: plan.id,
}), }),
}])[0].done(function(response){ }])[0].done(function(response){
debug.info("Detailed studyplan:",response);
self.selectedstudyplan = ProcessStudyplan(response); self.selectedstudyplan = ProcessStudyplan(response);
self.loadingstudyplan = false; self.loadingstudyplan = false;
}).fail(notification.exception); }).fail(notification.exception);
@ -449,7 +446,7 @@ export default {
}, },
data() { data() {
return { return {
selectedpageindex: 0, selectedpageindex: -1,
text: strings.pageinfo, text: strings.pageinfo,
}; };
}, },
@ -458,6 +455,23 @@ export default {
selectedpage() { selectedpage() {
return this.value.pages[this.selectedpageindex]; return this.value.pages[this.selectedpageindex];
}, },
startpageindex() {
let startpageindex = 0;
let firststart = null;
for(const ix in this.value.pages) {
const page = this.value.pages[ix];
debug.info(`Checking page ${ix} - timing ${studyplanPageTiming(page)}`,page);
if(studyplanPageTiming(page) == "present") {
debug.info(`Found page nr ${ix} to be present`);
const s = new Date(page.startdate);
if( (!firststart) || firststart > s) {
startpageindex = ix;
firststart = s;
}
}
}
return startpageindex;
}
}, },
methods: { methods: {
pageduration(page){ pageduration(page){
@ -525,15 +539,16 @@ export default {
selectedpageChanged(newTabIndex,prevTabIndex) { selectedpageChanged(newTabIndex,prevTabIndex) {
ItemEventBus.$emit('redrawLines', null); ItemEventBus.$emit('redrawLines', null);
scrollCurrentIntoView(this.value.id); scrollCurrentIntoView(this.selectedpage.id);
} }
}, },
mounted() { mounted() {
scrollCurrentIntoView(this.value.id); // scrollCurrentIntoView(this.selectedpage.id);
this.$root.$emit('redrawLines'); this.$root.$emit('redrawLines');
}, },
updated() { updated() {
scrollCurrentIntoView(this.value.id);
scrollCurrentIntoView(this.selectedpage.id);
ItemEventBus.$emit('lineHeightChange', null); ItemEventBus.$emit('lineHeightChange', null);
this.$root.$emit('redrawLines'); this.$root.$emit('redrawLines');
ItemEventBus.$emit('redrawLines'); ItemEventBus.$emit('redrawLines');
@ -546,8 +561,8 @@ export default {
@activate-tab='selectedpageChanged' @activate-tab='selectedpageChanged'
content-class="mt-1"> content-class="mt-1">
<b-tab <b-tab
v-for="(page,pageindex) in value.pages" v-for="(page,pageindex) in value.pages"
:active="(pageindex == startpageindex)"
:key="page.id" :key="page.id"
:title-item-class="'s-studyplanpage-tab '+ page.timing" :title-item-class="'s-studyplanpage-tab '+ page.timing"
><template #title> ><template #title>

View File

@ -5,24 +5,9 @@
// Put this file in path/to/plugin/amd/src // Put this file in path/to/plugin/amd/src
import {load_strings} from './util/string-helper'; import {load_strings} from './util/string-helper';
import {format_date, studyplanDates} from './util/date-helper'; import {format_date, studyplanDates, studyplanTiming} from './util/date-helper';
export default { export default {
studyplanTiming(plan) {
const now = new Date().getTime();
const dates = studyplanDates(plan);
if(dates.start < now){
if( dates.end && now > dates.end) {
return 'past';
} else {
return 'present';
}
} else {
return 'future';
}
},
install(Vue/*,options*/){ install(Vue/*,options*/){
let strings = load_strings({ let strings = load_strings({
@ -57,18 +42,7 @@ export default {
}, },
computed: { computed: {
timing(){ timing(){
const now = new Date().getTime(); return studyplanTiming(this.value);
const startdate = new Date(this.value.pages[0].startdate).getTime();
const enddate = new Date(this.value.pages[0].enddate).getTime();
let timing = 'future';
if(startdate < now){
if(this.value.pages[0].enddate && now > enddate) {
timing = 'past';
} else {
timing = 'present';
}
}
return timing;
}, },
dates(){ dates(){
const dates = studyplanDates(this.value); const dates = studyplanDates(this.value);
@ -115,7 +89,7 @@ export default {
<div class='s-studyplan-card-info'> <div class='s-studyplan-card-info'>
<div class='s-studyplan-card-titlebar'> <div class='s-studyplan-card-titlebar'>
<b-card-title> <b-card-title>
<a v-if='open' href='#' @click.prevent='onOpenClick($event)'>{{value.name}}</a> <a class='title' v-if='open' href='#' @click.prevent='onOpenClick($event)'>{{value.name}}</a>
<template v-else>{{value.name}}</template> <template v-else>{{value.name}}</template>
</b-card-title> </b-card-title>
<div class='s-studyplan-card-titleslot'><slot name='title'></slot></div> <div class='s-studyplan-card-titleslot'><slot name='title'></slot></div>

View File

@ -125,3 +125,44 @@ export function studyplanDates(plan) {
end: (openEnded)?null:latestEnd, end: (openEnded)?null:latestEnd,
}; };
} }
/**
* Determine past/present/future for a studyplan
* @param {*} plan
* @returns {string} one of 'past', 'present', 'future'
*/
export function studyplanTiming(plan) {
const now = new Date().getTime();
const dates = studyplanDates(plan);
if(dates.start < now){
if( dates.end && now > dates.end) {
return 'past';
} else {
return 'present';
}
} else {
return 'future';
}
}
/**
* Determine past/present/future for a studyplan
* @param {*} page
* @returns {string} one of 'past', 'present', 'future'
*/
export function studyplanPageTiming(page) {
const now = new Date().getTime();
const start = new Date(page.startdate);
const end = (page.enddate)?(new Date(page.enddate)):null;
if(start < now){
if( end && now > end) {
return 'past';
} else {
return 'present';
}
} else {
return 'future';
}
}

View File

@ -215,11 +215,8 @@ class studentstudyplanservice extends \external_api {
$list = []; $list = [];
$studyplans = studyplan::find_for_user($userid); $studyplans = studyplan::find_for_user($userid);
foreach ($studyplans as $studyplan) { 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($userid); $list[] = $studyplan->simple_model($userid);
} }
}
return $list; return $list;
} }

View File

@ -1313,6 +1313,16 @@
max-width: 400px; max-width: 400px;
margin-bottom: 1em; margin-bottom: 1em;
} }
.path-local-treestudyplan.path-local-treestudyplan-edit .card.s-studyplan-card,
.features-treestudyplan.path-local-treestudyplan-edit .card.s-studyplan-card {
min-width: 450px;
max-width: 450px;
}
.path-local-treestudyplan .card.s-studyplan-card.card-body,
.features-treestudyplan .card.s-studyplan-card.card-body {
padding: 0.75rem;
padding-bottom: 0.5rem;
}
.path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header, .path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header,
.features-treestudyplan .card.s-studyplan-card.timing-past .card-header { .features-treestudyplan .card.s-studyplan-card.timing-past .card-header {
background-color: var(--past); background-color: var(--past);
@ -1329,6 +1339,7 @@
.features-treestudyplan .s-studyplan-card-title-buttons { .features-treestudyplan .s-studyplan-card-title-buttons {
font-size: 16px; font-size: 16px;
float: right; float: right;
white-space: nowrap;
} }
.path-local-treestudyplan .s-studyplan-card-title-buttons > *, .path-local-treestudyplan .s-studyplan-card-title-buttons > *,
.features-treestudyplan .s-studyplan-card-title-buttons > * { .features-treestudyplan .s-studyplan-card-title-buttons > * {

View File

@ -166,7 +166,6 @@ print $OUTPUT->header();
> >
<template #title> <template #title>
<span class='s-studyplan-card-title-buttons'> <span class='s-studyplan-card-title-buttons'>
<a href='#' @click.prevent="export_plan(studyplan)" ><i class='fa fa-download'></i></a>
<t-studyplan-edit v-model="studyplans[planindex]" @moved="movedStudyplan"></t-studyplan-edit> <t-studyplan-edit v-model="studyplans[planindex]" @moved="movedStudyplan"></t-studyplan-edit>
<t-studyplan-associate v-model="studyplans[planindex]"></t-studyplan-associate> <t-studyplan-associate v-model="studyplans[planindex]"></t-studyplan-associate>
</span> </span>

View File

@ -1,10 +1,20 @@
.path-local-treestudyplan, .features-treestudyplan { .path-local-treestudyplan, .features-treestudyplan {
.card.s-studyplan-card { .card.s-studyplan-card {
min-width: 400px; min-width: 400px;
max-width: 400px; max-width: 400px;
margin-bottom: 1em; margin-bottom: 1em;
} }
&.path-local-treestudyplan-edit .card.s-studyplan-card{
min-width: 450px;
max-width: 450px;
}
.card.s-studyplan-card.card-body {
padding: 0.75rem;
padding-bottom: 0.5rem;
}
.card.s-studyplan-card.timing-past .card-header { .card.s-studyplan-card.timing-past .card-header {
background-color: var(--past); background-color: var(--past);
@ -19,6 +29,7 @@
.s-studyplan-card-title-buttons { .s-studyplan-card-title-buttons {
font-size: 16px /*12pt*/; font-size: 16px /*12pt*/;
float: right; float: right;
white-space: nowrap;
} }
.s-studyplan-card-title-buttons > * { .s-studyplan-card-title-buttons > * {
margin-left: 0.2em; margin-left: 0.2em;
@ -58,7 +69,6 @@
justify-content: space-between; justify-content: space-between;
gap: 5px; gap: 5px;
} }
.s-studyplan-card-titlebuttons { .s-studyplan-card-titlebuttons {
margin-left: auto; margin-left: auto;

View File

@ -1313,6 +1313,16 @@
max-width: 400px; max-width: 400px;
margin-bottom: 1em; margin-bottom: 1em;
} }
.path-local-treestudyplan.path-local-treestudyplan-edit .card.s-studyplan-card,
.features-treestudyplan.path-local-treestudyplan-edit .card.s-studyplan-card {
min-width: 450px;
max-width: 450px;
}
.path-local-treestudyplan .card.s-studyplan-card.card-body,
.features-treestudyplan .card.s-studyplan-card.card-body {
padding: 0.75rem;
padding-bottom: 0.5rem;
}
.path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header, .path-local-treestudyplan .card.s-studyplan-card.timing-past .card-header,
.features-treestudyplan .card.s-studyplan-card.timing-past .card-header { .features-treestudyplan .card.s-studyplan-card.timing-past .card-header {
background-color: var(--past); background-color: var(--past);
@ -1329,6 +1339,7 @@
.features-treestudyplan .s-studyplan-card-title-buttons { .features-treestudyplan .s-studyplan-card-title-buttons {
font-size: 16px; font-size: 16px;
float: right; float: right;
white-space: nowrap;
} }
.path-local-treestudyplan .s-studyplan-card-title-buttons > *, .path-local-treestudyplan .s-studyplan-card-title-buttons > *,
.features-treestudyplan .s-studyplan-card-title-buttons > * { .features-treestudyplan .s-studyplan-card-title-buttons > * {