Improved UX on date selector. Cannot select invalid dates anymore
This commit is contained in:
parent
db8b9c9a02
commit
7431943747
15 changed files with 141 additions and 76 deletions
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-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/treestudyplan-components.min.js
vendored
2
amd/build/treestudyplan-components.min.js
vendored
|
@ -1,3 +1,3 @@
|
||||||
define("local_treestudyplan/treestudyplan-components",["exports","./util/string-helper"],(function(_exports,_stringHelper){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var _default={studyplanTiming:function(a){var now=(new Date).getTime(),timing="future";return new Date(a.startdate).getTime()<now&&(timing=a.enddate&&now>new Date(a.enddate).getTime()?"past":"present"),timing},install:function(Vue){var strings=(0,_stringHelper.load_strings)({studyplancard:{open:"open",noenddate:"noenddate",idnumber:"studyplan_idnumber"}}),ItemEventBus=new Vue;Vue.component("s-studyplan-card",{props:{value:{type:Object},open:{type:Boolean}},data:function(){return{text:strings.studyplancard}},computed:{timing:function(){var now=(new Date).getTime(),startdate=new Date(this.value.pages[0].startdate).getTime(),enddate=new Date(this.value.pages[0].enddate).getTime(),timing="future";return startdate<now&&(timing=this.value.pages[0].enddate&&now>enddate?"past":"present"),timing},startdate:function(){return(0,_stringHelper.format_date)(this.value.pages[0].startdate)},enddate:function(){return this.value.pages[0].enddate?(0,_stringHelper.format_date)(this.value.pages[0].enddate):this.text.noenddate}},methods:{onOpenClick:function(e){this.$emit("open",e)}},template:"\n <b-card \n :class=\"'s-studyplan-card timing-' + timing\"\n >\n <template #header></template>\n <b-card-title>\n <a v-if='open' href='#' @click.prevent='onOpenClick($event)'>{{value.name}}</a>\n <template v-else>{{value.name}}</template>\n <slot name='title'></slot>\n </b-card-title>\n <div class='s-studyplan-card-idnumber' v-if='value.idnumber'><i>{{ text.idnumber}}:</i> {{ value.idnumber }}</div>\n <div class='s-studyplan-card-description' v-if='value.description'>{{ value.description }}</div>\n <slot></slot>\n <template #footer>\n <span :class=\"'t-timing-'+timing\" v-html=\"startdate + ' - '+ enddate\"></span>\n <span class=\"s-studyplan-card-buttons\">\n <slot name='footer'></slot>\n <b-button style=\"float:right;\" v-if='open' variant='primary' \n @click.prevent='onOpenClick($event)'>{{ text.open }}</b-button>\n </span>\n </template>\n </b-card>\n "}),Vue.component("s-studyline-header-heading",{props:{},data:function(){return{layerHeights:{}}},created:function(){ItemEventBus.$on("headerHeightChange",this.onHeaderHeightChange)},computed:{},methods:{onHeaderHeightChange:function(newheight){this.$refs.main&&(this.$refs.main.style.height="".concat(newheight,"px"))}},template:'\n <div class="s-studyline-header-heading" ref="main"></div>\n '}),Vue.component("s-studyline-header-period",{props:{value:{type:Object}},mounted:function(){var self=this;1==self.value.period&&(self.resizeListener=new ResizeObserver((function(){if(self.$refs.main){var size=self.$refs.main.getBoundingClientRect();ItemEventBus.$emit("headerHeightChange",size.height)}})).observe(self.$refs.main))},unmounted:function(){this.resizeListener&&this.resizeListener.disconnect()},computed:{startdate:function(){return(0,_stringHelper.format_date)(this.value.startdate)},enddate:function(){return(0,_stringHelper.format_date)(this.value.enddate)},current:function(){if(this.value&&this.value.startdate&&this.value.enddate){var now=new Date,pstart=new Date(this.value.startdate),pend=new Date(this.value.enddate);return now>=pstart&&now<pend}return!1}},data:function(){return{}},template:'\n <div :class="\'s-studyline-header-period \' + (current?\'current \':\' \')" ref="main"\n ><p><abbr :id="\'s-period-\'+value.id" :title="value.fullname">{{ value.shortname }}</abbr>\n <b-tooltip\n :target="\'s-period-\'+value.id" triggers="hover"\n >{{ value.fullname }}<br>\n <span class="s-studyline-header-period-datespan">\n <span class="date">{{ startdate }}</span> - <span class="date">{{ enddate }}</span>\n </span>\n </b-tooltip>\n <slot></slot\n ><p class="s-studyline-header-period-datespan small">\n <span class="date">{{ startdate }}</span> - <span class="date">{{ enddate }}</span>\n </p>\n </div>\n '})}};return _exports.default=_default,_exports.default}));
|
define("local_treestudyplan/treestudyplan-components",["exports","./util/string-helper","./util/date-helper"],(function(_exports,_stringHelper,_dateHelper){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var _default={studyplanTiming:function(a){var now=(new Date).getTime(),timing="future";return new Date(a.startdate).getTime()<now&&(timing=a.enddate&&now>new Date(a.enddate).getTime()?"past":"present"),timing},install:function(Vue){var strings=(0,_stringHelper.load_strings)({studyplancard:{open:"open",noenddate:"noenddate",idnumber:"studyplan_idnumber"}}),ItemEventBus=new Vue;Vue.component("s-studyplan-card",{props:{value:{type:Object},open:{type:Boolean}},data:function(){return{text:strings.studyplancard}},computed:{timing:function(){var now=(new Date).getTime(),startdate=new Date(this.value.pages[0].startdate).getTime(),enddate=new Date(this.value.pages[0].enddate).getTime(),timing="future";return startdate<now&&(timing=this.value.pages[0].enddate&&now>enddate?"past":"present"),timing},startdate:function(){return(0,_dateHelper.format_date)(this.value.pages[0].startdate)},enddate:function(){return this.value.pages[0].enddate?(0,_dateHelper.format_date)(this.value.pages[0].enddate):this.text.noenddate}},methods:{onOpenClick:function(e){this.$emit("open",e)}},template:"\n <b-card \n :class=\"'s-studyplan-card timing-' + timing\"\n >\n <template #header></template>\n <b-card-title>\n <a v-if='open' href='#' @click.prevent='onOpenClick($event)'>{{value.name}}</a>\n <template v-else>{{value.name}}</template>\n <slot name='title'></slot>\n </b-card-title>\n <div class='s-studyplan-card-idnumber' v-if='value.idnumber'><i>{{ text.idnumber}}:</i> {{ value.idnumber }}</div>\n <div class='s-studyplan-card-description' v-if='value.description'>{{ value.description }}</div>\n <slot></slot>\n <template #footer>\n <span :class=\"'t-timing-'+timing\" v-html=\"startdate + ' - '+ enddate\"></span>\n <span class=\"s-studyplan-card-buttons\">\n <slot name='footer'></slot>\n <b-button style=\"float:right;\" v-if='open' variant='primary' \n @click.prevent='onOpenClick($event)'>{{ text.open }}</b-button>\n </span>\n </template>\n </b-card>\n "}),Vue.component("s-studyline-header-heading",{props:{},data:function(){return{layerHeights:{}}},created:function(){ItemEventBus.$on("headerHeightChange",this.onHeaderHeightChange)},computed:{},methods:{onHeaderHeightChange:function(newheight){this.$refs.main&&(this.$refs.main.style.height="".concat(newheight,"px"))}},template:'\n <div class="s-studyline-header-heading" ref="main"></div>\n '}),Vue.component("s-studyline-header-period",{props:{value:{type:Object}},mounted:function(){var self=this;1==self.value.period&&(self.resizeListener=new ResizeObserver((function(){if(self.$refs.main){var size=self.$refs.main.getBoundingClientRect();ItemEventBus.$emit("headerHeightChange",size.height)}})).observe(self.$refs.main))},unmounted:function(){this.resizeListener&&this.resizeListener.disconnect()},computed:{startdate:function(){return(0,_dateHelper.format_date)(this.value.startdate)},enddate:function(){return(0,_dateHelper.format_date)(this.value.enddate)},current:function(){if(this.value&&this.value.startdate&&this.value.enddate){var now=new Date,pstart=new Date(this.value.startdate),pend=new Date(this.value.enddate);return now>=pstart&&now<pend}return!1}},data:function(){return{}},template:'\n <div :class="\'s-studyline-header-period \' + (current?\'current \':\' \')" ref="main"\n ><p><abbr :id="\'s-period-\'+value.id" :title="value.fullname">{{ value.shortname }}</abbr>\n <b-tooltip\n :target="\'s-period-\'+value.id" triggers="hover"\n >{{ value.fullname }}<br>\n <span class="s-studyline-header-period-datespan">\n <span class="date">{{ startdate }}</span> - <span class="date">{{ enddate }}</span>\n </span>\n </b-tooltip>\n <slot></slot\n ><p class="s-studyline-header-period-datespan small">\n <span class="date">{{ startdate }}</span> - <span class="date">{{ enddate }}</span>\n </p>\n </div>\n '})}};return _exports.default=_default,_exports.default}));
|
||||||
|
|
||||||
//# sourceMappingURL=treestudyplan-components.min.js.map
|
//# sourceMappingURL=treestudyplan-components.min.js.map
|
File diff suppressed because one or more lines are too long
3
amd/build/util/date-helper.min.js
vendored
Normal file
3
amd/build/util/date-helper.min.js
vendored
Normal file
|
@ -0,0 +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}));
|
||||||
|
|
||||||
|
//# sourceMappingURL=date-helper.min.js.map
|
1
amd/build/util/date-helper.min.js.map
Normal file
1
amd/build/util/date-helper.min.js.map
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"date-helper.min.js","sources":["../../src/util/date-helper.js"],"sourcesContent":["/**\n * Format a date according to localized custom\n * @param {Date|string} d The date to convert\n * @param {boolean} short Short format (default false)\n * @returns {string}\n */\nexport function format_date(d,short){\n if(!(d instanceof Date)){\n d = new Date(d);\n }\n\n let monthformat = \"short\";\n if(short){\n monthformat = \"numeric\";\n }\n return d.toLocaleDateString(document.documentElement.lang,{\n year: 'numeric', month: monthformat, day: 'numeric'\n });\n}\n\n/**\n * Provides standardized information about the period between two dates\n * As\n * @param {Date|string} first First day of the span\n * @param {Date|string} last Last day of the span\n * @returns {Object} Object containing formatted start and end dates and span information\n */\nexport function datespaninfo(first,last){\n if(!(first instanceof Date)){ first = new Date(first);}\n if(!(last instanceof Date)){ last = new Date(last);}\n\n // Make sure the end date is at the very end of the day and the start date at the very beginning\n first.setHours(0);\n first.setMinutes(0);\n first.setSeconds(0);\n first.setMilliseconds(0);\n last.setHours(23);\n last.setMinutes(59);\n last.setSeconds(59);\n last.setMilliseconds(999);\n\n const dayspan = Math.round(((last - first)+1)/(24*60*60*1000)); // Add one millisecond to offset the 999 ms\n const years = Math.floor(dayspan/365); // Yes, we ignore leap years/leap days\n const ydaysleft = dayspan % 365;\n\n const weeks = Math.floor(ydaysleft/7);\n const wdaysleft = ydaysleft % 7;\n\n return {\n first: first,\n last: last,\n totaldays: dayspan,\n years: years,\n weeks: weeks,\n days: wdaysleft,\n formatted: {\n first: format_date(first),\n last: format_date(last),\n }\n };\n\n}\n\n/**\n * Format a Date object to YYYY-MM-DD format\n * @param {Date} date Date object\n * @returns Date string in YYYY-MM-DD format\n */\nfunction dateYYYYMMDD(date) {\n const d = new Date(date);\n let month = '' + (d.getMonth() + 1);\n let day = '' + d.getDate();\n const year = d.getFullYear();\n\n if (month.length < 2) {\n month = '0' + month;\n }\n if (day.length < 2) {\n day = '0' + day;\n }\n return [year, month, day].join('-');\n}\n\n/**\n * String formatting function - replaces {name} in string by value of same key in values parameter\n * @param {string} datestr String containing date format in YYYY-MM-DD\n * @param {int} days Object containing keys to replace {key} strings with. Make negative to subtract\n * @returns Date string in YYYY-MM-DD format\n */\nexport function add_days(datestr,days) {\n const date = new Date(datestr);\n const newdate = new Date(date.getTime() + (days * 86400000) ); // Add n days in ms.\n return dateYYYYMMDD(newdate);\n}"],"names":["format_date","d","short","Date","monthformat","toLocaleDateString","document","documentElement","lang","year","month","day","datestr","days","date","getMonth","getDate","getFullYear","length","join","dateYYYYMMDD","getTime","first","last","setHours","setMinutes","setSeconds","setMilliseconds","dayspan","Math","round","years","floor","ydaysleft","weeks","totaldays","formatted"],"mappings":"uFAMgBA,YAAYC,EAAEC,OACrBD,aAAaE,OACdF,EAAI,IAAIE,KAAKF,QAGbG,YAAc,eACfF,QACCE,YAAc,WAEXH,EAAEI,mBAAmBC,SAASC,gBAAgBC,KAAK,CACtDC,KAAM,UAAWC,MAAON,YAAaO,IAAK,+FAyEzBC,QAAQC,UACvBC,KAAO,IAAIX,KAAKS,yBAtBJE,UACZb,EAAI,IAAIE,KAAKW,MACfJ,MAAQ,IAAMT,EAAEc,WAAa,GAC7BJ,IAAM,GAAKV,EAAEe,UACXP,KAAOR,EAAEgB,cAEXP,MAAMQ,OAAS,IACfR,MAAQ,IAAMA,OAEdC,IAAIO,OAAS,IACbP,IAAM,IAAMA,WAET,CAACF,KAAMC,MAAOC,KAAKQ,KAAK,KAYxBC,CADS,IAAIjB,KAAKW,KAAKO,UAAoB,MAAPR,uCAhElBS,MAAMC,MAC1BD,iBAAiBnB,OAAQmB,MAAQ,IAAInB,KAAKmB,QAC1CC,gBAAgBpB,OAAQoB,KAAO,IAAIpB,KAAKoB,OAG7CD,MAAME,SAAS,GACfF,MAAMG,WAAW,GACjBH,MAAMI,WAAW,GACjBJ,MAAMK,gBAAgB,GACtBJ,KAAKC,SAAS,IACdD,KAAKE,WAAW,IAChBF,KAAKG,WAAW,IAChBH,KAAKI,gBAAgB,SAEfC,QAAUC,KAAKC,OAAQP,KAAOD,MAAO,UACrCS,MAAQF,KAAKG,MAAMJ,QAAQ,KAC3BK,UAAYL,QAAU,IAEtBM,MAAQL,KAAKG,MAAMC,UAAU,SAG5B,CACHX,MAAOA,MACPC,KAAMA,KACNY,UAAWP,QACXG,MAAOA,MACPG,MAAOA,MACPrB,KARcoB,UAAY,EAS1BG,UAAW,CACPd,MAAOtB,YAAYsB,OACnBC,KAAMvB,YAAYuB"}
|
3
amd/build/util/string-helper copy.min.js
vendored
Normal file
3
amd/build/util/string-helper copy.min.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
define("local_treestudyplan/util/string-helper copy",["exports","core/str"],(function(_exports,_str){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.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,_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,(function(m,m1){return m1&&values.hasOwnProperty(m1)?values[m1]:m}))}}));
|
||||||
|
|
||||||
|
//# sourceMappingURL=string-helper copy.min.js.map
|
1
amd/build/util/string-helper copy.min.js.map
Normal file
1
amd/build/util/string-helper copy.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
amd/build/util/string-helper.min.js
vendored
2
amd/build/util/string-helper.min.js
vendored
|
@ -1,3 +1,3 @@
|
||||||
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){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.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,_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,(function(m,m1){return m1&&values.hasOwnProperty(m1)?values[m1]:m}))}}));
|
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}(0,_str.get_strings)(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,(function(m,m1){return m1&&values.hasOwnProperty(m1)?values[m1]:m}))}}));
|
||||||
|
|
||||||
//# sourceMappingURL=string-helper.min.js.map
|
//# sourceMappingURL=string-helper.min.js.map
|
File diff suppressed because one or more lines are too long
|
@ -10,7 +10,8 @@ import {SimpleLine} from "./simpleline/simpleline";
|
||||||
import {call} from 'core/ajax';
|
import {call} from 'core/ajax';
|
||||||
import notification from 'core/notification';
|
import notification from 'core/notification';
|
||||||
import {get_strings} from 'core/str';
|
import {get_strings} from 'core/str';
|
||||||
import {load_stringkeys, load_strings, format_date, datespaninfo, strformat } from './util/string-helper';
|
import {load_stringkeys, load_strings, strformat } from './util/string-helper';
|
||||||
|
import {format_date, add_days, datespaninfo } from './util/date-helper';
|
||||||
import {objCopy,transportItem} from './studyplan-processor';
|
import {objCopy,transportItem} from './studyplan-processor';
|
||||||
import Debugger from './util/debugger';
|
import Debugger from './util/debugger';
|
||||||
import {download,upload} from './downloader';
|
import {download,upload} from './downloader';
|
||||||
|
@ -1206,7 +1207,18 @@ export default {
|
||||||
self.$emit('input',self.value);
|
self.$emit('input',self.value);
|
||||||
}).fail(notification.exception);
|
}).fail(notification.exception);
|
||||||
},
|
},
|
||||||
|
add_day(date,days) {
|
||||||
|
if( days === undefined ){
|
||||||
|
days = 1;
|
||||||
|
}
|
||||||
|
return add_days(date,days);
|
||||||
|
},
|
||||||
|
sub_day(date,days) {
|
||||||
|
if( days === undefined ){
|
||||||
|
days = 1;
|
||||||
|
}
|
||||||
|
return add_days(date,0 - days);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
template:
|
template:
|
||||||
|
@ -1247,7 +1259,7 @@ export default {
|
||||||
<b-form-datepicker
|
<b-form-datepicker
|
||||||
v-model="editdata.startdate"
|
v-model="editdata.startdate"
|
||||||
:min="(minstart ? minstart : '')"
|
:min="(minstart ? minstart : '')"
|
||||||
:max="value.enddate"
|
:max="sub_day(value.enddate)"
|
||||||
></b-form-datepicker>
|
></b-form-datepicker>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
|
@ -1256,7 +1268,7 @@ export default {
|
||||||
<b-col cols="8">
|
<b-col cols="8">
|
||||||
<b-form-datepicker
|
<b-form-datepicker
|
||||||
v-model="editdata.enddate"
|
v-model="editdata.enddate"
|
||||||
:min="value.startdate"
|
:min="add_day(value.startdate)"
|
||||||
:max="(maxend ? maxend : '')"
|
:max="(maxend ? maxend : '')"
|
||||||
></b-form-datepicker>
|
></b-form-datepicker>
|
||||||
</b-col>
|
</b-col>
|
||||||
|
@ -1575,6 +1587,18 @@ export default {
|
||||||
next.refresh();
|
next.refresh();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
add_day(date,days) {
|
||||||
|
if( days === undefined ){
|
||||||
|
days = 1;
|
||||||
|
}
|
||||||
|
return add_days(date,days);
|
||||||
|
},
|
||||||
|
sub_day(date,days) {
|
||||||
|
if( days === undefined ){
|
||||||
|
days = 1;
|
||||||
|
}
|
||||||
|
return add_days(date,0 - days);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
template:
|
template:
|
||||||
|
@ -1664,8 +1688,8 @@ export default {
|
||||||
:ref="'periodeditor-'+index"
|
:ref="'periodeditor-'+index"
|
||||||
@edited="periodEdited"
|
@edited="periodEdited"
|
||||||
v-model="page.perioddesc[index-1]"
|
v-model="page.perioddesc[index-1]"
|
||||||
:minstart="(index > 1) ? page.perioddesc[index-2].startdate : null"
|
:minstart="(index > 1) ? add_day(page.perioddesc[index-2].startdate,2) : null"
|
||||||
:maxend="(index < page.periods) ? page.perioddesc[index].enddate : null"
|
:maxend="(index < page.periods) ? sub_day(page.perioddesc[index].enddate,2) : null"
|
||||||
></t-period-edit
|
></t-period-edit
|
||||||
></s-studyline-header-period>
|
></s-studyline-header-period>
|
||||||
<div class="s-studyline-header-filter"></div>
|
<div class="s-studyline-header-filter"></div>
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
/*eslint-env es6*/
|
/*eslint-env es6*/
|
||||||
// Put this file in path/to/plugin/amd/src
|
// Put this file in path/to/plugin/amd/src
|
||||||
|
|
||||||
import {load_strings, format_date} from './util/string-helper';
|
import {load_strings} from './util/string-helper';
|
||||||
|
import {format_date} from './util/date-helper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
studyplanTiming(a) {
|
studyplanTiming(a) {
|
||||||
|
|
94
amd/src/util/date-helper.js
Normal file
94
amd/src/util/date-helper.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* Format a date according to localized custom
|
||||||
|
* @param {Date|string} d The date to convert
|
||||||
|
* @param {boolean} short Short format (default false)
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format_date(d,short){
|
||||||
|
if(!(d instanceof Date)){
|
||||||
|
d = new Date(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
let monthformat = "short";
|
||||||
|
if(short){
|
||||||
|
monthformat = "numeric";
|
||||||
|
}
|
||||||
|
return d.toLocaleDateString(document.documentElement.lang,{
|
||||||
|
year: 'numeric', month: monthformat, day: 'numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides standardized information about the period between two dates
|
||||||
|
* As
|
||||||
|
* @param {Date|string} first First day of the span
|
||||||
|
* @param {Date|string} last Last day of the span
|
||||||
|
* @returns {Object} Object containing formatted start and end dates and span information
|
||||||
|
*/
|
||||||
|
export function datespaninfo(first,last){
|
||||||
|
if(!(first instanceof Date)){ first = new Date(first);}
|
||||||
|
if(!(last instanceof Date)){ last = new Date(last);}
|
||||||
|
|
||||||
|
// Make sure the end date is at the very end of the day and the start date at the very beginning
|
||||||
|
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)/(24*60*60*1000)); // Add one millisecond to offset the 999 ms
|
||||||
|
const years = Math.floor(dayspan/365); // Yes, we ignore leap years/leap days
|
||||||
|
const ydaysleft = dayspan % 365;
|
||||||
|
|
||||||
|
const weeks = Math.floor(ydaysleft/7);
|
||||||
|
const wdaysleft = ydaysleft % 7;
|
||||||
|
|
||||||
|
return {
|
||||||
|
first: first,
|
||||||
|
last: last,
|
||||||
|
totaldays: dayspan,
|
||||||
|
years: years,
|
||||||
|
weeks: weeks,
|
||||||
|
days: wdaysleft,
|
||||||
|
formatted: {
|
||||||
|
first: format_date(first),
|
||||||
|
last: format_date(last),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a Date object to YYYY-MM-DD format
|
||||||
|
* @param {Date} date Date object
|
||||||
|
* @returns Date string in YYYY-MM-DD format
|
||||||
|
*/
|
||||||
|
function dateYYYYMMDD(date) {
|
||||||
|
const d = new Date(date);
|
||||||
|
let month = '' + (d.getMonth() + 1);
|
||||||
|
let day = '' + d.getDate();
|
||||||
|
const year = d.getFullYear();
|
||||||
|
|
||||||
|
if (month.length < 2) {
|
||||||
|
month = '0' + month;
|
||||||
|
}
|
||||||
|
if (day.length < 2) {
|
||||||
|
day = '0' + day;
|
||||||
|
}
|
||||||
|
return [year, month, day].join('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String formatting function - replaces {name} in string by value of same key in values parameter
|
||||||
|
* @param {string} datestr String containing date format in YYYY-MM-DD
|
||||||
|
* @param {int} days Object containing keys to replace {key} strings with. Make negative to subtract
|
||||||
|
* @returns Date string in YYYY-MM-DD format
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
|
@ -54,68 +54,6 @@ export function load_stringkeys(string_keys){
|
||||||
}
|
}
|
||||||
return string_keys;
|
return string_keys;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Format a date according to localized custom
|
|
||||||
* @param {Date|string} d The date to convert
|
|
||||||
* @param {boolean} short Short format (default false)
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function format_date(d,short){
|
|
||||||
if(!(d instanceof Date)){
|
|
||||||
d = new Date(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
let monthformat = "short";
|
|
||||||
if(short){
|
|
||||||
monthformat = "numeric";
|
|
||||||
}
|
|
||||||
return d.toLocaleDateString(document.documentElement.lang,{
|
|
||||||
year: 'numeric', month: monthformat, day: 'numeric'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides standardized information about the period between two dates
|
|
||||||
* As
|
|
||||||
* @param {Date|string} first First day of the span
|
|
||||||
* @param {Date|string} last Last day of the span
|
|
||||||
* @returns {Object} Object containing formatted start and end dates and span information
|
|
||||||
*/
|
|
||||||
export function datespaninfo(first,last){
|
|
||||||
if(!(first instanceof Date)){ first = new Date(first);}
|
|
||||||
if(!(last instanceof Date)){ last = new Date(last);}
|
|
||||||
|
|
||||||
// Make sure the end date is at the very end of the day and the start date at the very beginning
|
|
||||||
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)/(24*60*60*1000)); // Add one millisecond to offset the 999 ms
|
|
||||||
const years = Math.floor(dayspan/365); // Yes, we ignore leap years/leap days
|
|
||||||
const ydaysleft = dayspan % 365;
|
|
||||||
|
|
||||||
const weeks = Math.floor(ydaysleft/7);
|
|
||||||
const wdaysleft = ydaysleft % 7;
|
|
||||||
|
|
||||||
return {
|
|
||||||
first: first,
|
|
||||||
last: last,
|
|
||||||
totaldays: dayspan,
|
|
||||||
years: years,
|
|
||||||
weeks: weeks,
|
|
||||||
days: wdaysleft,
|
|
||||||
formatted: {
|
|
||||||
first: format_date(first),
|
|
||||||
last: format_date(last),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String formatting function - replaces {name} in string by value of same key in values parameter
|
* String formatting function - replaces {name} in string by value of same key in values parameter
|
||||||
|
|
|
@ -321,7 +321,7 @@ class period {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust start date of previous period if needed
|
// Adjust start date of next period if needed
|
||||||
if (isset($next) && !empty($fields['enddate'])) {
|
if (isset($next) && !empty($fields['enddate'])) {
|
||||||
$mindate = $this->enddate()->add(new DateInterval("P1D")); // Subtract 1 day, since periods include the end day.
|
$mindate = $this->enddate()->add(new DateInterval("P1D")); // Subtract 1 day, since periods include the end day.
|
||||||
$rqdate = $next->startdate();
|
$rqdate = $next->startdate();
|
||||||
|
|
Loading…
Reference in a new issue