Map page v1
This commit is contained in:
parent
2b2cd32847
commit
471d629a93
@ -1,27 +1,22 @@
|
|||||||
from flask import Flask, request, jsonify
|
from flask import Flask, request, jsonify
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
|
||||||
# Initialize CORS
|
|
||||||
app = Flask(__name__)
|
|
||||||
CORS(app)
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
CORS(app) # Enable CORS for all routes
|
||||||
|
|
||||||
# Define the data directory
|
# Data directory and file
|
||||||
DATA_DIR = 'data'
|
DATA_DIR = 'data'
|
||||||
|
DATA_FILE = os.path.join(DATA_DIR, 'journeys.json')
|
||||||
os.makedirs(DATA_DIR, exist_ok=True)
|
os.makedirs(DATA_DIR, exist_ok=True)
|
||||||
|
|
||||||
# Define the data file path
|
# In-memory store (loaded from file on startup)
|
||||||
DATA_FILE = os.path.join(DATA_DIR, 'journeys.json')
|
|
||||||
|
|
||||||
# Initialize journeys list
|
|
||||||
journeys = []
|
journeys = []
|
||||||
|
|
||||||
def load_journeys():
|
def load_journeys():
|
||||||
"""Load journeys from the data file."""
|
"""Load journeys from the JSON file."""
|
||||||
global journeys
|
global journeys
|
||||||
try:
|
try:
|
||||||
if os.path.exists(DATA_FILE):
|
if os.path.exists(DATA_FILE):
|
||||||
@ -34,64 +29,72 @@ def load_journeys():
|
|||||||
journeys = []
|
journeys = []
|
||||||
|
|
||||||
def save_journeys():
|
def save_journeys():
|
||||||
"""Save journeys to the data file."""
|
"""Save journeys to the JSON file."""
|
||||||
try:
|
try:
|
||||||
with open(DATA_FILE, 'w') as f:
|
with open(DATA_FILE, 'w') as f:
|
||||||
json.dump(journeys, f, indent=2)
|
json.dump(journeys, f, indent=2)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error saving journeys: {e}")
|
print(f"Error saving journeys: {e}")
|
||||||
|
|
||||||
# Load journeys when the app starts
|
# Load existing journeys on startup
|
||||||
load_journeys()
|
load_journeys()
|
||||||
|
|
||||||
|
def get_next_id():
|
||||||
|
"""Return the next available ID (simple integer increment)."""
|
||||||
|
if not journeys:
|
||||||
|
return 1
|
||||||
|
return max(j['id'] for j in journeys) + 1
|
||||||
|
|
||||||
@app.route('/api/journeys', methods=['POST'])
|
@app.route('/api/journeys', methods=['POST'])
|
||||||
def create_journey():
|
def create_journey():
|
||||||
"""Create a new journey."""
|
"""Create a new journey."""
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
if not data:
|
||||||
|
return jsonify({'error': 'No data provided'}), 400
|
||||||
|
|
||||||
if not data or 'name' not in data:
|
title = data.get('title')
|
||||||
return jsonify({'error': 'Journey name is required'}), 400
|
if not title:
|
||||||
|
return jsonify({'error': 'Journey title is required'}), 400
|
||||||
|
|
||||||
# Create new journey
|
|
||||||
new_journey = {
|
new_journey = {
|
||||||
'id': len(journeys) + 1,
|
'id': get_next_id(),
|
||||||
'name': data['name'],
|
'title': title,
|
||||||
'description': data.get('description', ''),
|
'description': data.get('description', ''),
|
||||||
'markers': data.get('markers', []),
|
'markers': data.get('markers', []), # list of marker objects
|
||||||
'createdAt': datetime.now().isoformat()
|
'created_at': datetime.now().isoformat()
|
||||||
}
|
}
|
||||||
|
|
||||||
journeys.append(new_journey)
|
journeys.append(new_journey)
|
||||||
save_journeys()
|
save_journeys()
|
||||||
|
|
||||||
return jsonify(new_journey), 201
|
return jsonify(new_journey), 201
|
||||||
|
|
||||||
@app.route('/api/journeys', methods=['GET'])
|
@app.route('/api/journeys', methods=['GET'])
|
||||||
def get_journeys():
|
def get_journeys():
|
||||||
"""Get all journeys."""
|
"""Return all journeys."""
|
||||||
return jsonify(journeys)
|
return jsonify(journeys)
|
||||||
|
|
||||||
@app.route('/api/journeys/<string:journey_id>', methods=['GET'])
|
@app.route('/api/journeys/<int:journey_id>', methods=['GET'])
|
||||||
def get_journey(journey_id):
|
def get_journey(journey_id):
|
||||||
"""Get a specific journey by ID."""
|
"""Return a specific journey by ID."""
|
||||||
journey = next((j for j in journeys if str(j['id']) == journey_id), None)
|
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||||||
if journey:
|
if journey is None:
|
||||||
return jsonify(journey)
|
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
return jsonify({'error': 'Journey not found'}), 404
|
||||||
|
return jsonify(journey)
|
||||||
|
|
||||||
|
@app.route('/api/journeys/<int:journey_id>', methods=['PUT'])
|
||||||
@app.route('/api/journeys/<string:journey_id>', methods=['PUT'])
|
|
||||||
def update_journey(journey_id):
|
def update_journey(journey_id):
|
||||||
"""Update an existing journey."""
|
"""Update an existing journey."""
|
||||||
journey = next((j for j in journeys if str(j['id']) == journey_id), None)
|
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||||||
if not journey:
|
if journey is None:
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
return jsonify({'error': 'Journey not found'}), 404
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
if not data:
|
||||||
|
return jsonify({'error': 'No data provided'}), 400
|
||||||
|
|
||||||
# Update journey fields
|
# Update allowed fields
|
||||||
if 'name' in data:
|
if 'title' in data:
|
||||||
journey['name'] = data['name']
|
journey['title'] = data['title']
|
||||||
if 'description' in data:
|
if 'description' in data:
|
||||||
journey['description'] = data['description']
|
journey['description'] = data['description']
|
||||||
if 'markers' in data:
|
if 'markers' in data:
|
||||||
@ -100,38 +103,33 @@ def update_journey(journey_id):
|
|||||||
save_journeys()
|
save_journeys()
|
||||||
return jsonify(journey)
|
return jsonify(journey)
|
||||||
|
|
||||||
@app.route('/api/journeys/<string:journey_id>', methods=['DELETE'])
|
@app.route('/api/journeys/<int:journey_id>', methods=['DELETE'])
|
||||||
def delete_journey(journey_id):
|
def delete_journey(journey_id):
|
||||||
"""Delete a journey."""
|
"""Delete a journey."""
|
||||||
global journeys
|
global journeys
|
||||||
journey = next((j for j in journeys if str(j['id']) == journey_id), None)
|
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
||||||
if not journey:
|
if journey is None:
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
return jsonify({'error': 'Journey not found'}), 404
|
||||||
|
|
||||||
journeys = [j for j in journeys if str(j['id']) != int(journey_id)]
|
journeys = [j for j in journeys if j['id'] != journey_id]
|
||||||
save_journeys()
|
save_journeys()
|
||||||
|
|
||||||
return jsonify({'message': 'Journey deleted successfully', 'journey': journey})
|
return jsonify({'message': 'Journey deleted successfully', 'journey': journey})
|
||||||
|
|
||||||
@app.route('/api/journeys/health', methods=['GET'])
|
@app.route('/api/journeys/health', methods=['GET'])
|
||||||
def health_check():
|
def health_check():
|
||||||
"""Health check endpoint."""
|
"""Simple health check endpoint."""
|
||||||
return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()})
|
return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()})
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
"""Serve the main HTML page."""
|
"""Root endpoint – just a welcome message."""
|
||||||
return '''
|
return '''
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head><title>Journey Mapper Backend</title></head>
|
||||||
<title>Journey Mapper</title>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
</head>
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Journey Mapper</h1>
|
<h1>Journey Mapper API</h1>
|
||||||
<p>Backend is running. Access API at <a href="/api/journeys">/api/journeys</a></p>
|
<p>Backend is running. Use <code>/api/journeys</code> endpoints.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
'''
|
'''
|
||||||
|
|||||||
138
backend/app2.py
138
backend/app2.py
@ -1,138 +0,0 @@
|
|||||||
from flask import Flask, request, jsonify
|
|
||||||
from flask_cors import CORS
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
CORS(app) # Enable CORS for all routes
|
|
||||||
|
|
||||||
# Data directory and file
|
|
||||||
DATA_DIR = 'data'
|
|
||||||
DATA_FILE = os.path.join(DATA_DIR, 'journeys.json')
|
|
||||||
os.makedirs(DATA_DIR, exist_ok=True)
|
|
||||||
|
|
||||||
# In-memory store (loaded from file on startup)
|
|
||||||
journeys = []
|
|
||||||
|
|
||||||
def load_journeys():
|
|
||||||
"""Load journeys from the JSON file."""
|
|
||||||
global journeys
|
|
||||||
try:
|
|
||||||
if os.path.exists(DATA_FILE):
|
|
||||||
with open(DATA_FILE, 'r') as f:
|
|
||||||
journeys = json.load(f)
|
|
||||||
else:
|
|
||||||
journeys = []
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading journeys: {e}")
|
|
||||||
journeys = []
|
|
||||||
|
|
||||||
def save_journeys():
|
|
||||||
"""Save journeys to the JSON file."""
|
|
||||||
try:
|
|
||||||
with open(DATA_FILE, 'w') as f:
|
|
||||||
json.dump(journeys, f, indent=2)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error saving journeys: {e}")
|
|
||||||
|
|
||||||
# Load existing journeys on startup
|
|
||||||
load_journeys()
|
|
||||||
|
|
||||||
def get_next_id():
|
|
||||||
"""Return the next available ID (simple integer increment)."""
|
|
||||||
if not journeys:
|
|
||||||
return 1
|
|
||||||
return max(j['id'] for j in journeys) + 1
|
|
||||||
|
|
||||||
@app.route('/api/journeys', methods=['POST'])
|
|
||||||
def create_journey():
|
|
||||||
"""Create a new journey."""
|
|
||||||
data = request.get_json()
|
|
||||||
if not data:
|
|
||||||
return jsonify({'error': 'No data provided'}), 400
|
|
||||||
|
|
||||||
title = data.get('title')
|
|
||||||
if not title:
|
|
||||||
return jsonify({'error': 'Journey title is required'}), 400
|
|
||||||
|
|
||||||
new_journey = {
|
|
||||||
'id': get_next_id(),
|
|
||||||
'title': title,
|
|
||||||
'description': data.get('description', ''),
|
|
||||||
'markers': data.get('markers', []), # list of marker objects
|
|
||||||
'created_at': datetime.now().isoformat()
|
|
||||||
}
|
|
||||||
|
|
||||||
journeys.append(new_journey)
|
|
||||||
save_journeys()
|
|
||||||
return jsonify(new_journey), 201
|
|
||||||
|
|
||||||
@app.route('/api/journeys', methods=['GET'])
|
|
||||||
def get_journeys():
|
|
||||||
"""Return all journeys."""
|
|
||||||
return jsonify(journeys)
|
|
||||||
|
|
||||||
@app.route('/api/journeys/<int:journey_id>', methods=['GET'])
|
|
||||||
def get_journey(journey_id):
|
|
||||||
"""Return a specific journey by ID."""
|
|
||||||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
|
||||||
if journey is None:
|
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
|
||||||
return jsonify(journey)
|
|
||||||
|
|
||||||
@app.route('/api/journeys/<int:journey_id>', methods=['PUT'])
|
|
||||||
def update_journey(journey_id):
|
|
||||||
"""Update an existing journey."""
|
|
||||||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
|
||||||
if journey is None:
|
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
if not data:
|
|
||||||
return jsonify({'error': 'No data provided'}), 400
|
|
||||||
|
|
||||||
# Update allowed fields
|
|
||||||
if 'title' in data:
|
|
||||||
journey['title'] = data['title']
|
|
||||||
if 'description' in data:
|
|
||||||
journey['description'] = data['description']
|
|
||||||
if 'markers' in data:
|
|
||||||
journey['markers'] = data['markers']
|
|
||||||
|
|
||||||
save_journeys()
|
|
||||||
return jsonify(journey)
|
|
||||||
|
|
||||||
@app.route('/api/journeys/<int:journey_id>', methods=['DELETE'])
|
|
||||||
def delete_journey(journey_id):
|
|
||||||
"""Delete a journey."""
|
|
||||||
global journeys
|
|
||||||
journey = next((j for j in journeys if j['id'] == journey_id), None)
|
|
||||||
if journey is None:
|
|
||||||
return jsonify({'error': 'Journey not found'}), 404
|
|
||||||
|
|
||||||
journeys = [j for j in journeys if j['id'] != journey_id]
|
|
||||||
save_journeys()
|
|
||||||
return jsonify({'message': 'Journey deleted successfully', 'journey': journey})
|
|
||||||
|
|
||||||
@app.route('/api/journeys/health', methods=['GET'])
|
|
||||||
def health_check():
|
|
||||||
"""Simple health check endpoint."""
|
|
||||||
return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()})
|
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
def index():
|
|
||||||
"""Root endpoint – just a welcome message."""
|
|
||||||
return '''
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head><title>Journey Mapper Backend</title></head>
|
|
||||||
<body>
|
|
||||||
<h1>Journey Mapper API</h1>
|
|
||||||
<p>Backend is running. Use <code>/api/journeys</code> endpoints.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
'''
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(debug=True, port=5000)
|
|
||||||
@ -30,5 +30,53 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"created_at": "2026-03-01T19:02:15.679031"
|
"created_at": "2026-03-01T19:02:15.679031"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"title": "test 1",
|
||||||
|
"description": "sdfdsfafsfsdsf",
|
||||||
|
"markers": [
|
||||||
|
{
|
||||||
|
"lat": 48.705462895790575,
|
||||||
|
"lng": 2.4334716796875,
|
||||||
|
"title": "New Marker",
|
||||||
|
"date": "",
|
||||||
|
"description": "",
|
||||||
|
"videoUrl": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lat": 47.37603463349758,
|
||||||
|
"lng": 2.0654296875000004,
|
||||||
|
"title": "New Marker",
|
||||||
|
"date": "",
|
||||||
|
"description": "",
|
||||||
|
"videoUrl": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lat": 47.25686404408872,
|
||||||
|
"lng": 5.020751953125,
|
||||||
|
"title": "New Marker",
|
||||||
|
"date": "",
|
||||||
|
"description": "",
|
||||||
|
"videoUrl": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lat": 47.25686404408872,
|
||||||
|
"lng": 5.954589843750001,
|
||||||
|
"title": "New Marker",
|
||||||
|
"date": "",
|
||||||
|
"description": "",
|
||||||
|
"videoUrl": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lat": 47.357431944587034,
|
||||||
|
"lng": 7.289428710937501,
|
||||||
|
"title": "New Marker",
|
||||||
|
"date": "",
|
||||||
|
"description": "",
|
||||||
|
"videoUrl": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"created_at": "2026-03-05T13:00:48.757539"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
17
journey.html
17
journey.html
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Journey Timeline</title>
|
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="journey-timeline">
|
|
||||||
<h1 id="journey-title"></h1>
|
|
||||||
<div id="timeline-container"></div>
|
|
||||||
</div>
|
|
||||||
<script src="js/journey-post.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
80
map.html
80
map.html
@ -1,80 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Simple Map Project</title>
|
|
||||||
|
|
||||||
<!-- Leaflet CSS -->
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
||||||
|
|
||||||
<!-- Custom CSS -->
|
|
||||||
<link rel="stylesheet" href="css/map.css">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Your existing inline styles... */
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
```
|
|
||||||
|
|
||||||
map.html
|
|
||||||
```html
|
|
||||||
<<<<<<< SEARCH
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Journey Mapper</title>
|
|
||||||
|
|
||||||
<!-- Leaflet CSS -->
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
||||||
|
|
||||||
<!-- Custom CSS -->
|
|
||||||
<link rel="stylesheet" href="css/map.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="app-container">
|
|
||||||
<div class="sidebar">
|
|
||||||
<div class="journey-panel">
|
|
||||||
<h3><i class="fas fa-route"></i> Journey Manager</h3>
|
|
||||||
|
|
||||||
<!-- Journey Form -->
|
|
||||||
<form id="journey-form" class="journey-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="journey-name"><i class="fas fa-heading"></i> Journey Name:</label>
|
|
||||||
<input type="text" id="journey-name" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="journey-desc"><i class="fas fa-align-left"></i> Description:</label>
|
|
||||||
<textarea id="journey-desc"></textarea>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Markers List -->
|
|
||||||
<h4><i class="fas fa-map-marker-alt"></i> Journey Markers</h4>
|
|
||||||
<div id="markers-container" class="markers-list">
|
|
||||||
<!-- Markers will be added here -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Buttons -->
|
|
||||||
<div class="button-group">
|
|
||||||
<button id="add-marker" class="btn btn-primary"><i class="fas fa-plus"></i> Add Marker</button>
|
|
||||||
<button id="save-journey" class="btn btn-success"><i class="fas fa-save"></i> Save Journey</button>
|
|
||||||
<button id="clear-markers" class="btn btn-danger"><i class="fas fa-trash"></i> Clear Markers</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Map container -->
|
|
||||||
<div id="map" class="map-area"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Leaflet JS -->
|
|
||||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom JavaScript -->
|
|
||||||
<script src="js/main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,189 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Simple Map Project</title>
|
|
||||||
|
|
||||||
<!-- Leaflet CSS -->
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#map {
|
|
||||||
flex: 1;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 300px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
overflow-y: auto
|
|
||||||
}
|
|
||||||
|
|
||||||
.map-controls {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 20px;
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
padding: 8px 12px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: #3887be;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:hover {
|
|
||||||
background: #2c6d95;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="sidebar">
|
|
||||||
<div class="journey-panel">
|
|
||||||
<h3><i class="fas fa-route"></i> Journey Manager</h3>
|
|
||||||
|
|
||||||
<!-- Journey Form -->
|
|
||||||
<div class="journey-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="journey-name"><i class="fas fa-heading"></i> Journey Name:</label>
|
|
||||||
<input type="text" id="journey-name" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="journey-desc"><i class="fas fa-align-left"></i> Description:</label>
|
|
||||||
<textarea id="journey-desc"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Markers List -->
|
|
||||||
<h4><i class="fas fa-map-marker-alt"></i> Journey Markers</h4>
|
|
||||||
<div id="markers-list" class="markers-container">
|
|
||||||
<!-- Markers will be added here -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Buttons -->
|
|
||||||
<div class="button-group">
|
|
||||||
<button id="add-marker" class="btn btn-primary"><i class="fas fa-plus"></i> Add Marker</button>
|
|
||||||
<button id="save-journey" class="btn btn-success"><i class="fas fa-save"></i> Save Journey</button>
|
|
||||||
<button id="clear-markers" class="btn btn-danger"><i class="fas fa-trash"></i> Clear Markers</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="map"></div>
|
|
||||||
|
|
||||||
<!-- Leaflet JS -->
|
|
||||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Initialize the map
|
|
||||||
const map = L.map('map').setView([8.5, 47.3], 10);
|
|
||||||
|
|
||||||
// Add tile layer
|
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
||||||
attribution: '© OpenStreetMap contributors'
|
|
||||||
}).addTo(map);
|
|
||||||
|
|
||||||
// Add controls
|
|
||||||
const controls = document.createElement('div');
|
|
||||||
controls.className = 'map-controls';
|
|
||||||
|
|
||||||
// Zoom controls
|
|
||||||
const zoomInBtn = document.createElement('button');
|
|
||||||
zoomInBtn.className = 'btn';
|
|
||||||
zoomInBtn.innerHTML = '+';
|
|
||||||
zoomInBtn.addEventListener('click', () => map.zoomIn());
|
|
||||||
|
|
||||||
const zoomOutBtn = document.createElement('button');
|
|
||||||
zoomOutBtn.className = 'btn';
|
|
||||||
zoomOutBtn.innerHTML = '-';
|
|
||||||
zoomOutBtn.addEventListener('click', () => map.zoomOut());
|
|
||||||
|
|
||||||
controls.appendChild(zoomInBtn);
|
|
||||||
controls.appendChild(zoomOutBtn);
|
|
||||||
|
|
||||||
document.body.appendChild(controls);
|
|
||||||
|
|
||||||
// Add geolocation control
|
|
||||||
const locateBtn = document.createElement('button');
|
|
||||||
locateBtn.className = 'btn';
|
|
||||||
locateBtn.innerHTML = '📍';
|
|
||||||
locateBtn.addEventListener('click', () => {
|
|
||||||
map.locate({setView: true});
|
|
||||||
});
|
|
||||||
|
|
||||||
controls.appendChild(locateBtn);
|
|
||||||
|
|
||||||
// Marker functionality
|
|
||||||
let markers = [];
|
|
||||||
|
|
||||||
document.getElementById('add-marker').addEventListener('click', () => {
|
|
||||||
map.on('click', function(e) {
|
|
||||||
const marker = L.marker(e.latlng, {draggable: true}).addTo(map);
|
|
||||||
|
|
||||||
marker.bindPopup('<input type="text" placeholder="Enter title">');
|
|
||||||
|
|
||||||
markers.push(marker);
|
|
||||||
|
|
||||||
updateMarkerList();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('clear-markers').addEventListener('click', () => {
|
|
||||||
map.eachLayer(function(layer) {
|
|
||||||
if (layer instanceof L.Marker) {
|
|
||||||
map.removeLayer(layer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
markers = [];
|
|
||||||
updateMarkerList();
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateMarkerList() {
|
|
||||||
const list = document.getElementById('marker-list');
|
|
||||||
list.innerHTML = '';
|
|
||||||
|
|
||||||
markers.forEach((marker, index) => {
|
|
||||||
const li = document.createElement('div');
|
|
||||||
li.textContent = `Marker ${index + 1}: ${marker.getLatLng().lat.toFixed(4)}, ${marker.getLngLat().lng.toFixed(4)}`;
|
|
||||||
list.appendChild(li);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize with some basic markers
|
|
||||||
map.on('ready', () => {
|
|
||||||
const initialMarkers = [
|
|
||||||
[8.5, 47.3],
|
|
||||||
[48.8566, 2.3522]
|
|
||||||
];
|
|
||||||
|
|
||||||
initialMarkers.forEach(lngLat => {
|
|
||||||
const marker = L.marker(lngLat).addTo(map);
|
|
||||||
markers.push(marker);
|
|
||||||
});
|
|
||||||
|
|
||||||
updateMarkerList();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user