Report-Generator / templates /classified_edit.html
Jaimodiji's picture
Upload folder using huggingface_hub
c001f24
Raw
History Blame
11.7 kB
{% extends "base.html" %}
{% block title %}Edit Classified Questions{% endblock %}
{% block content %}
<div class="container mt-5">
<div class="card bg-dark text-white">
<div class="card-header d-flex justify-content-between align-items-center">
<h2>Edit Classified Questions</h2>
<a href="/neetprep" class="btn btn-outline-light">Back to NeetPrep Home</a>
</div>
<div class="card-body">
<!-- Filter Form -->
<div class="row mb-3">
<div class="col-md-6">
<input type="text" id="search-input" class="form-control bg-dark text-white" placeholder="Search questions...">
</div>
<div class="col-md-4">
<select id="chapter-filter" class="form-select bg-dark text-white">
<option value="all">All Chapters</option>
{% for chapter in chapters %}
<option value="{{ chapter }}">{{ chapter }}</option>
{% endfor %}
</select>
</div>
</div>
<!-- Tag Filter -->
<div class="mb-3">
<strong>Filter by Tag:</strong>
<span id="tag-filter-chips">
<button class="btn btn-sm btn-outline-light active" data-tag="all">All</button>
{% for tag in all_tags %}
<button class="btn btn-sm btn-outline-info" data-tag="{{ tag }}">{{ tag }}</button>
{% endfor %}
</span>
</div>
<!-- Bulk Actions -->
<div class="mb-3">
<button class="btn btn-danger" id="delete-selected-btn">Delete Selected</button>
</div>
<!-- Questions Table -->
<div class="table-responsive">
<table class="table table-dark table-hover">
<thead>
<tr>
<th><input type="checkbox" id="select-all-checkbox"></th>
<th>Question Text</th>
<th>Chapter</th>
<th>Subject</th>
<th>Tags</th>
<th>Action</th>
</tr>
</thead>
<tbody id="questions-table-body">
{% for q in questions %}
<tr data-chapter="{{ q.chapter }}" data-tags="{{ q.tags or '' }}">
<td><input type="checkbox" class="question-checkbox" data-id="{{ q.id }}"></td>
<td>{{ q.question_text_plain }}</td>
<td class="chapter-cell">{{ q.chapter }}</td>
<td class="subject-cell">{{ q.subject }}</td>
<td>{{ q.tags }}</td>
<td>
<button class="btn btn-sm btn-primary edit-btn"
data-id="{{ q.id }}"
data-chapter="{{ q.chapter }}"
data-subject="{{ q.subject }}"
data-bs-toggle="modal"
data-bs-target="#editModal">
Edit
</button>
<button class="btn btn-sm btn-danger delete-btn"
data-id="{{ q.id }}">
Delete
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Edit Modal -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content bg-dark text-white">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel">Edit Question Metadata</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="edit-form">
<input type="hidden" id="edit-question-id">
<div class="mb-3">
<label for="edit-chapter" class="form-label">Chapter</label>
<input type="text" class="form-control bg-secondary text-white" id="edit-chapter" required>
</div>
<div class="mb-3">
<label for="edit-subject" class="form-label">Subject</label>
<select class="form-select bg-secondary text-white" id="edit-subject" required>
{% for subject in available_subjects %}
<option value="{{ subject }}">{{ subject }}</option>
{% endfor %}
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="save-changes-btn">Save changes</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
document.addEventListener('DOMContentLoaded', function () {
const editModal = new bootstrap.Modal(document.getElementById('editModal'));
const editQuestionId = document.getElementById('edit-question-id');
const editChapter = document.getElementById('edit-chapter');
const editSubject = document.getElementById('edit-subject');
document.querySelectorAll('.edit-btn').forEach(button => {
button.addEventListener('click', () => {
editQuestionId.value = button.dataset.id;
editChapter.value = button.dataset.chapter;
editSubject.value = button.dataset.subject;
});
});
document.getElementById('save-changes-btn').addEventListener('click', async () => {
const id = editQuestionId.value;
const chapter = editChapter.value;
const subject = editSubject.value;
try {
const response = await fetch(`/classified/update_question/${id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ chapter: chapter, subject: subject })
});
const result = await response.json();
if (result.success) {
// Update the table row
const row = document.querySelector(`button[data-id='${id}']`).closest('tr');
row.querySelector('.chapter-cell').textContent = chapter;
row.querySelector('.subject-cell').textContent = subject;
// Update the button's data attributes as well
const editBtn = row.querySelector('.edit-btn');
editBtn.dataset.chapter = chapter;
editBtn.dataset.subject = subject;
editModal.hide();
} else {
alert(`Error: ${result.error}`);
}
} catch (error) {
alert(`Request failed: ${error}`);
}
});
// --- Filtering Logic ---
const searchInput = document.getElementById('search-input');
const chapterFilter = document.getElementById('chapter-filter');
const tagFilterChips = document.getElementById('tag-filter-chips');
const tableBody = document.getElementById('questions-table-body');
const rows = tableBody.getElementsByTagName('tr');
let activeTag = 'all';
function filterTable() {
const searchText = searchInput.value.toLowerCase();
const selectedChapter = chapterFilter.value;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const chapter = row.dataset.chapter;
const tags = (row.dataset.tags || '').split(',').map(t => t.trim());
const text = row.textContent || row.innerText;
const chapterMatch = (selectedChapter === 'all' || chapter === selectedChapter);
const searchMatch = (text.toLowerCase().indexOf(searchText) > -1);
const tagMatch = (activeTag === 'all' || tags.includes(activeTag));
if (chapterMatch && searchMatch && tagMatch) {
row.style.display = "";
} else {
row.style.display = "none";
}
}
}
searchInput.addEventListener('keyup', filterTable);
chapterFilter.addEventListener('change', filterTable);
tagFilterChips.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
tagFilterChips.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
e.target.classList.add('active');
activeTag = e.target.dataset.tag;
filterTable();
}
});
// --- Bulk Actions ---
const selectAllCheckbox = document.getElementById('select-all-checkbox');
const questionCheckboxes = document.querySelectorAll('.question-checkbox');
const deleteSelectedBtn = document.getElementById('delete-selected-btn');
selectAllCheckbox.addEventListener('change', (e) => {
questionCheckboxes.forEach(checkbox => {
checkbox.checked = e.target.checked;
});
});
deleteSelectedBtn.addEventListener('click', async () => {
const selectedIds = Array.from(questionCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.dataset.id);
if (selectedIds.length === 0) {
alert('Please select at least one question to delete.');
return;
}
if (!confirm(`Are you sure you want to delete ${selectedIds.length} questions?`)) return;
try {
const response = await fetch('/classified/delete_many', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: selectedIds })
});
const result = await response.json();
if (result.success) {
selectedIds.forEach(id => {
document.querySelector(`.question-checkbox[data-id='${id}']`).closest('tr').remove();
});
} else {
alert(`Error: ${result.error}`);
}
} catch (error) {
alert(`Request failed: ${error}`);
}
});
document.querySelectorAll('.delete-btn').forEach(button => {
button.addEventListener('click', async () => {
const id = button.dataset.id;
if (!confirm('Are you sure you want to delete this question?')) return;
try {
const response = await fetch(`/classified/delete_question/${id}`, {
method: 'DELETE'
});
const result = await response.json();
if (result.success) {
button.closest('tr').remove();
} else {
alert(`Error: ${result.error}`);
}
} catch (error) {
alert(`Request failed: ${error}`);
}
});
});
});
</script>
{% endblock %}