aTweet/templates/admin_panel.html

353 lines
15 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel - aTweet</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
.admin-panel { max-width: 1200px; margin: 0 auto; padding: 20px; }
.admin-stats { display: flex; justify-content: space-between; margin-bottom: 30px; }
.stat-card { background-color: var(--primary-color); color: white; border-radius: 10px; padding: 20px; text-align: center; flex: 1; margin: 0 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
.admin-section { background-color: var(--background-color); border-radius: 10px; padding: 20px; margin-bottom: 40px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
.admin-table { width: 100%; border-collapse: collapse; }
.admin-table th, .admin-table td { padding: 12px; text-align: left; border-bottom: 1px solid var(--border-color); }
.admin-table th { background-color: var(--primary-color); color: white; }
.admin-table tr:hover { background-color: var(--hover-color); }
.admin-actions { display: flex; gap: 10px; }
.admin-button { padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.3s; color: white; }
.admin-button-view { background-color: #4CAF50; }
.admin-button-edit { background-color: #2196F3; }
.admin-button-delete { background-color: #f44336; }
.search-bar { margin-bottom: 20px; }
.search-bar input { width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; }
.pagination { display: flex; justify-content: center; margin-top: 20px; }
.pagination button { margin: 0 5px; padding: 5px 10px; background-color: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; }
.dashboard { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
.dashboard-card { background-color: var(--background-color); border-radius: 10px; padding: 20px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
.dashboard-card h3 { margin-top: 0; color: var(--primary-color); }
.quick-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 30px; }
.quick-action-button { padding: 10px 20px; background-color: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<div class="container admin-panel">
<h1>Admin Panel</h1>
<div class="admin-stats">
<div class="stat-card">
<h3>{{ user_count }}</h3>
<p>Total Users</p>
</div>
<div class="stat-card">
<h3>{{ tweet_count }}</h3>
<p>Total Tweets</p>
</div>
<div class="stat-card">
<h3>{{ group_count }}</h3>
<p>Total Groups</p>
</div>
</div>
<div class="dashboard">
<div class="dashboard-card">
<h3>Recent Activity</h3>
<ul id="recentActivity"></ul>
<li>Not implemented yet (lazyass)</li>
</div>
<div class="dashboard-card">
<h3>System Health</h3>
<p>Server Status: <span id="serverStatus">Operational</span></p>
<p>Database Size: <span id="databaseSize">16MB</span></p>
</div>
</div>
<div class="quick-actions">
<button class="quick-action-button" onclick="showBackupModal()">Backup Database</button>
<button class="quick-action-button" onclick="showMaintenanceModal()">Maintenance Mode</button>
<button class="quick-action-button" onclick="showBroadcastModal()">Broadcast Message</button>
</div>
<div class="admin-section">
<h2>Users</h2>
<div class="search-bar">
<input type="text" id="userSearch" placeholder="Search users...">
</div>
<table class="admin-table" id="userTable">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Joined</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.created_at }}</td>
<td class="admin-actions">
<button class="admin-button admin-button-view" onclick="viewUser({{ user.id }})">View</button>
<button class="admin-button admin-button-edit" onclick="editUser({{ user.id }})">Edit</button>
<button class="admin-button admin-button-delete" onclick="deleteUser({{ user.id }})">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<button onclick="changePage(-1, 'userTable')">Previous</button>
<span id="userCurrentPage">1</span>
<button onclick="changePage(1, 'userTable')">Next</button>
</div>
</div>
<div class="admin-section">
<h2>Tweets</h2>
<div class="search-bar">
<input type="text" id="tweetSearch" placeholder="Search tweets...">
</div>
<table class="admin-table" id="tweetTable">
<thead>
<tr>
<th>Content</th>
<th>User</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for tweet in tweets %}
<tr>
<td>{{ tweet.content }}</td>
<td>{{ tweet.username }}</td>
<td>{{ tweet.created_at }}</td>
<td class="admin-actions">
<button class="admin-button admin-button-view" onclick="viewTweet({{ tweet.id }})">View</button>
<button class="admin-button admin-button-delete" onclick="deleteTweet({{ tweet.id }})">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<button onclick="changePage(-1, 'tweetTable')">Previous</button>
<span id="tweetCurrentPage">1</span>
<button onclick="changePage(1, 'tweetTable')">Next</button>
</div>
</div>
<div class="admin-section">
<h2>Groups</h2>
<div class="search-bar">
<input type="text" id="groupSearch" placeholder="Search groups...">
</div>
<table class="admin-table" id="groupTable">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Members</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for group in groups %}
<tr>
<td>{{ group.name }}</td>
<td>{{ group.description }}</td>
<td>{{ group.member_count }}</td>
<td>{{ group.created_at }}</td>
<td class="admin-actions">
<button class="admin-button admin-button-view" onclick="viewGroup({{ group.id }})">View</button>
<button class="admin-button admin-button-edit" onclick="editGroup({{ group.id }})">Edit</button>
<button class="admin-button admin-button-delete" onclick="deleteGroup({{ group.id }})">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<button onclick="changePage(-1, 'groupTable')">Previous</button>
<span id="groupCurrentPage">1</span>
<button onclick="changePage(1, 'groupTable')">Next</button>
</div>
</div>
</div>
<script>
function viewUser(userId) {
window.location.href = `/profile/${userId}`;
}
function editUser(userId) {
const newUsername = prompt("Enter new username:");
const newEmail = prompt("Enter new email:");
if (newUsername && newEmail) {
fetch(`/admin/edit_user/${userId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username: newUsername, email: newEmail }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Failed to edit user');
}
});
}
}
function deleteUser(userId) {
if (confirm('Are you sure you want to delete this user?')) {
fetch(`/admin/delete_user/${userId}`, { method: 'POST' })
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Failed to delete user');
}
});
}
}
function viewTweet(tweetId) {
window.location.href = `/tweet/${tweetId}`;
}
function deleteTweet(tweetId) {
if (confirm('Are you sure you want to delete this tweet?')) {
fetch(`/admin/delete_tweet/${tweetId}`, { method: 'POST' })
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Failed to delete tweet');
}
});
}
}
function viewGroup(groupId) {
window.location.href = `/group/${groupId}`;
}
function editGroup(groupId) {
const newName = prompt("Enter new group name:");
const newDescription = prompt("Enter new group description:");
if (newName && newDescription) {
fetch(`/admin/edit_group/${groupId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: newName, description: newDescription }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Failed to edit group');
}
});
}
}
function deleteGroup(groupId) {
if (confirm('Are you sure you want to delete this group?')) {
fetch(`/admin/delete_group/${groupId}`, { method: 'POST' })
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Failed to delete group');
}
});
}
}
function searchTable(inputId, tableId) {
const input = document.getElementById(inputId);
const filter = input.value.toUpperCase();
const table = document.getElementById(tableId);
const tr = table.getElementsByTagName("tr");
for (let i = 1; i < tr.length; i++) {
let txtValue = tr[i].textContent || tr[i].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
document.getElementById("userSearch").addEventListener("keyup", () => searchTable("userSearch", "userTable"));
document.getElementById("tweetSearch").addEventListener("keyup", () => searchTable("tweetSearch", "tweetTable"));
document.getElementById("groupSearch").addEventListener("keyup", () => searchTable("groupSearch", "groupTable"));
const itemsPerPage = 10;
const currentPages = {
userTable: 1,
tweetTable: 1,
groupTable: 1
};
function changePage(direction, tableId) {
currentPages[tableId] += direction;
if (currentPages[tableId] < 1) currentPages[tableId] = 1;
document.getElementById(`${tableId.replace('Table', 'CurrentPage')}`).textContent = currentPages[tableId];
updateTableDisplay(tableId);
}
function updateTableDisplay(tableId) {
const table = document.getElementById(tableId);
const tr = table.getElementsByTagName("tr");
const start = (currentPages[tableId] - 1) * itemsPerPage + 1;
const end = start + itemsPerPage;
for (let i = 1; i < tr.length; i++) {
if (i >= start && i < end) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
function showBackupModal() {
alert("Database backup functionality not implemented.");
}
function showMaintenanceModal() {
alert("Maintenance mode functionality not implemented.");
}
function showBroadcastModal() {
alert("Broadcast message functionality not implemented.");
}
function updateRecentActivity() {
const recentActivity = document.getElementById("recentActivity");
recentActivity.innerHTML = "<li>not even implemented</li>";
// Initial setup
updateTableDisplay('userTable');
updateTableDisplay('tweetTable');
updateTableDisplay('groupTable');
updateRecentActivity();
</script>
</body>
</html>