327 lines
14 KiB
HTML
327 lines
14 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block content %}
|
|
<!-- Add CSRF token to the page -->
|
|
{% csrf_token %}
|
|
|
|
<div class="container-fluid py-4">
|
|
<!-- Welcome Section -->
|
|
{% include 'components/welcome_section.html' with user=teacher %}
|
|
|
|
<!-- Subject Files Content -->
|
|
<div class="content-section active">
|
|
<div class="content-card">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h3 class="text-xl font-semibold mb-0">
|
|
<i class="fas fa-book me-2"></i>Manage Subject Materials
|
|
</h3>
|
|
<a href="{% url 'teacherDashboard' %}#subjectsSection" class="btn btn-sm btn-link text-decoration-none ps-0" id="backToSubjectsBtn">
|
|
<i class="fas fa-arrow-left me-1"></i> Back to Subjects
|
|
</a>
|
|
</div>
|
|
<button class="btn btn-primary" onclick="openUploadModal()">
|
|
<i class="fas fa-file-upload me-1"></i> Upload New Material
|
|
</button>
|
|
</div>
|
|
|
|
{% if subjects %}
|
|
<div class="row">
|
|
{% for subject in subjects %}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="card border-0 shadow-sm h-100">
|
|
<div class="card-header bg-light py-3">
|
|
<h5 class="card-title mb-0">{{ subject.name }}</h5>
|
|
<p class="text-muted mb-0 small">{{ subject.course }} - {{ subject.semester_or_year }}</p>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted small mb-3">
|
|
<i class="fas fa-file me-1"></i> {{ subject.files_count }} file(s) available
|
|
</p>
|
|
|
|
{% if subject.files %}
|
|
<div class="list-group">
|
|
{% for file in subject.files %}
|
|
<div class="list-group-item list-group-item-action {% if file.file_type == 'syllabus' %}bg-light{% endif %}">
|
|
<div class="d-flex w-100 justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">
|
|
{% if file.file_type == 'syllabus' %}
|
|
<i class="fas fa-file-pdf text-danger me-2"></i>
|
|
{% else %}
|
|
<i class="fas fa-file-alt text-primary me-2"></i>
|
|
{% endif %}
|
|
{{ file.title }}
|
|
</h6>
|
|
<p class="mb-1 small">
|
|
{% if file.description %}{{ file.description }}{% endif %}
|
|
</p>
|
|
<small class="text-muted">
|
|
{% if file.file_type == 'syllabus' %}
|
|
<span class="badge bg-info">Syllabus</span>
|
|
{% else %}
|
|
<span class="badge bg-primary">Study Material</span>
|
|
{% endif %}
|
|
{% if file.uploaded_at %}
|
|
<span class="ms-1">Uploaded {{ file.uploaded_at|timesince }} ago</span>
|
|
{% endif %}
|
|
{% if file.uploaded_by %}
|
|
<span class="ms-1">by {{ file.uploaded_by }}</span>
|
|
{% endif %}
|
|
</small>
|
|
</div>
|
|
<div class="d-flex flex-column align-items-end">
|
|
<a href="{{ file.file_url }}" class="btn btn-sm btn-outline-primary mb-1" target="_blank">
|
|
<i class="fas fa-download me-1"></i> Download
|
|
</a>
|
|
{% if file.file_type == 'syllabus' %}
|
|
<a href="{{ file.file_url }}" class="btn btn-sm btn-outline-secondary" target="_blank">
|
|
<i class="fas fa-eye me-1"></i> View Syllabus
|
|
</a>
|
|
{% else %}
|
|
<button class="btn btn-sm btn-outline-danger" onclick="deleteFile('{{ file.id }}')">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="alert alert-info">
|
|
<i class="fas fa-info-circle me-2"></i>No files available for this subject.
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="mt-3">
|
|
<button class="btn btn-sm btn-primary w-100" onclick="openUploadModal('{{ subject.id }}')">
|
|
<i class="fas fa-file-upload me-1"></i> Upload to {{ subject.name }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="alert alert-info">
|
|
<i class="fas fa-info-circle me-2"></i>You don't have any subjects assigned.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Upload File Modal -->
|
|
<div id="uploadFileModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0,0,0,0.5); z-index: 10000;" onclick="if(event.target === this) closeUploadModal();">
|
|
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 600px; background-color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.2);">
|
|
<div style="background-color: #3F51B5; color: white; padding: 15px; border-top-left-radius: 8px; border-top-right-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
<h5 style="margin: 0; font-size: 18px;">Upload Study Material</h5>
|
|
<button style="background: none; border: none; color: white; font-size: 24px; cursor: pointer; line-height: 24px;" onclick="closeUploadModal()">×</button>
|
|
</div>
|
|
<div style="padding: 20px;">
|
|
<form id="uploadFileForm" method="post" action="/app/manage-subject-files/" enctype="multipart/form-data">
|
|
{% csrf_token %}
|
|
|
|
<div class="mb-3">
|
|
<label for="subject_id" class="form-label">Subject</label>
|
|
<select class="form-select" id="subject_id" name="subject_id" required>
|
|
<option value="">Select a subject</option>
|
|
{% for subject in subjects %}
|
|
<option value="{{ subject.id }}">{{ subject.name }} ({{ subject.course }})</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="title" class="form-label">Title</label>
|
|
<input type="text" class="form-control" id="title" name="title" required placeholder="e.g. Chapter 1 Notes">
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="description" class="form-label">Description (Optional)</label>
|
|
<textarea class="form-control" id="description" name="description" rows="2" placeholder="Brief description of the material"></textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="file" class="form-label">File</label>
|
|
<input type="file" class="form-control" id="file" name="file" required>
|
|
<div class="form-text">Upload PDF, DOCX, PPT or other study materials. Max file size: 10MB</div>
|
|
</div>
|
|
|
|
<div id="uploadResponse" style="display: none;" class="alert mb-3"></div>
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="button" class="btn btn-secondary me-2" onclick="closeUploadModal()">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-upload me-1"></i> Upload
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Confirmation Modal -->
|
|
<div id="confirmationModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0,0,0,0.5); z-index: 10000;" onclick="if(event.target === this) closeConfirmationModal();">
|
|
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 400px; background-color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.2);">
|
|
<div style="background-color: #f44336; color: white; padding: 15px; border-top-left-radius: 8px; border-top-right-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
<h5 style="margin: 0; font-size: 18px;">Confirm Deletion</h5>
|
|
<button style="background: none; border: none; color: white; font-size: 24px; cursor: pointer; line-height: 24px;" onclick="closeConfirmationModal()">×</button>
|
|
</div>
|
|
<div style="padding: 20px;">
|
|
<p class="mb-4">Are you sure you want to delete this file? This action cannot be undone.</p>
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="button" class="btn btn-secondary me-2" onclick="closeConfirmationModal()">Cancel</button>
|
|
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">
|
|
<i class="fas fa-trash me-1"></i> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom Navigation -->
|
|
{% include 'components/bottom_nav.html' with user=teacher %}
|
|
|
|
<script>
|
|
// Modal Functions
|
|
function openUploadModal(subjectId = '') {
|
|
const modal = document.getElementById('uploadFileModal');
|
|
const subjectSelect = document.getElementById('subject_id');
|
|
const responseDiv = document.getElementById('uploadResponse');
|
|
|
|
// Reset the form
|
|
document.getElementById('uploadFileForm').reset();
|
|
responseDiv.style.display = 'none';
|
|
|
|
// If a subject ID was provided, pre-select it
|
|
if (subjectId) {
|
|
subjectSelect.value = subjectId;
|
|
}
|
|
|
|
modal.style.display = 'block';
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
function closeUploadModal() {
|
|
document.getElementById('uploadFileModal').style.display = 'none';
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
let fileIdToDelete = null;
|
|
|
|
function deleteFile(fileId) {
|
|
fileIdToDelete = fileId;
|
|
document.getElementById('confirmationModal').style.display = 'block';
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
function closeConfirmationModal() {
|
|
document.getElementById('confirmationModal').style.display = 'none';
|
|
document.body.style.overflow = '';
|
|
fileIdToDelete = null;
|
|
}
|
|
|
|
// Form Submission and AJAX Functions
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// File upload form submission
|
|
const uploadForm = document.getElementById('uploadFileForm');
|
|
uploadForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(uploadForm);
|
|
const submitBtn = uploadForm.querySelector('button[type="submit"]');
|
|
const responseDiv = document.getElementById('uploadResponse');
|
|
|
|
// Disable the submit button and show loading state
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> Uploading...';
|
|
|
|
fetch('/app/manage-subject-files/', {
|
|
method: 'POST',
|
|
body: formData,
|
|
credentials: 'same-origin',
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
responseDiv.style.display = 'block';
|
|
|
|
if (data.success) {
|
|
responseDiv.className = 'alert alert-success mb-3';
|
|
responseDiv.innerHTML = '<i class="fas fa-check-circle me-1"></i> ' + data.message;
|
|
|
|
// Reload the page after a short delay to show the new file
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
responseDiv.className = 'alert alert-danger mb-3';
|
|
responseDiv.innerHTML = '<i class="fas fa-exclamation-circle me-1"></i> ' + data.message;
|
|
}
|
|
})
|
|
.catch(error => {
|
|
responseDiv.style.display = 'block';
|
|
responseDiv.className = 'alert alert-danger mb-3';
|
|
responseDiv.innerHTML = '<i class="fas fa-exclamation-circle me-1"></i> An error occurred while uploading the file.';
|
|
console.error('Error:', error);
|
|
})
|
|
.finally(() => {
|
|
// Re-enable the submit button
|
|
submitBtn.disabled = false;
|
|
submitBtn.innerHTML = '<i class="fas fa-upload me-1"></i> Upload';
|
|
});
|
|
});
|
|
|
|
// Delete file confirmation
|
|
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
|
|
confirmDeleteBtn.addEventListener('click', function() {
|
|
if (!fileIdToDelete) return;
|
|
|
|
// Disable the button and show loading state
|
|
confirmDeleteBtn.disabled = true;
|
|
confirmDeleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> Deleting...';
|
|
|
|
const formData = new FormData();
|
|
formData.append('file_id', fileIdToDelete);
|
|
formData.append('csrfmiddlewaretoken', document.querySelector('[name=csrfmiddlewaretoken]').value);
|
|
|
|
fetch('/app/delete-subject-file/', {
|
|
method: 'POST',
|
|
body: formData,
|
|
credentials: 'same-origin',
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Close the modal and reload the page to show the updated list
|
|
closeConfirmationModal();
|
|
window.location.reload();
|
|
} else {
|
|
alert('Error: ' + data.message);
|
|
closeConfirmationModal();
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while deleting the file.');
|
|
closeConfirmationModal();
|
|
});
|
|
});
|
|
});
|
|
|
|
// Ensure back button properly navigates to subjects section
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const backBtn = document.getElementById('backToSubjectsBtn');
|
|
if (backBtn) {
|
|
backBtn.addEventListener('click', function(e) {
|
|
// Store in sessionStorage that we should activate subjects section
|
|
sessionStorage.setItem('activateSection', 'subjectsSection');
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |