Save before creating restore point: Periodic backup
Auto-saved at 2025-07-30 08:54:37 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,8 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
const jspreadsheetInstance = React.useRef<unknown>(null)
|
const jspreadsheetInstance = React.useRef<unknown>(null)
|
||||||
const isActiveRef = React.useRef<boolean>(true)
|
const isActiveRef = React.useRef<boolean>(true)
|
||||||
const isMergingRef = React.useRef<boolean>(false)
|
const isMergingRef = React.useRef<boolean>(false)
|
||||||
|
const isInitializingRef = React.useRef<boolean>(false)
|
||||||
|
const initTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
|
||||||
const currentDate = new Date()
|
const currentDate = new Date()
|
||||||
const [selectedMonth, setSelectedMonth] = React.useState<string>((currentDate.getMonth() + 1).toString())
|
const [selectedMonth, setSelectedMonth] = React.useState<string>((currentDate.getMonth() + 1).toString())
|
||||||
const [selectedYear, setSelectedYear] = React.useState<string>(currentDate.getFullYear().toString())
|
const [selectedYear, setSelectedYear] = React.useState<string>(currentDate.getFullYear().toString())
|
||||||
@@ -147,7 +149,33 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
console.log("useEffect triggered - Month:", selectedMonth, "Year:", selectedYear, "Force:", forceUpdate)
|
console.log("useEffect triggered - Month:", selectedMonth, "Year:", selectedYear, "Force:", forceUpdate)
|
||||||
isActiveRef.current = true
|
|
||||||
|
// Clear any existing timeout
|
||||||
|
if (initTimeoutRef.current) {
|
||||||
|
console.log("CLEARING: existing timeout, debouncing useEffect")
|
||||||
|
clearTimeout(initTimeoutRef.current)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent multiple simultaneous initializations with immediate return
|
||||||
|
if (isInitializingRef.current) {
|
||||||
|
console.log("BLOCKED: useEffect - already initializing, skipping completely")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("DEBOUNCING: useEffect with 100ms delay")
|
||||||
|
|
||||||
|
// Debounce the initialization to prevent rapid successive calls
|
||||||
|
initTimeoutRef.current = setTimeout(() => {
|
||||||
|
console.log("EXECUTING: debounced useEffect after delay")
|
||||||
|
|
||||||
|
// Double-check we're still not initializing (could have started between timeout set and execution)
|
||||||
|
if (isInitializingRef.current) {
|
||||||
|
console.log("BLOCKED: Still initializing at timeout execution")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isInitializingRef.current = true
|
||||||
|
isActiveRef.current = true
|
||||||
|
|
||||||
const loadJSpreadsheet = async () => {
|
const loadJSpreadsheet = async () => {
|
||||||
console.log("Starting loadJSpreadsheet function")
|
console.log("Starting loadJSpreadsheet function")
|
||||||
@@ -370,8 +398,8 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
if (!isActiveRef.current || !jspreadsheetInstance.current) return
|
if (!isActiveRef.current || !jspreadsheetInstance.current) return
|
||||||
|
|
||||||
// Apply rotation to first row (y === 0) when text is entered
|
// Apply rotation to first row (y === 0) when text is entered
|
||||||
if (y === 0 && value && value.trim()) {
|
if (y === 0 && value !== undefined) {
|
||||||
console.log("First row change detected, applying rotation...")
|
console.log("First row change detected, applying rotation...", { x, y, value })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!isActiveRef.current || !spreadsheetRef.current) return
|
if (!isActiveRef.current || !spreadsheetRef.current) return
|
||||||
|
|
||||||
@@ -384,15 +412,24 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
const targetCell = cells[x + 1] as HTMLElement // +1 because first cell is row number
|
const targetCell = cells[x + 1] as HTMLElement // +1 because first cell is row number
|
||||||
console.log("Target cell found:", !!targetCell, "Cell content:", targetCell?.textContent)
|
console.log("Target cell found:", !!targetCell, "Cell content:", targetCell?.textContent)
|
||||||
if (targetCell) {
|
if (targetCell) {
|
||||||
targetCell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap;">${value}</div>`
|
// Apply rotation even for empty values to maintain consistent styling
|
||||||
console.log("Rotation applied to cell:", targetCell)
|
const displayValue = value && value.trim() ? value.trim() : ''
|
||||||
|
if (displayValue) {
|
||||||
|
targetCell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap; width: 100%;">${displayValue}</div>`
|
||||||
|
console.log("Rotation applied to cell with value:", displayValue)
|
||||||
|
} else {
|
||||||
|
// Clear rotation for empty cells
|
||||||
|
targetCell.innerHTML = ''
|
||||||
|
targetCell.style.transform = 'none'
|
||||||
|
console.log("Cleared rotation for empty cell")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error applying rotation:", error)
|
console.error("Error applying rotation:", error)
|
||||||
}
|
}
|
||||||
}, 100)
|
}, 50) // Reduced timeout for faster response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -477,6 +514,13 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
}
|
}
|
||||||
}, 300) // Increased timeout to ensure spreadsheet is fully ready
|
}, 300) // Increased timeout to ensure spreadsheet is fully ready
|
||||||
|
|
||||||
|
// Clear initialization flag after successful setup - increased timeout to prevent rapid re-initializations
|
||||||
|
setTimeout(() => {
|
||||||
|
isInitializingRef.current = false
|
||||||
|
initTimeoutRef.current = null
|
||||||
|
console.log("Initialization completed, flag and timeout cleared")
|
||||||
|
}, 2000) // Extended to 2 seconds to ensure complete initialization
|
||||||
|
|
||||||
// Apply counter-clockwise rotation to data values only (exclude second column which contains field labels)
|
// Apply counter-clockwise rotation to data values only (exclude second column which contains field labels)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const table = spreadsheetRef.current?.querySelector('.jexcel tbody')
|
const table = spreadsheetRef.current?.querySelector('.jexcel tbody')
|
||||||
@@ -484,8 +528,8 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
const rows = table.querySelectorAll('tr')
|
const rows = table.querySelectorAll('tr')
|
||||||
const totalCells = data[0]?.length || 0
|
const totalCells = data[0]?.length || 0
|
||||||
|
|
||||||
// Rotate data values in rows 2, 3, 4, 5, 6 (day names, year, month, day, shifts)
|
// Rotate data values in rows 1, 2, 3, 4, 5, 6 (first row, day names, year, month, day, shifts)
|
||||||
;[1, 2, 3, 4, 5].forEach(rowIndex => {
|
;[0, 1, 2, 3, 4, 5].forEach(rowIndex => {
|
||||||
if (rows[rowIndex]) {
|
if (rows[rowIndex]) {
|
||||||
const cells = rows[rowIndex].querySelectorAll('td')
|
const cells = rows[rowIndex].querySelectorAll('td')
|
||||||
cells.forEach((cell, cellIndex) => {
|
cells.forEach((cell, cellIndex) => {
|
||||||
@@ -494,7 +538,9 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
const originalText = cell.textContent?.trim()
|
const originalText = cell.textContent?.trim()
|
||||||
if (originalText) {
|
if (originalText) {
|
||||||
// Use 12px font for all rotated values (date values, day names, and shifts)
|
// Use 12px font for all rotated values (date values, day names, and shifts)
|
||||||
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap;">${originalText}</div>`
|
// For first row (rowIndex 0), ensure width: 100% for better text display
|
||||||
|
const extraStyle = rowIndex === 0 ? ' width: 100%;' : ''
|
||||||
|
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap;${extraStyle}">${originalText}</div>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -502,7 +548,7 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Make only "Pohotovost TKB" bold, keep other field labels regular and ensure they're not rotated
|
// Make only "Pohotovost TKB" bold, keep other field labels regular and ensure they're not rotated
|
||||||
;[0, 2, 3, 4, 5].forEach(rowIndex => {
|
;[0, 1, 2, 3, 4, 5].forEach(rowIndex => {
|
||||||
if (rows[rowIndex]) {
|
if (rows[rowIndex]) {
|
||||||
const cells = rows[rowIndex].querySelectorAll('td')
|
const cells = rows[rowIndex].querySelectorAll('td')
|
||||||
if (cells[1]) { // Second column (index 1)
|
if (cells[1]) { // Second column (index 1)
|
||||||
@@ -521,17 +567,27 @@ export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetP
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Cannot initialize - missing ref or jexcel library")
|
console.log("Cannot initialize - missing ref or jexcel library")
|
||||||
|
isInitializingRef.current = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Calling loadJSpreadsheet...")
|
console.log("Calling loadJSpreadsheet...")
|
||||||
loadJSpreadsheet().catch(error => {
|
loadJSpreadsheet().catch(error => {
|
||||||
console.error("Error in loadJSpreadsheet:", error)
|
console.error("Error in loadJSpreadsheet:", error)
|
||||||
|
isInitializingRef.current = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
}, 100) // 100ms debounce delay
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
// Clear timeout on cleanup
|
||||||
|
if (initTimeoutRef.current) {
|
||||||
|
clearTimeout(initTimeoutRef.current)
|
||||||
|
initTimeoutRef.current = null
|
||||||
|
}
|
||||||
isActiveRef.current = false
|
isActiveRef.current = false
|
||||||
isMergingRef.current = false
|
isMergingRef.current = false
|
||||||
|
isInitializingRef.current = false
|
||||||
if (jspreadsheetInstance.current) {
|
if (jspreadsheetInstance.current) {
|
||||||
jspreadsheetInstance.current.destroy()
|
jspreadsheetInstance.current.destroy()
|
||||||
jspreadsheetInstance.current = null
|
jspreadsheetInstance.current = null
|
||||||
|
|||||||
@@ -148,3 +148,6 @@
|
|||||||
2025-07-30 07:54:37 +02:00: 🔖 Creating restore point...
|
2025-07-30 07:54:37 +02:00: 🔖 Creating restore point...
|
||||||
2025-07-30 07:54:43 +02:00: ✅ Restore point created
|
2025-07-30 07:54:43 +02:00: ✅ Restore point created
|
||||||
2025-07-30 08:24:37 +02:00: 🔖 Creating restore point...
|
2025-07-30 08:24:37 +02:00: 🔖 Creating restore point...
|
||||||
|
2025-07-30 08:24:45 +02:00: ✅ Restore point created
|
||||||
|
2025-07-30 08:54:37 +02:00: 🔄 Hourly reset: Commit counter reset to 0
|
||||||
|
2025-07-30 08:54:37 +02:00: 🔖 Creating restore point...
|
||||||
|
|||||||
@@ -144,3 +144,6 @@
|
|||||||
2025-07-30 07:54:37 +02:00: 🔖 Creating restore point...
|
2025-07-30 07:54:37 +02:00: 🔖 Creating restore point...
|
||||||
2025-07-30 07:54:43 +02:00: ✅ Restore point created
|
2025-07-30 07:54:43 +02:00: ✅ Restore point created
|
||||||
2025-07-30 08:24:37 +02:00: 🔖 Creating restore point...
|
2025-07-30 08:24:37 +02:00: 🔖 Creating restore point...
|
||||||
|
2025-07-30 08:24:45 +02:00: ✅ Restore point created
|
||||||
|
2025-07-30 08:54:37 +02:00: 🔄 Hourly reset: Commit counter reset to 0
|
||||||
|
2025-07-30 08:54:37 +02:00: 🔖 Creating restore point...
|
||||||
|
|||||||
Reference in New Issue
Block a user