Compare commits
6 Commits
eaad398127
...
e44e1ffb8a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e44e1ffb8a | ||
|
|
fb86c59413 | ||
|
|
191eeca57f | ||
|
|
8ed2967f6f | ||
|
|
58eb8c169b | ||
|
|
0ead94ac8d |
174
AUTO-COMMIT-README.md
Normal file
174
AUTO-COMMIT-README.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Auto-Commit System for Timeshift Project
|
||||
|
||||
This system automatically saves your work to git to prevent losing changes when Claude gets restarted or when making experimental changes.
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Start Auto-Watch (Recommended)
|
||||
```bash
|
||||
npm run watch-commit
|
||||
```
|
||||
This will automatically commit changes every 30 seconds when files are modified.
|
||||
|
||||
### Manual Commands
|
||||
```bash
|
||||
# Save current work immediately
|
||||
npm run save "Your commit message"
|
||||
|
||||
# Create a restore point before major changes
|
||||
npm run restore-point "Before major refactor"
|
||||
|
||||
# List all restore points
|
||||
./auto-commit.sh list
|
||||
|
||||
# Clean old restore points (keeps last 10)
|
||||
./auto-commit.sh cleanup
|
||||
```
|
||||
|
||||
## 📋 How It Works
|
||||
|
||||
### Automatic Commits
|
||||
- **File Watcher**: Monitors `components/`, `app/`, `lib/`, `styles/` directories
|
||||
- **Smart Delay**: Waits 30 seconds after last change before committing
|
||||
- **Rate Limiting**: Max 10 commits per hour to avoid spam
|
||||
- **File Types**: Watches `.tsx`, `.ts`, `.js`, `.jsx`, `.css`, `.scss`, `.json` files
|
||||
|
||||
### Restore Points
|
||||
- **Branches**: Creates timestamped branches like `restore-point-20250129-143022`
|
||||
- **Automatic**: Creates restore points on startup and every 30 minutes
|
||||
- **Manual**: Create before risky changes with `npm run restore-point "description"`
|
||||
|
||||
## 🔧 Features
|
||||
|
||||
### Auto-Commit Script Features
|
||||
✅ Automatic timestamped commits
|
||||
✅ Descriptive commit messages
|
||||
✅ Rate limiting to prevent spam
|
||||
✅ Restore point creation
|
||||
✅ Cleanup of old restore points
|
||||
✅ Git status checking
|
||||
|
||||
### File Watcher Features
|
||||
✅ Real-time file monitoring
|
||||
✅ Smart batching of changes
|
||||
✅ Graceful shutdown handling
|
||||
✅ Periodic restore points
|
||||
✅ Console logging for transparency
|
||||
|
||||
## 📚 Usage Examples
|
||||
|
||||
### Starting Your Work Session
|
||||
```bash
|
||||
# Start the auto-commit watcher
|
||||
npm run watch-commit
|
||||
|
||||
# In another terminal, start development
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Before Making Risky Changes
|
||||
```bash
|
||||
# Create a restore point
|
||||
npm run restore-point "Before implementing new feature"
|
||||
|
||||
# Make your changes...
|
||||
# Files are auto-committed as you work
|
||||
|
||||
# If something breaks, restore with:
|
||||
git checkout restore-point-20250129-143022
|
||||
```
|
||||
|
||||
### Manual Saves
|
||||
```bash
|
||||
# Quick save
|
||||
npm run save
|
||||
|
||||
# Save with custom message
|
||||
npm run save "Fixed spreadsheet column alignment"
|
||||
```
|
||||
|
||||
### Managing Restore Points
|
||||
```bash
|
||||
# List all restore points
|
||||
./auto-commit.sh list
|
||||
|
||||
# Clean up old ones (keeps last 10)
|
||||
./auto-commit.sh cleanup
|
||||
```
|
||||
|
||||
## 🎯 Benefits
|
||||
|
||||
1. **Never Lose Work**: Changes are saved every 30 seconds automatically
|
||||
2. **Easy Recovery**: Restore points let you go back to working states
|
||||
3. **Experiment Safely**: Try changes knowing you can always revert
|
||||
4. **Claude Restarts**: No more losing progress when Claude session ends
|
||||
5. **Version History**: Full git history of all changes with timestamps
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
### Modify Watch Settings
|
||||
Edit `watch-and-commit.js`:
|
||||
```javascript
|
||||
const COMMIT_DELAY = 30000; // 30 seconds
|
||||
const MAX_COMMITS_PER_HOUR = 10;
|
||||
const WATCH_DIRS = ['components', 'app', 'lib', 'styles'];
|
||||
```
|
||||
|
||||
### Modify Auto-Commit Behavior
|
||||
Edit `auto-commit.sh` to change commit message format or add custom logic.
|
||||
|
||||
## 🛟 Recovery Scenarios
|
||||
|
||||
### Claude Gets Restarted
|
||||
Your work is automatically saved! Just continue from where you left off.
|
||||
|
||||
### Experimental Changes Break Things
|
||||
```bash
|
||||
# List restore points to find a good one
|
||||
./auto-commit.sh list
|
||||
|
||||
# Checkout the restore point
|
||||
git checkout restore-point-20250129-143022
|
||||
|
||||
# Or continue from main with your auto-commits
|
||||
git checkout main
|
||||
git log --oneline -10 # See recent auto-commits
|
||||
```
|
||||
|
||||
### Need to Go Back a Few Commits
|
||||
```bash
|
||||
# See recent commits
|
||||
git log --oneline -10
|
||||
|
||||
# Reset to a specific commit (keep files)
|
||||
git reset --soft HEAD~3
|
||||
|
||||
# Or create a new branch from specific commit
|
||||
git checkout -b fix-attempt abc1234
|
||||
```
|
||||
|
||||
## 🚦 Status Indicators
|
||||
|
||||
The watcher shows:
|
||||
- 🔍 **Started**: Auto-commit watcher is running
|
||||
- 📝 **File changed**: A file was modified
|
||||
- 🔄 **Performing auto-commit**: About to save changes
|
||||
- ✅ **Auto-commit successful**: Changes saved
|
||||
- 🔖 **Creating restore point**: Making a backup branch
|
||||
- ⏸️ **Rate limit reached**: Too many commits, pausing
|
||||
|
||||
## 🎮 Quick Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `npm run watch-commit` | Start automatic file watching |
|
||||
| `npm run save` | Immediate manual commit |
|
||||
| `npm run restore-point` | Create backup branch |
|
||||
| `./auto-commit.sh list` | Show restore points |
|
||||
| `./auto-commit.sh cleanup` | Remove old restore points |
|
||||
| `git checkout restore-point-XXXXXX` | Restore to backup |
|
||||
| `git log --oneline -10` | See recent commits |
|
||||
|
||||
---
|
||||
|
||||
**Pro Tip**: Always run `npm run watch-commit` when starting work with Claude to ensure nothing gets lost! 🛡️
|
||||
103
PM2-QUICK-REFERENCE.md
Normal file
103
PM2-QUICK-REFERENCE.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# PM2 Auto-Commit Service - Quick Reference
|
||||
|
||||
## ✅ Service Status: RUNNING
|
||||
The auto-commit watcher is now running as a PM2 background service!
|
||||
|
||||
## 🚀 Quick Commands
|
||||
|
||||
### Service Management
|
||||
```bash
|
||||
# Check service status
|
||||
npm run pm2:status
|
||||
|
||||
# View auto-commit logs
|
||||
npm run services:logs
|
||||
|
||||
# Stop auto-commit service
|
||||
npm run services:stop
|
||||
|
||||
# Start auto-commit service
|
||||
npm run services:start
|
||||
|
||||
# Restart auto-commit service
|
||||
./start-services.sh restart
|
||||
```
|
||||
|
||||
### Manual Operations
|
||||
```bash
|
||||
# Save changes immediately
|
||||
npm run save "Your message"
|
||||
|
||||
# Create restore point
|
||||
npm run restore-point "Before big changes"
|
||||
|
||||
# List restore points
|
||||
./auto-commit.sh list
|
||||
```
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Real-time Monitoring
|
||||
```bash
|
||||
# PM2 monitoring dashboard
|
||||
npm run pm2:monit
|
||||
|
||||
# Live log streaming
|
||||
pm2 logs timeshift-auto-commit
|
||||
```
|
||||
|
||||
### Log Files
|
||||
- **Output**: `/home/klas/timeshift/logs/auto-commit.out.log`
|
||||
- **Errors**: `/home/klas/timeshift/logs/auto-commit.error.log`
|
||||
- **Combined**: `/home/klas/timeshift/logs/auto-commit.log`
|
||||
|
||||
## ⚙️ How It Works
|
||||
|
||||
1. **File Watching**: Monitors `components/`, `app/`, `lib/` directories
|
||||
2. **Smart Delay**: Waits 30 seconds after last change
|
||||
3. **Auto-Commit**: Creates timestamped git commits
|
||||
4. **Rate Limiting**: Max 10 commits per hour
|
||||
5. **Restore Points**: Creates backup branches every 30 minutes
|
||||
|
||||
## 🛡️ Backup & Recovery
|
||||
|
||||
### Automatic Backups
|
||||
- ✅ Auto-commits every 30 seconds when files change
|
||||
- ✅ Restore points every 30 minutes
|
||||
- ✅ Session restore point on startup
|
||||
|
||||
### Manual Recovery
|
||||
```bash
|
||||
# See all restore points
|
||||
./auto-commit.sh list
|
||||
|
||||
# Restore to specific point
|
||||
git checkout restore-point-20250729-142449
|
||||
|
||||
# Go back to main
|
||||
git checkout main
|
||||
|
||||
# See recent auto-commits
|
||||
git log --oneline -10
|
||||
```
|
||||
|
||||
## 🔧 Process Info
|
||||
- **Service Name**: `timeshift-auto-commit`
|
||||
- **Process ID**: Check with `npm run pm2:status`
|
||||
- **Auto-restart**: Yes (if crashes)
|
||||
- **Max Memory**: 200MB limit
|
||||
- **Log Rotation**: Managed by PM2
|
||||
|
||||
## 🎯 Benefits Achieved
|
||||
|
||||
✅ **No more lost work** - Changes saved every 30 seconds
|
||||
✅ **Claude restart proof** - Survives session restarts
|
||||
✅ **Background operation** - Runs independently
|
||||
✅ **Auto-recovery** - PM2 restarts if crashes
|
||||
✅ **Full monitoring** - Logs and status tracking
|
||||
✅ **Easy management** - Simple npm commands
|
||||
|
||||
---
|
||||
|
||||
**🎉 Success**: Your work is now automatically protected!
|
||||
The service is running in the background and will continue even if Claude restarts.
|
||||
106
auto-commit.sh
Executable file
106
auto-commit.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Auto-commit script for timeshift project
|
||||
# Usage: ./auto-commit.sh [message]
|
||||
|
||||
set -e
|
||||
|
||||
# Function to auto-commit changes
|
||||
auto_commit() {
|
||||
local message="$1"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# Check if there are any changes
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "🔄 Auto-committing changes at $timestamp"
|
||||
|
||||
# Add all changes
|
||||
git add .
|
||||
|
||||
# Create commit message
|
||||
if [[ -z "$message" ]]; then
|
||||
message="Auto-commit: Save work in progress"
|
||||
fi
|
||||
|
||||
# Commit with timestamp
|
||||
git commit -m "$(cat <<EOF
|
||||
$message
|
||||
|
||||
Auto-saved at $timestamp
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
|
||||
echo "✅ Changes committed successfully"
|
||||
|
||||
# Show short log
|
||||
git log --oneline -3
|
||||
else
|
||||
echo "📝 No changes to commit at $timestamp"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to create a safe restore point
|
||||
create_restore_point() {
|
||||
local description="$1"
|
||||
local branch_name="restore-point-$(date '+%Y%m%d-%H%M%S')"
|
||||
|
||||
echo "🔖 Creating restore point: $branch_name"
|
||||
|
||||
# Commit current changes first
|
||||
auto_commit "Save before creating restore point: $description"
|
||||
|
||||
# Create a new branch as restore point
|
||||
git branch "$branch_name"
|
||||
|
||||
echo "✅ Restore point created: $branch_name"
|
||||
echo "📋 To restore later, run: git checkout $branch_name"
|
||||
}
|
||||
|
||||
# Function to show available restore points
|
||||
list_restore_points() {
|
||||
echo "📋 Available restore points:"
|
||||
git branch | grep "restore-point-" | sed 's/^..//' | sort -r
|
||||
}
|
||||
|
||||
# Function to clean old restore points (keep last 10)
|
||||
cleanup_restore_points() {
|
||||
echo "🧹 Cleaning old restore points (keeping last 10)..."
|
||||
git branch | grep "restore-point-" | sed 's/^..//' | sort -r | tail -n +11 | while read branch; do
|
||||
git branch -D "$branch" 2>/dev/null && echo "🗑️ Deleted old restore point: $branch"
|
||||
done
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
case "$1" in
|
||||
"commit")
|
||||
auto_commit "$2"
|
||||
;;
|
||||
"restore-point")
|
||||
create_restore_point "$2"
|
||||
;;
|
||||
"list")
|
||||
list_restore_points
|
||||
;;
|
||||
"cleanup")
|
||||
cleanup_restore_points
|
||||
;;
|
||||
*)
|
||||
echo "📚 Auto-commit utility for timeshift project"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $0 commit [message] - Auto-commit current changes"
|
||||
echo " $0 restore-point [desc] - Create a restore point branch"
|
||||
echo " $0 list - List available restore points"
|
||||
echo " $0 cleanup - Clean old restore points"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 commit 'Fixed spreadsheet layout'"
|
||||
echo " $0 restore-point 'Before major refactor'"
|
||||
echo ""
|
||||
auto_commit "$1"
|
||||
;;
|
||||
esac
|
||||
32
components/test-component.tsx
Normal file
32
components/test-component.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
interface TestComponentProps {
|
||||
teamId: string
|
||||
teamName: string
|
||||
}
|
||||
|
||||
export function TestComponent({ teamId, teamName }: TestComponentProps) {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle className="flex items-center gap-2">{teamName} - Test Component</CardTitle>
|
||||
<CardDescription>Testing if React components load properly (Team ID: {teamId})</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="border rounded-lg p-4">
|
||||
<p>This is a test component to verify React is working.</p>
|
||||
<p>If you can see this, the basic React setup is functional.</p>
|
||||
<p>Auto-commit test: {new Date().toISOString()}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ interface TimeshiftSpreadsheetProps {
|
||||
teamName: string
|
||||
}
|
||||
|
||||
export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpreadsheetProps) {
|
||||
export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetProps) {
|
||||
const spreadsheetRef = React.useRef<HTMLDivElement>(null)
|
||||
const jspreadsheetInstance = React.useRef<unknown>(null)
|
||||
const currentDate = new Date()
|
||||
@@ -55,7 +55,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
const yearRow = ["rok"]
|
||||
const monthRow = ["měsíc"]
|
||||
const dateRow = ["den"]
|
||||
const shiftRow = [`Pohotovost ${_teamId.toUpperCase()}`]
|
||||
const shiftRow = [`Pohotovost ${teamId.toUpperCase()}`]
|
||||
|
||||
// Generate columns for each day from prevMonthStart to nextMonthEnd
|
||||
const currentDate = new Date(prevMonthStart)
|
||||
@@ -102,6 +102,14 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
"Pohotovost IT"
|
||||
]
|
||||
|
||||
// Add separator column and "Práce mimo směnu" column
|
||||
titleRow.push("", "") // Empty separator + empty for merged cell
|
||||
dayNameRow.push("", "Práce mimo směnu") // Empty separator + the text
|
||||
yearRow.push("", "") // Empty separator + empty for merged cell
|
||||
monthRow.push("", "") // Empty separator + empty for merged cell
|
||||
dateRow.push("", "") // Empty separator + empty for merged cell
|
||||
shiftRow.push("", "") // Empty separator + empty for merged cell
|
||||
|
||||
const employeeRows = employees.map(name => {
|
||||
const row = [name]
|
||||
// Add empty cells for each day/night pair
|
||||
@@ -119,7 +127,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
|
||||
// Sample data for different teams (fallback)
|
||||
const getTeamData = (_teamId: string) => {
|
||||
const getTeamData = (teamId: string) => {
|
||||
const baseData = [
|
||||
["Employee", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
||||
["John Smith", "08:00-16:00", "08:00-16:00", "08:00-16:00", "08:00-16:00", "08:00-16:00", "OFF", "OFF"],
|
||||
@@ -212,11 +220,11 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
console.log("Monthly data generated successfully")
|
||||
} else {
|
||||
console.log("Using basic team data")
|
||||
data = getTeamData(_teamId)
|
||||
data = getTeamData(teamId)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error generating data:", error)
|
||||
data = getTeamData(_teamId)
|
||||
data = getTeamData(teamId)
|
||||
}
|
||||
|
||||
console.log("Data generated:", data.length, "rows, first row:", data[0]?.length, "columns")
|
||||
@@ -232,6 +240,12 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
// Generate styles for day/night shifts based on the Excel pattern
|
||||
const styles: Record<string, string> = {}
|
||||
if (selectedMonth && selectedYear) {
|
||||
// Make first row (row 1) taller - 97px
|
||||
for (let col = 0; col < (data[0]?.length || 0); col++) {
|
||||
const colLetter = getExcelColumnName(col)
|
||||
styles[`${colLetter}1`] = "height: 97px;"
|
||||
}
|
||||
|
||||
// Make day names row (row 2) taller
|
||||
for (let col = 0; col < (data[0]?.length || 0); col++) {
|
||||
const colLetter = getExcelColumnName(col)
|
||||
@@ -249,7 +263,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
|
||||
// Style weekend days (Saturday/Sunday in day name row and date rows below)
|
||||
for (let col = 1; col < (data[0]?.length || 0); col += 2) {
|
||||
for (let col = 1; col < (data[0]?.length || 0) - 2; col += 2) { // -2 to exclude separator and Práce mimo směnu columns
|
||||
const dayName = data[1]?.[col]
|
||||
if (dayName === "Sobota" || dayName === "Neděle") {
|
||||
const colLetter = getExcelColumnName(col)
|
||||
@@ -266,6 +280,28 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Style the "Práce mimo směnu" column (last column)
|
||||
const totalCols = data[0]?.length || 0
|
||||
if (totalCols >= 2) {
|
||||
const separatorColIndex = totalCols - 2
|
||||
const praceMimoColIndex = totalCols - 1
|
||||
const separatorColLetter = getExcelColumnName(separatorColIndex)
|
||||
const praceMimoColLetter = getExcelColumnName(praceMimoColIndex)
|
||||
|
||||
// Style separator column with left border
|
||||
for (let row = 2; row <= 6; row++) {
|
||||
styles[`${separatorColLetter}${row}`] = "border-left: 2px solid #000000;"
|
||||
}
|
||||
|
||||
// Style "Práce mimo směnu" column
|
||||
styles[`${praceMimoColLetter}2`] = "border: 1px solid #000000; text-align: center; vertical-align: middle; font-weight: bold; height: 50px;"
|
||||
for (let row = 3; row <= 6; row++) {
|
||||
styles[`${praceMimoColLetter}${row}`] = "border-left: 1px solid #000000; border-right: 1px solid #000000;"
|
||||
}
|
||||
// Bottom border for the last row of the merged cell
|
||||
styles[`${praceMimoColLetter}6`] += " border-bottom: 1px solid #000000;"
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Initializing jspreadsheet with config:", {
|
||||
@@ -293,41 +329,64 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
console.log("jspreadsheet initialized:", !!jspreadsheetInstance.current)
|
||||
|
||||
// Apply cell merges for header rows after initialization
|
||||
if (jspreadsheetInstance.current && selectedMonth && selectedYear) {
|
||||
const instance = jspreadsheetInstance.current as any
|
||||
if (instance.setMerge) {
|
||||
// Merge all pairs in rows 2, 3, 4, 5 (day names, year, month, day)
|
||||
for (let row = 2; row <= 5; row++) {
|
||||
for (let col = 1; col < (data[0]?.length || 0); col += 2) {
|
||||
const colLetter = getExcelColumnName(col)
|
||||
try {
|
||||
// Correct syntax: setMerge(cellAddress, colspan, rowspan)
|
||||
instance.setMerge(`${colLetter}${row}`, 2, 1) // 2 columns, 1 row
|
||||
console.log(`Merged ${colLetter}${row} with 2 columns`)
|
||||
} catch (error) {
|
||||
console.error(`Failed to merge ${colLetter}${row}:`, error)
|
||||
setTimeout(() => {
|
||||
if (jspreadsheetInstance.current && selectedMonth && selectedYear) {
|
||||
const instance = jspreadsheetInstance.current as any
|
||||
if (instance.setMerge) {
|
||||
try {
|
||||
// Merge all pairs in rows 2, 3, 4, 5 (day names, year, month, day) excluding separator and Práce mimo směnu columns
|
||||
const totalCols = data[0]?.length || 0
|
||||
for (let row = 2; row <= 5; row++) {
|
||||
for (let col = 1; col < totalCols - 2; col += 2) { // -2 to exclude separator and Práce mimo směnu columns
|
||||
const colLetter = getExcelColumnName(col)
|
||||
try {
|
||||
// Correct syntax: setMerge(cellAddress, colspan, rowspan)
|
||||
instance.setMerge(`${colLetter}${row}`, 2, 1) // 2 columns, 1 row
|
||||
} catch (error) {
|
||||
// Silently skip merge errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge "Práce mimo směnu" column vertically from rows 2-6
|
||||
const praceMimoColIndex = totalCols - 1
|
||||
const praceMimoColLetter = getExcelColumnName(praceMimoColIndex)
|
||||
try {
|
||||
instance.setMerge(`${praceMimoColLetter}2`, 1, 5) // 1 column, 5 rows (2-6)
|
||||
} catch (error) {
|
||||
console.error("Error merging Práce mimo směnu column:", error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error during merging:", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
|
||||
// Apply counter-clockwise rotation to data values only (exclude second column which contains field labels)
|
||||
setTimeout(() => {
|
||||
const table = spreadsheetRef.current?.querySelector('.jexcel tbody')
|
||||
if (table) {
|
||||
const rows = table.querySelectorAll('tr')
|
||||
const totalCells = data[0]?.length || 0
|
||||
|
||||
// Rotate data values in rows 2, 3, 4, 5, 6 (day names, year, month, day, shifts) excluding first two columns
|
||||
// Rotate data values in rows 2, 3, 4, 5, 6 (day names, year, month, day, shifts)
|
||||
;[1, 2, 3, 4, 5].forEach(rowIndex => {
|
||||
if (rows[rowIndex]) {
|
||||
const cells = rows[rowIndex].querySelectorAll('td')
|
||||
cells.forEach((cell, cellIndex) => {
|
||||
// Skip first two columns (row numbers and field labels)
|
||||
if (cellIndex > 1) {
|
||||
const originalText = cell.textContent
|
||||
// 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>`
|
||||
// Skip first two columns (row numbers and field labels), separator column, but include Práce mimo směnu
|
||||
if (cellIndex > 1 && cellIndex < totalCells + 1) { // +1 because of row number column
|
||||
const originalText = cell.textContent?.trim()
|
||||
if (originalText) {
|
||||
// Special handling for "Práce mimo směnu" text
|
||||
if (originalText === "Práce mimo směnu") {
|
||||
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 80px; display: flex; align-items: center; justify-content: center; white-space: nowrap; font-weight: bold;">${originalText}</div>`
|
||||
} else if (cellIndex < totalCells - 1) { // Don't rotate separator column (empty)
|
||||
// Use 12px font for all other 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>`
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -366,7 +425,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
jspreadsheetInstance.current.destroy()
|
||||
}
|
||||
}
|
||||
}, [_teamId, selectedMonth, selectedYear, forceUpdate])
|
||||
}, [teamId, selectedMonth, selectedYear, forceUpdate])
|
||||
|
||||
const handleSave = () => {
|
||||
if (jspreadsheetInstance.current) {
|
||||
@@ -400,11 +459,6 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
}
|
||||
|
||||
const handleAddEmployee = () => {
|
||||
if (jspreadsheetInstance.current) {
|
||||
jspreadsheetInstance.current.insertRow()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="w-full">
|
||||
|
||||
44
ecosystem.config.js
Normal file
44
ecosystem.config.js
Normal file
@@ -0,0 +1,44 @@
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'timeshift-auto-commit',
|
||||
script: './watch-and-commit.js',
|
||||
cwd: '/home/klas/timeshift',
|
||||
watch: false, // We don't want PM2 to restart on file changes since we're watching files ourselves
|
||||
autorestart: true,
|
||||
max_restarts: 10,
|
||||
min_uptime: '10s',
|
||||
restart_delay: 5000,
|
||||
env: {
|
||||
NODE_ENV: 'development',
|
||||
PWD: '/home/klas/timeshift'
|
||||
},
|
||||
log_file: '/home/klas/timeshift/logs/auto-commit.log',
|
||||
out_file: '/home/klas/timeshift/logs/auto-commit.out.log',
|
||||
error_file: '/home/klas/timeshift/logs/auto-commit.error.log',
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||
merge_logs: true,
|
||||
max_memory_restart: '200M'
|
||||
},
|
||||
{
|
||||
name: 'timeshift-dev',
|
||||
script: 'npm',
|
||||
args: 'run dev',
|
||||
cwd: '/home/klas/timeshift',
|
||||
watch: false,
|
||||
autorestart: true,
|
||||
max_restarts: 5,
|
||||
min_uptime: '30s',
|
||||
restart_delay: 10000,
|
||||
env: {
|
||||
NODE_ENV: 'development',
|
||||
PORT: 3000
|
||||
},
|
||||
log_file: '/home/klas/timeshift/logs/dev-server.log',
|
||||
out_file: '/home/klas/timeshift/logs/dev-server.out.log',
|
||||
error_file: '/home/klas/timeshift/logs/dev-server.error.log',
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||
merge_logs: true
|
||||
}
|
||||
]
|
||||
};
|
||||
2
logs/auto-commit.error.log
Normal file
2
logs/auto-commit.error.log
Normal file
@@ -0,0 +1,2 @@
|
||||
2025-07-29 14:27:23 +02:00: (node:489145) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||
2025-07-29 14:27:23 +02:00: (Use `node --trace-deprecation ...` to show where the warning was created)
|
||||
32
logs/auto-commit.log
Normal file
32
logs/auto-commit.log
Normal file
@@ -0,0 +1,32 @@
|
||||
2025-07-29 14:27:23 +02:00: 🚀 Timeshift Auto-Commit Watcher Started
|
||||
2025-07-29 14:27:23 +02:00: ==========================================
|
||||
2025-07-29 14:27:23 +02:00: 📅 Start time: 2025-07-29T12:27:23.269Z
|
||||
2025-07-29 14:27:23 +02:00: 📁 Watching directories: components, app, lib, styles
|
||||
2025-07-29 14:27:23 +02:00: 📄 File extensions: .tsx, .ts, .js, .jsx, .css, .scss, .json
|
||||
2025-07-29 14:27:23 +02:00: ⏱️ Commit delay: 30s
|
||||
2025-07-29 14:27:23 +02:00: 🚦 Max commits per hour: 10
|
||||
2025-07-29 14:27:23 +02:00: 🔧 Process ID: 489145
|
||||
2025-07-29 14:27:23 +02:00: ==========================================
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/components
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/app
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/lib
|
||||
2025-07-29 14:27:23 +02:00: ⚠️ Directory not found: /home/klas/timeshift/styles
|
||||
2025-07-29 14:27:23 +02:00: 🚀 Auto-commit system ready! Press Ctrl+C to stop.
|
||||
2025-07-29 14:27:23 +02:00: 📋 Commands available:
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh commit [message]
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh restore-point [description]
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh list
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh cleanup
|
||||
2025-07-29 14:27:23 +02:00: (node:489145) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||
2025-07-29 14:27:23 +02:00: (Use `node --trace-deprecation ...` to show where the warning was created)
|
||||
2025-07-29 14:27:28 +02:00: 🔖 Creating restore point...
|
||||
2025-07-29 14:27:28 +02:00: ✅ Restore point created
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:31:08 +02:00: 🔄 Performing auto-commit...
|
||||
2025-07-29 14:31:08 +02:00: ✅ Auto-commit successful
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:46 +02:00: 🔄 Performing auto-commit...
|
||||
30
logs/auto-commit.out.log
Normal file
30
logs/auto-commit.out.log
Normal file
@@ -0,0 +1,30 @@
|
||||
2025-07-29 14:27:23 +02:00: 🚀 Timeshift Auto-Commit Watcher Started
|
||||
2025-07-29 14:27:23 +02:00: ==========================================
|
||||
2025-07-29 14:27:23 +02:00: 📅 Start time: 2025-07-29T12:27:23.269Z
|
||||
2025-07-29 14:27:23 +02:00: 📁 Watching directories: components, app, lib, styles
|
||||
2025-07-29 14:27:23 +02:00: 📄 File extensions: .tsx, .ts, .js, .jsx, .css, .scss, .json
|
||||
2025-07-29 14:27:23 +02:00: ⏱️ Commit delay: 30s
|
||||
2025-07-29 14:27:23 +02:00: 🚦 Max commits per hour: 10
|
||||
2025-07-29 14:27:23 +02:00: 🔧 Process ID: 489145
|
||||
2025-07-29 14:27:23 +02:00: ==========================================
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/components
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/app
|
||||
2025-07-29 14:27:23 +02:00: 👀 Watching: /home/klas/timeshift/lib
|
||||
2025-07-29 14:27:23 +02:00: ⚠️ Directory not found: /home/klas/timeshift/styles
|
||||
2025-07-29 14:27:23 +02:00: 🚀 Auto-commit system ready! Press Ctrl+C to stop.
|
||||
2025-07-29 14:27:23 +02:00: 📋 Commands available:
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh commit [message]
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh restore-point [description]
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh list
|
||||
2025-07-29 14:27:23 +02:00: ./auto-commit.sh cleanup
|
||||
2025-07-29 14:27:28 +02:00: 🔖 Creating restore point...
|
||||
2025-07-29 14:27:28 +02:00: ✅ Restore point created
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:30:38 +02:00: 📝 File changed: components/test-component.tsx (change)
|
||||
2025-07-29 14:31:08 +02:00: 🔄 Performing auto-commit...
|
||||
2025-07-29 14:31:08 +02:00: ✅ Auto-commit successful
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:16 +02:00: 📝 File changed: components/timeshift-spreadsheet.tsx (change)
|
||||
2025-07-29 14:35:46 +02:00: 🔄 Performing auto-commit...
|
||||
16
package.json
16
package.json
@@ -6,7 +6,21 @@
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"auto-commit": "./auto-commit.sh",
|
||||
"watch-commit": "node watch-and-commit.js",
|
||||
"save": "./auto-commit.sh commit",
|
||||
"restore-point": "./auto-commit.sh restore-point",
|
||||
"pm2:start": "pm2 start ecosystem.config.js",
|
||||
"pm2:stop": "pm2 stop ecosystem.config.js",
|
||||
"pm2:restart": "pm2 restart ecosystem.config.js",
|
||||
"pm2:delete": "pm2 delete ecosystem.config.js",
|
||||
"pm2:logs": "pm2 logs timeshift-auto-commit",
|
||||
"pm2:status": "pm2 status",
|
||||
"pm2:monit": "pm2 monit",
|
||||
"services:start": "pm2 start ecosystem.config.js --only timeshift-auto-commit",
|
||||
"services:stop": "pm2 stop timeshift-auto-commit",
|
||||
"services:logs": "pm2 logs timeshift-auto-commit --lines 50"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
|
||||
BIN
screenshots/Snímek obrazovky 2025-07-29 141447.png
Normal file
BIN
screenshots/Snímek obrazovky 2025-07-29 141447.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
103
start-services.sh
Executable file
103
start-services.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Timeshift Project Services Startup Script
|
||||
# This script starts the auto-commit watcher and development server using PM2
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting Timeshift Project Services"
|
||||
echo "========================================"
|
||||
|
||||
# Function to check if PM2 is installed
|
||||
check_pm2() {
|
||||
if ! command -v pm2 &> /dev/null; then
|
||||
echo "❌ PM2 is not installed. Please install it first:"
|
||||
echo " npm install -g pm2"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ PM2 is available"
|
||||
}
|
||||
|
||||
# Function to start services
|
||||
start_services() {
|
||||
echo ""
|
||||
echo "🔧 Starting services..."
|
||||
|
||||
# Stop any existing services first
|
||||
pm2 delete timeshift-auto-commit 2>/dev/null || true
|
||||
pm2 delete timeshift-dev 2>/dev/null || true
|
||||
|
||||
# Start the auto-commit watcher
|
||||
echo "📁 Starting auto-commit watcher..."
|
||||
pm2 start ecosystem.config.js --only timeshift-auto-commit
|
||||
|
||||
# Wait a moment for the service to start
|
||||
sleep 2
|
||||
|
||||
echo ""
|
||||
echo "✅ Services started successfully!"
|
||||
echo ""
|
||||
|
||||
# Show status
|
||||
pm2 status
|
||||
|
||||
echo ""
|
||||
echo "📋 Service Management Commands:"
|
||||
echo " npm run services:logs - View auto-commit logs"
|
||||
echo " npm run services:stop - Stop auto-commit service"
|
||||
echo " npm run pm2:status - Check all PM2 services"
|
||||
echo " npm run pm2:monit - Open PM2 monitoring"
|
||||
echo ""
|
||||
echo "🌐 Development Server:"
|
||||
echo " npm run dev - Start Next.js dev server manually"
|
||||
echo " npm run pm2:start - Start both services with PM2"
|
||||
echo ""
|
||||
echo "💾 Manual Save Commands:"
|
||||
echo " npm run save - Save changes immediately"
|
||||
echo " npm run restore-point - Create a restore point"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to show logs
|
||||
show_logs() {
|
||||
echo "📋 Auto-commit service logs (last 20 lines):"
|
||||
echo "============================================"
|
||||
pm2 logs timeshift-auto-commit --lines 20 --nostream
|
||||
}
|
||||
|
||||
# Main execution
|
||||
case "$1" in
|
||||
"logs")
|
||||
show_logs
|
||||
;;
|
||||
"stop")
|
||||
echo "🛑 Stopping auto-commit service..."
|
||||
pm2 stop timeshift-auto-commit
|
||||
echo "✅ Service stopped"
|
||||
;;
|
||||
"restart")
|
||||
echo "🔄 Restarting auto-commit service..."
|
||||
pm2 restart timeshift-auto-commit
|
||||
echo "✅ Service restarted"
|
||||
;;
|
||||
"status")
|
||||
pm2 status
|
||||
;;
|
||||
*)
|
||||
check_pm2
|
||||
start_services
|
||||
|
||||
# Option to show logs
|
||||
echo "👀 Would you like to see the logs? (y/n)"
|
||||
read -t 10 -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
show_logs
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "🎯 Auto-commit watcher is now running in the background!"
|
||||
echo "🔄 Your changes will be automatically saved every 30 seconds."
|
||||
echo "🛡️ No more lost work when Claude restarts!"
|
||||
2
test-auto-commit.txt
Normal file
2
test-auto-commit.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
This is a test file to verify auto-commit is working.
|
||||
Created at: 2025-07-29 14:27:30
|
||||
189
watch-and-commit.js
Executable file
189
watch-and-commit.js
Executable file
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { exec } = require('child_process');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
// Configuration
|
||||
const WATCH_DIRS = ['components', 'app', 'lib', 'styles'];
|
||||
const WATCH_EXTENSIONS = ['.tsx', '.ts', '.js', '.jsx', '.css', '.scss', '.json'];
|
||||
const COMMIT_DELAY = 30000; // 30 seconds delay before auto-commit
|
||||
const MAX_COMMITS_PER_HOUR = 10;
|
||||
|
||||
class AutoCommitWatcher {
|
||||
constructor() {
|
||||
this.commitQueue = new Set();
|
||||
this.commitTimeout = null;
|
||||
this.commitsThisHour = 0;
|
||||
this.lastCommitTime = 0;
|
||||
this.startTime = new Date();
|
||||
|
||||
// Reset commit counter every hour
|
||||
setInterval(() => {
|
||||
this.commitsThisHour = 0;
|
||||
console.log('🔄 Hourly reset: Commit counter reset to 0');
|
||||
}, 3600000);
|
||||
|
||||
// Log startup info
|
||||
console.log('🚀 Timeshift Auto-Commit Watcher Started');
|
||||
console.log('==========================================');
|
||||
console.log(`📅 Start time: ${this.startTime.toISOString()}`);
|
||||
console.log(`📁 Watching directories: ${WATCH_DIRS.join(', ')}`);
|
||||
console.log(`📄 File extensions: ${WATCH_EXTENSIONS.join(', ')}`);
|
||||
console.log(`⏱️ Commit delay: ${COMMIT_DELAY/1000}s`);
|
||||
console.log(`🚦 Max commits per hour: ${MAX_COMMITS_PER_HOUR}`);
|
||||
console.log(`🔧 Process ID: ${process.pid}`);
|
||||
console.log('==========================================');
|
||||
}
|
||||
|
||||
start() {
|
||||
WATCH_DIRS.forEach(dir => {
|
||||
const fullPath = path.join(process.cwd(), dir);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
this.watchDirectory(fullPath);
|
||||
console.log(`👀 Watching: ${fullPath}`);
|
||||
} else {
|
||||
console.log(`⚠️ Directory not found: ${fullPath}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watchDirectory(dirPath) {
|
||||
try {
|
||||
fs.watch(dirPath, { recursive: true }, (eventType, filename) => {
|
||||
if (!filename) return;
|
||||
|
||||
const filePath = path.join(dirPath, filename);
|
||||
const ext = path.extname(filename);
|
||||
|
||||
// Check if file extension is in our watch list
|
||||
if (WATCH_EXTENSIONS.includes(ext)) {
|
||||
this.handleFileChange(filePath, eventType);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`❌ Error watching directory ${dirPath}:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
handleFileChange(filePath, eventType) {
|
||||
const relativePath = path.relative(process.cwd(), filePath);
|
||||
console.log(`📝 File changed: ${relativePath} (${eventType})`);
|
||||
|
||||
// Add to commit queue
|
||||
this.commitQueue.add(relativePath);
|
||||
|
||||
// Clear existing timeout and set new one
|
||||
if (this.commitTimeout) {
|
||||
clearTimeout(this.commitTimeout);
|
||||
}
|
||||
|
||||
this.commitTimeout = setTimeout(() => {
|
||||
this.performAutoCommit();
|
||||
}, COMMIT_DELAY);
|
||||
}
|
||||
|
||||
async performAutoCommit() {
|
||||
// Rate limiting
|
||||
if (this.commitsThisHour >= MAX_COMMITS_PER_HOUR) {
|
||||
console.log(`⏸️ Rate limit reached (${MAX_COMMITS_PER_HOUR} commits/hour). Skipping auto-commit.`);
|
||||
this.commitQueue.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if enough time has passed since last commit
|
||||
const now = Date.now();
|
||||
if (now - this.lastCommitTime < COMMIT_DELAY) {
|
||||
console.log('⏸️ Too soon since last commit. Skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.commitQueue.size === 0) {
|
||||
console.log('📋 No files in commit queue');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if there are actually changes to commit
|
||||
const { stdout: status } = await execAsync('git status --porcelain');
|
||||
if (!status.trim()) {
|
||||
console.log('📝 No actual changes to commit');
|
||||
this.commitQueue.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔄 Performing auto-commit...');
|
||||
|
||||
// Create commit message with changed files
|
||||
const changedFiles = Array.from(this.commitQueue).slice(0, 5); // Limit to 5 files in message
|
||||
const fileList = changedFiles.join(', ');
|
||||
const moreFiles = this.commitQueue.size > 5 ? ` and ${this.commitQueue.size - 5} more` : '';
|
||||
|
||||
const message = `Auto-save: Updated ${fileList}${moreFiles}`;
|
||||
|
||||
// Use our auto-commit script
|
||||
await execAsync(`./auto-commit.sh commit "${message}"`);
|
||||
|
||||
console.log('✅ Auto-commit successful');
|
||||
this.commitsThisHour++;
|
||||
this.lastCommitTime = now;
|
||||
this.commitQueue.clear();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Auto-commit failed:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async createRestorePoint(description = 'Auto restore point') {
|
||||
try {
|
||||
console.log('🔖 Creating restore point...');
|
||||
await execAsync(`./auto-commit.sh restore-point "${description}"`);
|
||||
console.log('✅ Restore point created');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to create restore point:', error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle process termination gracefully
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('\n🛑 Stopping auto-commit watcher...');
|
||||
|
||||
// Perform final commit if there are pending changes
|
||||
try {
|
||||
const { stdout: status } = await execAsync('git status --porcelain');
|
||||
if (status.trim()) {
|
||||
console.log('💾 Saving final changes...');
|
||||
await execAsync('./auto-commit.sh commit "Final auto-save before shutdown"');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error during shutdown save:', error.message);
|
||||
}
|
||||
|
||||
console.log('👋 Auto-commit watcher stopped');
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Start the watcher
|
||||
const watcher = new AutoCommitWatcher();
|
||||
watcher.start();
|
||||
|
||||
// Create restore point on startup
|
||||
setTimeout(() => {
|
||||
watcher.createRestorePoint('Session start');
|
||||
}, 5000);
|
||||
|
||||
// Create periodic restore points (every 30 minutes)
|
||||
setInterval(() => {
|
||||
watcher.createRestorePoint('Periodic backup');
|
||||
}, 30 * 60 * 1000);
|
||||
|
||||
console.log('🚀 Auto-commit system ready! Press Ctrl+C to stop.');
|
||||
console.log('📋 Commands available:');
|
||||
console.log(' ./auto-commit.sh commit [message]');
|
||||
console.log(' ./auto-commit.sh restore-point [description]');
|
||||
console.log(' ./auto-commit.sh list');
|
||||
console.log(' ./auto-commit.sh cleanup');
|
||||
Reference in New Issue
Block a user