Spaces:
Running
Running
File size: 9,912 Bytes
b0f2d3d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
{% extends "base.html" %}
{% block title %}
Moderate Comments - {{ video.title }}
{% endblock %}
{% block content %}
<div class="container mx-auto px-4 py-8">
<!-- Outer container with card styling -->
<div class="bg-white shadow-xl rounded-lg overflow-visible">
<!-- Header section with video title and controls -->
<div class="bg-gradient-to-r from-blue-500 to-purple-600 p-6">
<div class="flex justify-between items-center">
<h1 class="text-3xl font-bold text-white flex items-center">
<i class="fab fa-youtube mr-4 text-red-500"></i>
{{ video.title }}
</h1>
<div class="flex space-x-4">
<button id="refreshCommentsBtn" class="bg-white text-blue-600 px-4 py-2 rounded-lg hover:bg-blue-50 transition duration-300 flex items-center shadow-md">
<i class="fas fa-sync mr-2"></i>Refresh Comments
</button>
<div x-data="{ showSettings: false, saveSettings() {
// Add your save logic here, e.g., update a model or call an API
alert('Settings saved!');
this.showSettings = false; // Optionally hide the settings box after saving
} }" class="relative">
<button @click="showSettings = !showSettings" class="bg-white text-purple-600 px-4 py-2 rounded-lg hover:bg-purple-50 transition duration-300 flex items-center shadow-md">
<i class="fas fa-cog mr-2"></i>Moderation Settings
</button>
<div x-show="showSettings" x-transition class="absolute right-0 mt-2 w-72 bg-white rounded-lg shadow-2xl p-6 z-20 border border-gray-100">
<h3 class="text-xl font-semibold mb-4 text-gray-800">Moderation Settings</h3>
<div class="space-y-4">
<div class="flex items-center">
<input type="checkbox" id="auto-delete" class="mr-3 rounded text-blue-500 focus:ring-blue-400">
<label for="auto-delete" class="text-gray-700">Auto-delete flagged comments</label>
</div>
<div>
<label class="block mb-2 text-gray-700">Gambling Confidence Threshold</label>
<input type="range" min="0" max="1" step="0.05" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer" x-model="threshold" value="0.55">
</div>
<button @click="saveSettings" class="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white py-2 rounded-lg hover:opacity-90 transition duration-300">
Save Settings
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Comments Section -->
<div class="grid md:grid-cols-2 gap-6 p-6">
<!-- Safe Comments Column -->
<div>
<h2 class="text-2xl font-semibold mb-4 flex items-center text-green-600">
<i class="fas fa-check-circle mr-3"></i>Safe Comments
<span class="text-sm text-gray-500 ml-2">({{ safe_comments|length }})</span>
</h2>
<div class="space-y-4">
{% for comment in safe_comments %}
<div class="bg-white p-4 rounded-lg shadow-md border border-gray-100">
<p class="mb-2 text-gray-800">{{ comment.text }}</p>
<div class="text-sm text-gray-600 flex justify-between items-center">
<span class="font-medium">{{ comment.author }}</span>
<span class="text-xs text-green-600">Safe</span>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Flagged Comments Column -->
<div>
<h2 class="text-2xl font-semibold mb-4 flex items-center text-red-600">
<i class="fas fa-exclamation-triangle mr-3"></i>Flagged Comments
<span id="flaggedCount" class="text-sm text-gray-500 ml-2">({{ flagged_comments|length }})</span>
</h2>
<div class="space-y-4">
{% for comment in flagged_comments %}
<div class="comment-card bg-red-50 p-4 rounded-lg shadow-md border border-red-200 relative">
<p class="mb-2 text-gray-800">{{ comment.text }}</p>
<div class="text-sm text-gray-600 flex justify-between items-center">
<span class="font-medium">{{ comment.author }}</span>
<div class="flex space-x-2">
<button data-comment-id="{{ comment.id }}" data-video-id="{{ video.id }}" class="delete-comment-btn bg-red-500 text-white px-3 py-1 rounded hover:bg-red-600 transition duration-300">
Delete
</button>
<button data-comment-id="{{ comment.id }}" data-video-id="{{ video.id }}"class="keep-comment-btn bg-green-500 text-white px-3 py-1 rounded hover:bg-green-600 transition duration-300">
Keep
</button>
</div>
</div>
<div class="mt-2 text-xs text-gray-500">
<strong>Gambling Confidence:</strong> {{ comment.metrics.confidence_score }}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Delete Comment Functionality
document.querySelectorAll('.delete-comment-btn').forEach(button => {
button.addEventListener('click', async function(e) {
e.stopPropagation(); // Ensure this click doesn't affect other handlers
const commentId = this.getAttribute('data-comment-id');
const videoId = this.getAttribute('data-video-id');
const commentCard = this.closest('.comment-card');
try {
const response = await fetch(`/api/comments/${commentId}?video_id=${videoId}`, {
method: 'DELETE'
});
const data = await response.json();
if (data.success) {
// Remove the comment from the DOM
commentCard.remove();
// Optionally, update the flagged comments count
const flaggedCommentsCount = document.querySelector('h2 span');
const currentCount = parseInt(flaggedCommentsCount.textContent.replace(/[()]/g, ''));
flaggedCommentsCount.textContent = `(${currentCount - 1})`;
} else {
alert("Failed to delete comment. Please refresh and try again.");
}
} catch (err) {
console.error(err);
alert("Error deleting comment.");
}
});
});
// Keep Comment Functionality with added debug logging
document.querySelectorAll('.keep-comment-btn').forEach(button => {
button.addEventListener('click', async function(e) {
e.stopPropagation();
const commentId = this.getAttribute('data-comment-id');
const videoId = this.getAttribute('data-video-id');
const commentCard = this.closest('.comment-card');
console.log(`Keep button clicked for commentId: ${commentId}, videoId: ${videoId}`);
try {
// Make the API call to keep the comment on YouTube
const response = await fetch(`/api/comments/keep/${commentId}?video_id=${videoId}`, {
method: 'POST'
});
console.log("Response received from API:", response);
const data = await response.json();
console.log("Parsed response data:", data);
if (data.success) {
// If successful, remove from DOM and update the flagged count
commentCard.remove();
const flaggedCommentsCount = document.querySelector('#flaggedCount');
const currentCount = parseInt(flaggedCommentsCount.textContent);
flaggedCommentsCount.textContent = currentCount - 1;
console.log(`Comment ${commentId} removed, flagged count updated to ${currentCount - 1}`);
} else {
console.error(`API reported error for comment ${commentId}:`, data.error);
alert("Failed to keep comment: " + (data.error || 'Unknown error'));
}
} catch (err) {
console.error(`Error keeping comment ${commentId}:`, err);
alert("Error keeping comment.");
}
});
});
// Refresh Comments Functionality
document.getElementById('refreshCommentsBtn').addEventListener('click', function(e) {
e.stopPropagation(); // Prevent any unwanted event bubbling
const videoId = "{{ video.id }}";
window.location.href = `/video/${videoId}`;
});
});
</script>
{% endblock %}
|