RoyAalekh commited on
Commit
30dcd04
Β·
1 Parent(s): 206681c

Fix data persistence: Add database and sample data

Browse files

- Updated .gitignore to allow database files in production
- Added init_db.py to create database with sample tree data
- Added export_trees.py for CSV backup functionality
- Created initial trees.db with 5 sample trees across US cities
- Generated trees.csv backup file
- Fixed hovering pin animation on map (gentle glow instead of pulse)

Resolves issue where trees added locally weren't visible in HF repo.
Database and CSV files now tracked for production deployment.

Files changed (6) hide show
  1. .gitignore +6 -5
  2. data/export_trees.py +51 -0
  3. data/init_db.py +83 -0
  4. data/trees.csv +6 -0
  5. data/trees.db +0 -0
  6. static/map.html +26 -8
.gitignore CHANGED
@@ -17,11 +17,12 @@ env/
17
  *.log
18
  app.log
19
 
20
- # Database
21
- data/
22
- *.db
23
- *.sqlite
24
- *.sqlite3
 
25
 
26
  # Uploads
27
  uploads/
 
17
  *.log
18
  app.log
19
 
20
+ # Database (excluding production db)
21
+ data/*.tmp
22
+ data/*.backup
23
+ # *.db - Allow trees.db for production
24
+ # *.sqlite - Allow for production
25
+ # *.sqlite3 - Allow for production
26
 
27
  # Uploads
28
  uploads/
data/export_trees.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Export trees database to CSV format
4
+ """
5
+
6
+ import sqlite3
7
+ import csv
8
+ from pathlib import Path
9
+
10
+ def export_to_csv():
11
+ """Export trees database to CSV"""
12
+ db_path = Path("data/trees.db")
13
+ csv_path = Path("data/trees.csv")
14
+
15
+ if not db_path.exists():
16
+ print("❌ Database not found. Please run init_db.py first.")
17
+ return
18
+
19
+ conn = sqlite3.connect(db_path)
20
+ cursor = conn.cursor()
21
+
22
+ # Get all trees
23
+ cursor.execute("""
24
+ SELECT id, species, latitude, longitude, diameter, height, age,
25
+ health_status, notes, planted_by, plant_date, created_at, updated_at
26
+ FROM trees
27
+ ORDER BY id
28
+ """)
29
+
30
+ trees = cursor.fetchall()
31
+
32
+ # Write to CSV
33
+ with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
34
+ writer = csv.writer(csvfile)
35
+
36
+ # Write header
37
+ writer.writerow([
38
+ 'id', 'species', 'latitude', 'longitude', 'diameter', 'height', 'age',
39
+ 'health_status', 'notes', 'planted_by', 'plant_date', 'created_at', 'updated_at'
40
+ ])
41
+
42
+ # Write data
43
+ writer.writerows(trees)
44
+
45
+ conn.close()
46
+
47
+ print(f"βœ… Exported {len(trees)} trees to {csv_path}")
48
+ print(f"πŸ“„ CSV file size: {csv_path.stat().st_size} bytes")
49
+
50
+ if __name__ == "__main__":
51
+ export_to_csv()
data/init_db.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Initialize database with sample tree data for TreeTrack application
4
+ """
5
+
6
+ import sqlite3
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ def create_database():
11
+ """Create and initialize the database with sample data"""
12
+ db_path = Path("data/trees.db")
13
+
14
+ # Create the database
15
+ conn = sqlite3.connect(db_path)
16
+ cursor = conn.cursor()
17
+
18
+ # Create the trees table (based on your app.py structure)
19
+ cursor.execute('''
20
+ CREATE TABLE IF NOT EXISTS trees (
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ species TEXT NOT NULL,
23
+ latitude REAL NOT NULL,
24
+ longitude REAL NOT NULL,
25
+ diameter REAL,
26
+ height REAL,
27
+ age INTEGER,
28
+ health_status TEXT DEFAULT 'Good',
29
+ notes TEXT,
30
+ planted_by TEXT,
31
+ plant_date DATE,
32
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
33
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
34
+ )
35
+ ''')
36
+
37
+ # Add some sample trees (using coordinates around different cities)
38
+ sample_trees = [
39
+ ('Oak Tree', 40.7589, -73.9851, 45.5, 15.2, 25, 'Excellent', 'Healthy mature oak in Central Park area', 'TreeTrack Admin', '2023-04-15'),
40
+ ('Maple', 34.0522, -118.2437, 32.1, 12.8, 18, 'Good', 'Beautiful red maple in urban setting', 'TreeTrack Admin', '2023-05-20'),
41
+ ('Pine', 41.8781, -87.6298, 28.3, 18.5, 30, 'Good', 'Evergreen pine providing year-round shade', 'TreeTrack Admin', '2023-06-10'),
42
+ ('Birch', 47.6062, -122.3321, 22.7, 10.3, 12, 'Fair', 'Young birch tree showing good growth', 'TreeTrack Admin', '2023-07-01'),
43
+ ('Cedar', 39.7392, -104.9903, 38.9, 14.7, 22, 'Excellent', 'Mature cedar with excellent health', 'TreeTrack Admin', '2023-08-15'),
44
+ ]
45
+
46
+ cursor.executemany('''
47
+ INSERT INTO trees (species, latitude, longitude, diameter, height, age, health_status, notes, planted_by, plant_date)
48
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
49
+ ''', sample_trees)
50
+
51
+ # Create indexes for better query performance
52
+ cursor.execute('CREATE INDEX IF NOT EXISTS idx_species ON trees(species)')
53
+ cursor.execute('CREATE INDEX IF NOT EXISTS idx_location ON trees(latitude, longitude)')
54
+ cursor.execute('CREATE INDEX IF NOT EXISTS idx_health ON trees(health_status)')
55
+ cursor.execute('CREATE INDEX IF NOT EXISTS idx_created ON trees(created_at)')
56
+
57
+ conn.commit()
58
+ conn.close()
59
+
60
+ print(f"βœ… Database created successfully at {db_path}")
61
+ print(f"πŸ“Š Added {len(sample_trees)} sample trees")
62
+
63
+ # Verify the data
64
+ conn = sqlite3.connect(db_path)
65
+ cursor = conn.cursor()
66
+ cursor.execute("SELECT COUNT(*) FROM trees")
67
+ count = cursor.fetchone()[0]
68
+ print(f"🌳 Total trees in database: {count}")
69
+
70
+ cursor.execute("SELECT species, latitude, longitude FROM trees LIMIT 3")
71
+ sample = cursor.fetchall()
72
+ print("\nπŸ“ Sample tree data:")
73
+ for tree in sample:
74
+ print(f" - {tree[0]} at ({tree[1]:.4f}, {tree[2]:.4f})")
75
+
76
+ conn.close()
77
+
78
+ if __name__ == "__main__":
79
+ try:
80
+ create_database()
81
+ except Exception as e:
82
+ print(f"❌ Error creating database: {e}")
83
+ sys.exit(1)
data/trees.csv ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ id,species,latitude,longitude,diameter,height,age,health_status,notes,planted_by,plant_date,created_at,updated_at
2
+ 1,Oak Tree,40.7589,-73.9851,45.5,15.2,25,Excellent,Healthy mature oak in Central Park area,TreeTrack Admin,2023-04-15,2025-08-08 12:03:44,2025-08-08 12:03:44
3
+ 2,Maple,34.0522,-118.2437,32.1,12.8,18,Good,Beautiful red maple in urban setting,TreeTrack Admin,2023-05-20,2025-08-08 12:03:44,2025-08-08 12:03:44
4
+ 3,Pine,41.8781,-87.6298,28.3,18.5,30,Good,Evergreen pine providing year-round shade,TreeTrack Admin,2023-06-10,2025-08-08 12:03:44,2025-08-08 12:03:44
5
+ 4,Birch,47.6062,-122.3321,22.7,10.3,12,Fair,Young birch tree showing good growth,TreeTrack Admin,2023-07-01,2025-08-08 12:03:44,2025-08-08 12:03:44
6
+ 5,Cedar,39.7392,-104.9903,38.9,14.7,22,Excellent,Mature cedar with excellent health,TreeTrack Admin,2023-08-15,2025-08-08 12:03:44,2025-08-08 12:03:44
data/trees.db ADDED
Binary file (28.7 kB). View file
 
static/map.html CHANGED
@@ -246,14 +246,32 @@
246
  background: #ff6b35;
247
  border: 3px solid white;
248
  border-radius: 50%;
249
- box-shadow: 0 2px 10px rgba(0,0,0,0.3);
250
- animation: pulse 2s infinite;
251
- }
252
-
253
- @keyframes pulse {
254
- 0% { transform: scale(1); opacity: 1; }
255
- 50% { transform: scale(1.1); opacity: 0.7; }
256
- 100% { transform: scale(1); opacity: 1; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
 
259
  /* Loading States */
 
246
  background: #ff6b35;
247
  border: 3px solid white;
248
  border-radius: 50%;
249
+ box-shadow:
250
+ 0 2px 10px rgba(0,0,0,0.3),
251
+ 0 0 15px rgba(255, 107, 53, 0.6),
252
+ 0 0 25px rgba(255, 107, 53, 0.3);
253
+ animation: gentle-glow 3s ease-in-out infinite;
254
+ }
255
+
256
+ @keyframes gentle-glow {
257
+ 0% {
258
+ box-shadow:
259
+ 0 2px 10px rgba(0,0,0,0.3),
260
+ 0 0 15px rgba(255, 107, 53, 0.6),
261
+ 0 0 25px rgba(255, 107, 53, 0.3);
262
+ }
263
+ 50% {
264
+ box-shadow:
265
+ 0 2px 12px rgba(0,0,0,0.4),
266
+ 0 0 20px rgba(255, 107, 53, 0.8),
267
+ 0 0 35px rgba(255, 107, 53, 0.5);
268
+ }
269
+ 100% {
270
+ box-shadow:
271
+ 0 2px 10px rgba(0,0,0,0.3),
272
+ 0 0 15px rgba(255, 107, 53, 0.6),
273
+ 0 0 25px rgba(255, 107, 53, 0.3);
274
+ }
275
  }
276
 
277
  /* Loading States */