diff --git a/eco_project/backend/app.py b/eco_project/backend/app.py index 7c6eaae..96a112f 100644 --- a/eco_project/backend/app.py +++ b/eco_project/backend/app.py @@ -519,6 +519,56 @@ def videos(): except (FileNotFoundError, json.JSONDecodeError): return jsonify([]) +# Path for the drinking water videos JSON file and its lock file +DRINKING_WATER_VIDEOS_FILE = os.path.join(app.root_path, 'drinking_water_videos.json') +DRINKING_WATER_LOCK_FILE = os.path.join(app.root_path, 'drinking_water_videos.json.lock') + +@app.route('/api/drinking_water_videos', methods=['GET', 'POST']) +def drinking_water_videos(): + if request.method == 'POST': + # Handle video submission + data = request.get_json() + title = data.get('title') + url = data.get('url') + + if not title or not url: + return jsonify({"error": "Title and URL are required."}), 400 + + # Sanitize user input + sanitized_title = bleach.clean(title) + sanitized_url = bleach.clean(url) + + # A simple check to ensure the URL is a YouTube embed URL + if not sanitized_url.startswith("https://www.youtube.com/embed/"): + return jsonify({"error": "Invalid YouTube URL."}), 400 + + with FileLock(DRINKING_WATER_LOCK_FILE): + # Read existing videos + try: + with open(DRINKING_WATER_VIDEOS_FILE, 'r') as f: + videos = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + videos = [] + + # Add new video + videos.append({"title": sanitized_title, "url": sanitized_url}) + + # Write updated videos list back to the file + with open(DRINKING_WATER_VIDEOS_FILE, 'w') as f: + json.dump(videos, f, indent=4) + + return jsonify({"message": "Video added successfully!"}), 201 + + else: # GET request + # Return the list of videos + with FileLock(DRINKING_WATER_LOCK_FILE): + try: + with open(DRINKING_WATER_VIDEOS_FILE, 'r') as f: + videos = json.load(f) + return jsonify(videos) + except (FileNotFoundError, json.JSONDecodeError): + return jsonify([]) + @app.route('/api/chat', methods=['POST']) def chat(): data = request.get_json() diff --git a/eco_project/backend/drinking_water_videos.json.lock b/eco_project/backend/drinking_water_videos.json.lock new file mode 100644 index 0000000..e69de29 diff --git a/eco_project/backend/static/drinking_water_videos.css b/eco_project/backend/static/drinking_water_videos.css new file mode 100644 index 0000000..83618aa --- /dev/null +++ b/eco_project/backend/static/drinking_water_videos.css @@ -0,0 +1,23 @@ +.video-container { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + padding: 20px; +} + +.video-item { + width: 300px; + margin: 15px; + border: 1px solid #ccc; + box-shadow: 0 0 5px rgba(0,0,0,0.1); +} + +.video-item iframe { + width: 100%; + height: 170px; +} + +.video-item-title { + padding: 10px; + font-weight: bold; +} diff --git a/eco_project/backend/static/drinking_water_videos.html b/eco_project/backend/static/drinking_water_videos.html new file mode 100644 index 0000000..10d5963 --- /dev/null +++ b/eco_project/backend/static/drinking_water_videos.html @@ -0,0 +1,39 @@ + + + + + + Drinking Water Videos - Environment Protection + + + + +
+

Drinking Water Video Gallery

+ +
+
+
+

Share a Video

+
+ + + +
+
+
+
+

Featured Videos

+
+ +
+
+
+ + + + diff --git a/eco_project/backend/static/drinking_water_videos.js b/eco_project/backend/static/drinking_water_videos.js new file mode 100644 index 0000000..5d80aa7 --- /dev/null +++ b/eco_project/backend/static/drinking_water_videos.js @@ -0,0 +1,83 @@ +document.addEventListener('DOMContentLoaded', () => { + const videoContainer = document.querySelector('.video-container'); + const videoForm = document.getElementById('video-form'); + + async function fetchVideos() { + try { + const response = await fetch('/api/drinking_water_videos'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const videos = await response.json(); + displayVideos(videos); + } catch (error) { + videoContainer.innerHTML = `

Error fetching videos: ${error.message}

`; + } + } + + function displayVideos(videos) { + if (videos.length === 0) { + videoContainer.innerHTML = '

No videos to display.

'; + return; + } + let html = ''; + videos.forEach(video => { + const embedUrl = video.url.includes('youtube.com/watch?v=') + ? video.url.replace('watch?v=', 'embed/') + : video.url; + + html += ` +
+ +
${video.title}
+
+ `; + }); + videoContainer.innerHTML = html; + } + + videoForm.addEventListener('submit', async (event) => { + event.preventDefault(); + + const titleInput = document.getElementById('video-title'); + const urlInput = document.getElementById('video-url'); + const errorMessage = document.getElementById('error-message'); + + errorMessage.textContent = ''; + + let videoUrl = urlInput.value; + if (videoUrl.includes('youtube.com/watch?v=')) { + videoUrl = videoUrl.replace('watch?v=', 'embed/'); + } + + const newVideo = { + title: titleInput.value, + url: videoUrl, + }; + + try { + const response = await fetch('/api/drinking_water_videos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(newVideo), + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `HTTP error! status: ${response.status}`); + } + + titleInput.value = ''; + urlInput.value = ''; + + fetchVideos(); // Refresh the list of videos + } catch (error) { + console.error('Failed to submit video:', error); + errorMessage.textContent = `Error: ${error.message}`; + } + }); + + fetchVideos(); +});