mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-25 16:09:28 +00:00
extracted date handling with luxon into dateUtils file and only work with those functions to completely avoid anymore timezone bugs due to js Dates. formatDate was still affected by timezone issues and was showing off by one dates in rare cases.
This commit is contained in:
@@ -2,6 +2,7 @@ import BsModal from '../../Bootstrap/Modal.js';
|
||||
import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import ApiAbgabe from '../../../api/factory/abgabe.js'
|
||||
import { getDateStyleClass } from "./getDateStyleClass.js";
|
||||
import { compareISODateValues, formatISODate, getViennaTodayISO } from "./dateUtils.js";
|
||||
|
||||
export const AbgabeMitarbeiterDetail = {
|
||||
name: "AbgabeMitarbeiterDetail",
|
||||
@@ -138,7 +139,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
termin.dateStyle = getDateStyleClass(termin, this.notenOptions)
|
||||
}
|
||||
|
||||
this.projektarbeit.abgabetermine.sort((a, b) =>new Date(a.datum) - new Date(b.datum))
|
||||
this.projektarbeit.abgabetermine.sort((a, b) => compareISODateValues(a.datum, b.datum))
|
||||
|
||||
const index = this.projektarbeit.abgabetermine.findIndex(t => termin.paabgabe_id == t.paabgabe_id)
|
||||
|
||||
@@ -159,7 +160,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
'fixtermin': false,
|
||||
'invertedFixtermin': true,
|
||||
'kurzbz': '', // todo kurzbz textfield value vorschlag für qualgates
|
||||
'datum': new Date().toISOString().split('T')[0],
|
||||
'datum': getViennaTodayISO(),
|
||||
'note': this.allowedNotenOptions.find(opt => opt.note == 9),
|
||||
'beurteilungsnotiz': '',
|
||||
'upload_allowed': false,
|
||||
@@ -337,16 +338,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
}
|
||||
},
|
||||
formatDate(dateParam) {
|
||||
// unsafe for datepickers, dont use there
|
||||
const date = new Date(dateParam)
|
||||
// handle missing leading 0
|
||||
const padZero = (num) => String(num).padStart(2, '0');
|
||||
|
||||
const month = padZero(date.getMonth() + 1); // Months are zero-based
|
||||
const day = padZero(date.getDate());
|
||||
const year = date.getFullYear();
|
||||
|
||||
return `${day}.${month}.${year}`
|
||||
return formatISODate(dateParam)
|
||||
},
|
||||
openCreateNewAbgabeModal() {
|
||||
if(this.projektarbeit?.betreuerart_kurzbz == 'Zweitbegutachter') {
|
||||
@@ -364,7 +356,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
'fixtermin': false,
|
||||
'invertedFixtermin': true,
|
||||
'kurzbz': '',
|
||||
'datum': new Date().toISOString().split('T')[0],
|
||||
'datum': getViennaTodayISO(),
|
||||
'note': this.allowedNotenOptions.find(opt => opt.note == 9),
|
||||
'beurteilungsnotiz': '',
|
||||
'upload_allowed': typ.upload_allowed_default,
|
||||
@@ -398,7 +390,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
'fixtermin': false,
|
||||
'invertedFixtermin': true,
|
||||
'kurzbz': '',
|
||||
'datum': new Date().toISOString().split('T')[0],
|
||||
'datum': getViennaTodayISO(),
|
||||
'note': this.allowedNotenOptions.find(opt => opt.note == 9),
|
||||
'beurteilungsnotiz': '',
|
||||
'upload_allowed': false,
|
||||
@@ -597,7 +589,7 @@ export const AbgabeMitarbeiterDetail = {
|
||||
'fixtermin': false,
|
||||
'invertedFixtermin': true,
|
||||
'kurzbz': '',
|
||||
'datum': new Date().toISOString().split('T')[0],
|
||||
'datum': getViennaTodayISO(),
|
||||
'note': this.allowedNotenOptions.find(opt => opt.note == 9),
|
||||
'beurteilungsnotiz': '',
|
||||
'upload_allowed': typ.upload_allowed_default,
|
||||
|
||||
@@ -3,6 +3,7 @@ import BsModal from '../../Bootstrap/Modal.js';
|
||||
import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import ApiAbgabe from '../../../api/factory/abgabe.js'
|
||||
import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import { formatISODate, getViennaTodayISO } from "./dateUtils.js";
|
||||
|
||||
export const AbgabeStudentDetail = {
|
||||
name: "AbgabeStudentDetail",
|
||||
@@ -166,14 +167,7 @@ export const AbgabeStudentDetail = {
|
||||
window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url)
|
||||
},
|
||||
formatDate(dateParam) {
|
||||
const date = new Date(dateParam)
|
||||
const padZero = (num) => String(num).padStart(2, '0');
|
||||
|
||||
const month = padZero(date.getUTCMonth() + 1);
|
||||
const day = padZero(date.getUTCDate());
|
||||
const year = date.getUTCFullYear();
|
||||
|
||||
return `${day}.${month}.${year}`
|
||||
return formatISODate(dateParam)
|
||||
},
|
||||
async upload(termin) {
|
||||
|
||||
@@ -210,7 +204,7 @@ export const AbgabeStudentDetail = {
|
||||
if(res.meta.status == "success") {
|
||||
this.$fhcAlert.alertSuccess(this.$capitalize(this.$p.t('abgabetool/c4fileUploadSuccessv3')))
|
||||
|
||||
termin.abgabedatum = new Date().toISOString().split('T')[0];
|
||||
termin.abgabedatum = getViennaTodayISO();
|
||||
if(res?.data?.signatur !== undefined) {
|
||||
termin.signatur = res.data.signatur
|
||||
}
|
||||
@@ -684,4 +678,4 @@ export const AbgabeStudentDetail = {
|
||||
`,
|
||||
};
|
||||
|
||||
export default AbgabeStudentDetail;
|
||||
export default AbgabeStudentDetail;
|
||||
|
||||
@@ -10,6 +10,7 @@ import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import { splitMailsHelper } from "../../../helpers/EmailHelpers.js"
|
||||
import { getDateStyleClass} from "./getDateStyleClass.js";
|
||||
import { dateFilter } from '../../../tabulator/filters/Dates.js';
|
||||
import { compareISODateValues, formatISODate, getViennaTodayISO, toViennaDate } from "./dateUtils.js";
|
||||
|
||||
export const AbgabetoolAssistenz = {
|
||||
name: "AbgabetoolAssistenz",
|
||||
@@ -118,7 +119,7 @@ export const AbgabetoolAssistenz = {
|
||||
fixtermin: false,
|
||||
},
|
||||
serienTermin: Vue.reactive({
|
||||
datum: new Date().toISOString().split('T')[0],
|
||||
datum: getViennaTodayISO(),
|
||||
bezeichnung: {
|
||||
paabgabetyp_kurzbz: 'zwischen',
|
||||
bezeichnung: 'Zwischenabgabe'
|
||||
@@ -404,7 +405,7 @@ export const AbgabetoolAssistenz = {
|
||||
field: 'datum',
|
||||
headerFilter: dateFilter,
|
||||
headerFilterFunc: this.headerFilterTerminColISO,
|
||||
sorter: (a, b) => new Date(a) - new Date(b),
|
||||
sorter: compareISODateValues,
|
||||
formatter: (cell) => this.formatDate(cell.getValue()),
|
||||
minWidth: 100
|
||||
},
|
||||
@@ -413,7 +414,7 @@ export const AbgabetoolAssistenz = {
|
||||
field: 'abgabedatum',
|
||||
headerFilter: dateFilter,
|
||||
headerFilterFunc: this.headerFilterTerminColISO,
|
||||
sorter: (a, b) => new Date(a) - new Date(b),
|
||||
sorter: compareISODateValues,
|
||||
formatter: (cell) => this.formatDate(cell.getValue()),
|
||||
minWidth: 100
|
||||
},
|
||||
@@ -633,7 +634,7 @@ export const AbgabetoolAssistenz = {
|
||||
upload_allowed: false,
|
||||
fixtermin: false,
|
||||
}
|
||||
this.serienEdit.datum = new Date().toISOString().split('T')[0]
|
||||
this.serienEdit.datum = getViennaTodayISO()
|
||||
this.serienEdit.bezeichnung = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === 'zwischen')
|
||||
this.serienEdit.kurzbz = ''
|
||||
this.serienEdit.upload_allowed = false
|
||||
@@ -1087,7 +1088,7 @@ export const AbgabetoolAssistenz = {
|
||||
if (val instanceof Date) {
|
||||
dt = luxon.DateTime.fromJSDate(val);
|
||||
} else if (typeof val === "string") {
|
||||
dt = luxon.DateTime.fromISO(val);
|
||||
dt = toViennaDate(val);
|
||||
} else { // fallback
|
||||
dt = luxon.DateTime.fromMillis(Number(val));
|
||||
}
|
||||
@@ -1124,7 +1125,7 @@ export const AbgabetoolAssistenz = {
|
||||
if (val instanceof Date) {
|
||||
dt = luxon.DateTime.fromJSDate(val);
|
||||
} else if (typeof val === "string") {
|
||||
dt = luxon.DateTime.fromISO(val);
|
||||
dt = toViennaDate(val);
|
||||
} else { // fallback
|
||||
dt = luxon.DateTime.fromMillis(Number(val));
|
||||
}
|
||||
@@ -1372,7 +1373,7 @@ export const AbgabetoolAssistenz = {
|
||||
// while already looping through each termin, calculate datestyle beforehand
|
||||
termin.dateStyle = getDateStyleClass(termin, this.notenOptions)
|
||||
|
||||
const date = luxon.DateTime.fromISO(termin.datum).endOf('day')
|
||||
const date = toViennaDate(termin.datum).endOf('day')
|
||||
termin.luxonDate = date
|
||||
termin.diffMs = date.toMillis() - now.toMillis(); // positive = future, negative = past
|
||||
|
||||
@@ -1640,16 +1641,7 @@ export const AbgabetoolAssistenz = {
|
||||
return option.bezeichnung
|
||||
},
|
||||
formatDate(dateParam) {
|
||||
if(dateParam === null) return ''
|
||||
const date = new Date(dateParam)
|
||||
// handle missing leading 0
|
||||
const padZero = (num) => String(num).padStart(2, '0');
|
||||
|
||||
const month = padZero(date.getMonth() + 1); // Months are zero-based
|
||||
const day = padZero(date.getDate());
|
||||
const year = date.getFullYear();
|
||||
|
||||
return `${day}.${month}.${year}`;
|
||||
return formatISODate(dateParam);
|
||||
},
|
||||
formAction(cell) {
|
||||
const actionButtons = document.createElement('div');
|
||||
@@ -1758,7 +1750,7 @@ export const AbgabetoolAssistenz = {
|
||||
abgabe.bezeichnung = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz == abgabe.paabgabetyp_kurzbz)
|
||||
|
||||
pa.abgabetermine.push(abgabe)
|
||||
pa.abgabetermine.sort((a, b) => new Date(a.datum) - new Date(b.datum))
|
||||
pa.abgabetermine.sort((a, b) => compareISODateValues(a.datum, b.datum))
|
||||
})
|
||||
|
||||
this.projektarbeiten = this.mapProjekteToTableData(this.projektarbeiten)
|
||||
@@ -1822,7 +1814,7 @@ export const AbgabetoolAssistenz = {
|
||||
findLatestTerminWithUpload(projekt) {
|
||||
const withAbgabedatumSorted = projekt?.abgabetermine
|
||||
?.filter(t => t.abgabedatum != null)
|
||||
?.sort((a, b) => new Date(b.abgabedatum) - new Date(a.abgabedatum));
|
||||
?.sort((a, b) => compareISODateValues(b.abgabedatum, a.abgabedatum));
|
||||
|
||||
if(withAbgabedatumSorted.length) {
|
||||
return withAbgabedatumSorted[0]
|
||||
|
||||
@@ -7,6 +7,7 @@ import FhcOverlay from "../../Overlay/FhcOverlay.js";
|
||||
import { getDateStyleClass } from "./getDateStyleClass.js";
|
||||
import { dateFilter } from '../../../tabulator/filters/Dates.js';
|
||||
import {splitMailsHelper} from "../../../helpers/EmailHelpers.js";
|
||||
import { formatISODate, getViennaTodayISO, toViennaDate } from "./dateUtils.js";
|
||||
|
||||
export const AbgabetoolMitarbeiter = {
|
||||
name: "AbgabetoolMitarbeiter",
|
||||
@@ -63,7 +64,7 @@ export const AbgabetoolMitarbeiter = {
|
||||
allowedNotenOptions: null,
|
||||
notenOptionsNonFinal: null,
|
||||
serienTermin: Vue.reactive({
|
||||
datum: new Date().toISOString().split('T')[0],
|
||||
datum: getViennaTodayISO(),
|
||||
bezeichnung: {
|
||||
paabgabetyp_kurzbz: 'zwischen',
|
||||
bezeichnung: 'Zwischenabgabe'
|
||||
@@ -571,7 +572,7 @@ export const AbgabetoolMitarbeiter = {
|
||||
if (val instanceof Date) {
|
||||
dt = luxon.DateTime.fromJSDate(val);
|
||||
} else if (typeof val === "string") {
|
||||
dt = luxon.DateTime.fromISO(val);
|
||||
dt = toViennaDate(val);
|
||||
} else { // fallback
|
||||
dt = luxon.DateTime.fromMillis(Number(val));
|
||||
}
|
||||
@@ -803,7 +804,7 @@ export const AbgabetoolMitarbeiter = {
|
||||
// while already looping through each termin, calculate datestyle beforehand
|
||||
termin.dateStyle = getDateStyleClass(termin, this.notenOptions)
|
||||
|
||||
const date = luxon.DateTime.fromISO(termin.datum).endOf('day')
|
||||
const date = toViennaDate(termin.datum).endOf('day')
|
||||
termin.luxonDate = date
|
||||
termin.diffMs = date.toMillis() - now.toMillis(); // positive = future, negative = past
|
||||
|
||||
@@ -914,15 +915,7 @@ export const AbgabetoolMitarbeiter = {
|
||||
return option.bezeichnung
|
||||
},
|
||||
formatDate(dateParam) {
|
||||
const date = new Date(dateParam)
|
||||
// handle missing leading 0
|
||||
const padZero = (num) => String(num).padStart(2, '0');
|
||||
|
||||
const month = padZero(date.getMonth() + 1); // Months are zero-based
|
||||
const day = padZero(date.getDate());
|
||||
const year = date.getFullYear();
|
||||
|
||||
return `${day}.${month}.${year}`;
|
||||
return formatISODate(dateParam);
|
||||
},
|
||||
undoSelection(cell) {
|
||||
// checks if cells row is selected and unselects -> imitates columns which dont trigger row selection
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
const zone = 'Europe/Vienna';
|
||||
|
||||
export function getViennaTodayISO() {
|
||||
return luxon.DateTime.now().setZone(zone).toISODate();
|
||||
}
|
||||
|
||||
export function formatISODate(dateParam) {
|
||||
if (!dateParam) return '';
|
||||
|
||||
const date = luxon.DateTime.fromISO(String(dateParam), { zone });
|
||||
return date.isValid ? date.toFormat('dd.MM.yyyy') : '';
|
||||
}
|
||||
|
||||
export function toViennaDate(dateParam) {
|
||||
if (!dateParam) return null;
|
||||
|
||||
return luxon.DateTime.fromISO(String(dateParam), { zone });
|
||||
}
|
||||
|
||||
export function compareISODateValues(a, b) {
|
||||
if (!a && !b) return 0;
|
||||
if (!a) return 1;
|
||||
if (!b) return -1;
|
||||
|
||||
return String(a).localeCompare(String(b));
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
const zone = 'Europe/Vienna';
|
||||
const today = luxon.DateTime.now().setZone(zone);
|
||||
|
||||
export function getDateStyleClass(termin, notenOptions) {
|
||||
const today = luxon.DateTime.now().setZone(zone);
|
||||
const datum = luxon.DateTime.fromISO(termin.datum, { zone }).endOf('day');
|
||||
const abgabedatum = termin.abgabedatum ? luxon.DateTime.fromISO(termin.abgabedatum, { zone }) : null;
|
||||
termin.diffindays = datum.diff(today, 'days').days;
|
||||
@@ -35,4 +35,4 @@ export function getDateStyleClass(termin, notenOptions) {
|
||||
if (datum < today) return 'verpasst';
|
||||
if (termin.diffindays <= 12) return 'abzugeben';
|
||||
return 'standard';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user