209 lines
7.0 KiB
JavaScript
Raw Normal View History

2025-01-27 18:50:24 +01:00
let prevMonthBtn, nextMonthBtn, month
let prevWeekBtn, nextWeekBtn, week
2025-01-26 02:01:38 +01:00
let curYear = new Date().getFullYear()
let curMonth = new Date().getMonth()
2025-01-27 18:50:24 +01:00
let curWeekDate = new Date()
2025-01-26 02:01:38 +01:00
function prevMonth() {
curMonth = curMonth - 1
if (curMonth < 0) {
curMonth += 12
curYear -= 1
}
2025-02-03 12:06:59 +01:00
updateTableMonthly()
2025-01-26 02:01:38 +01:00
}
function nextMonth() {
curMonth = curMonth + 1
if (curMonth >= 12) {
curMonth -= 12
curYear += 1
}
2025-02-03 12:06:59 +01:00
updateTableMonthly()
2025-01-27 18:50:24 +01:00
}
function prevWeek() {
curWeekDate = new Date(curWeekDate.valueOf() - 7 * DAY_MS)
2025-02-03 12:06:59 +01:00
updateTableWeekly()
2025-01-27 18:50:24 +01:00
}
function nextWeek() {
curWeekDate = new Date(curWeekDate.valueOf() + 7 * DAY_MS)
2025-02-03 12:06:59 +01:00
updateTableWeekly()
2025-01-26 02:01:38 +01:00
}
2025-02-03 12:06:59 +01:00
function updateTableMonthly() {
2025-01-26 02:01:38 +01:00
let year = curYear.toString().padStart(4, "0")
let month = (curMonth + 1).toString().padStart(2, "0")
let today = new Date()
let txt = MONTHS[curMonth]
if (today.getFullYear() !== curYear) {
txt += " " + year.toString().padStart(4, "0")
}
document.getElementById("month").innerText = txt
fetch(`stats/by-month/${year}/${month}/`).then(res => {
return res.json()
}).then(res => {
if (res.status !== "success") {
return
}
2025-02-03 12:06:59 +01:00
updateTable(res.data)
2025-01-27 18:50:24 +01:00
})
}
2025-02-03 12:06:59 +01:00
function updateTableWeekly() {
let weekNum = curWeekDate.getWeek()
2025-01-27 18:50:24 +01:00
let weekDay = (curWeekDate.getDay() + 6) % 7
let startDate = new Date(curWeekDate.valueOf() - weekDay * DAY_MS)
let endDate = new Date(startDate.valueOf() + 6 * DAY_MS)
let today = new Date()
let date = `${MONTHS[startDate.getMonth()]} ${startDate.getDate()}`
2025-01-27 18:50:24 +01:00
if (startDate.getFullYear() !== today.getFullYear()) {
date += " " + startDate.getFullYear().toString().padStart(4, "0")
2025-01-27 18:50:24 +01:00
}
document.getElementById("week").innerText = `Week ${weekNum} (${date})`
2025-01-27 18:50:24 +01:00
fetch(`stats/between/${formatDate(startDate)}/${formatDate(endDate)}/`).then(res => {
return res.json()
}).then(res => {
if (res.status !== "success") {
2025-01-26 02:01:38 +01:00
return
}
2025-02-03 12:06:59 +01:00
updateTable(res.data)
2025-01-27 18:50:24 +01:00
})
}
2025-02-03 12:06:59 +01:00
function updateTable(data) {
let totalWorked = data.clockings.map(c => c.total).reduce((a, b) => a + b, 0)
let parents = data.parents.filter(parent => parent.duration !== null && parent.is_productive)
let headers = document.getElementById("headers-table")
let table = document.getElementById("projects-table")
let projNames = table.querySelector(".project-names")
let projNums = table.querySelector(".project-nums")
let totDurations = table.querySelector(".total-durations")
let workingRatios = table.querySelector(".working-time-ratios")
let imputedRatios = table.querySelector(".imputed-time-ratios")
let sagexHours = table.querySelector(".sagex-hours")
let realSagexHours = table.querySelector(".real-sagex-hours")
table.querySelectorAll("tr").forEach(row => row.innerHTML = "")
let totalImputed = 0
parents.forEach(parent => {
totalImputed += +parent.duration
})
headers.querySelector(".total-clocking").innerText = formatDuration(totalWorked)
headers.querySelector(".total-duration").innerText = formatDuration(totalImputed)
let sagexHoursTemplate = getTemplate("sagex-hours")
2025-02-03 12:06:59 +01:00
let totalSagex = 0
parents.forEach(parent => {
let duration = +parent.duration
let name = document.createElement("th")
name.innerText = parent.name
projNames.appendChild(name)
projNums.insertCell(-1).innerText = parent.project_num
table.querySelector(".clocking").insertCell(-1)
totDurations.insertCell(-1).innerText = formatDuration(duration)
let ratioWorking = duration / totalWorked
let ratioImputed = duration / totalImputed
workingRatios.insertCell(-1).innerText = formatPercentage(ratioWorking)
imputedRatios.insertCell(-1).innerText = formatPercentage(ratioImputed)
let sagexDuration = duration * totalWorked / totalImputed
totalSagex += sagexDuration
sagexHours.insertCell(-1).innerText = formatDuration(sagexDuration)
let td = sagexHoursTemplate.cloneNode(true)
let [h, m, s] = parent.real_sagex_hours.split(":")
let hoursInput = td.querySelector("input.hours")
let minutesInput = td.querySelector("input.minutes")
hoursInput.value = h
minutesInput.value = m
let timeout = null
minutesInput.addEventListener("input", () => reformatTime(minutesInput))
td.addEventListener("change", () => {
if (timeout !== null) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
updateSagex(parent.id, td)
}, 1000)
})
realSagexHours.appendChild(td)
2025-01-26 02:01:38 +01:00
})
2025-02-03 12:06:59 +01:00
headers.querySelector(".sagex-hours-total").innerText = formatDuration(totalSagex)
2025-01-26 02:01:38 +01:00
}
function reformatTime(input) {
let value = input.value
if (value.length === 1) {
input.value = "0" + value
} else if (value.length > 2) {
input.value = value.slice(value.length - 2)
}
}
function updateSagex(id, cell) {
let hoursInput = cell.querySelector(".hours")
let minutesInput = cell.querySelector(".minutes")
reformatTime(minutesInput)
let hours = +hoursInput.value
let minutes = +minutesInput.value
let year = curYear.toString().padStart(4, "0")
let month = (curMonth + 1).toString().padStart(2, "0")
let date = `${year}-${month}`
let fd = new FormData()
fd.set("minutes", hours * 60 + minutes)
req(`/sagex/${id}/${date}/`, {
method: "POST",
body: fd
}).then(res => {
return res.json()
}).then(res => {
if (res.status === "success") {
cell.classList.add("saved")
cell.addEventListener("animationend", () => {
cell.classList.remove("saved")
}, {once: true})
} else {
alert(res.error)
}
})
}
2025-01-26 02:01:38 +01:00
window.addEventListener("load", () => {
2025-01-27 18:50:24 +01:00
prevMonthBtn = document.getElementById("prev-month")
nextMonthBtn = document.getElementById("next-month")
2025-01-26 02:01:38 +01:00
month = document.getElementById("month")
2025-01-27 18:50:24 +01:00
prevWeekBtn = document.getElementById("prev-week")
nextWeekBtn = document.getElementById("next-week")
week = document.getElementById("week")
prevMonthBtn.addEventListener("click", () => prevMonth())
nextMonthBtn.addEventListener("click", () => nextMonth())
prevWeekBtn.addEventListener("click", () => prevWeek())
nextWeekBtn.addEventListener("click", () => nextWeek())
let monthGrp = document.getElementById("month-sel")
let weekGrp = document.getElementById("week-sel")
rangeSel = document.getElementById("range-sel")
rangeSel.addEventListener("change", () => {
let mode = rangeSel.value
if (mode === "weekly") {
monthGrp.classList.add("hidden")
weekGrp.classList.remove("hidden")
2025-02-03 12:06:59 +01:00
updateTableWeekly()
2025-01-27 18:50:24 +01:00
} else {
monthGrp.classList.remove("hidden")
weekGrp.classList.add("hidden")
2025-02-03 12:06:59 +01:00
updateTableMonthly()
2025-01-27 18:50:24 +01:00
}
})
2025-02-03 12:06:59 +01:00
updateTableMonthly()
2025-01-26 02:01:38 +01:00
})