- Add LessonsController with GET /Plugins/Lessons/List endpoint - Add LessonStore DI registration in ServiceRegistrator - Add lessonsPage.html embedded resource with grouped lesson listing - Implement IHasWebPages in Plugin for sidebar nav entry - Add ImplicitUsings/Nullable to csproj for net9.0 compatibility - Add Microsoft.AspNetCore.App FrameworkReference for MVC - Fix ServiceRegistrator to match 10.10.x IPluginServiceRegistrator signature
152 lines
4.8 KiB
HTML
152 lines
4.8 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Lessons</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: #101010;
|
|
color: #e0e0e0;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
.page {
|
|
padding: 2em;
|
|
max-width: 960px;
|
|
margin: 0 auto;
|
|
}
|
|
h1 {
|
|
font-size: 1.8em;
|
|
font-weight: 600;
|
|
margin-bottom: 1em;
|
|
color: #fff;
|
|
}
|
|
.grade-group {
|
|
margin-bottom: 2em;
|
|
}
|
|
.grade-header {
|
|
font-size: 1.2em;
|
|
font-weight: 600;
|
|
color: #00a4dc;
|
|
margin-bottom: 0.5em;
|
|
padding-bottom: 0.3em;
|
|
border-bottom: 1px solid #333;
|
|
}
|
|
.lesson-card {
|
|
background: #1a1a1a;
|
|
border: 1px solid #333;
|
|
border-radius: 6px;
|
|
padding: 0.75em 1em;
|
|
margin-bottom: 0.5em;
|
|
cursor: pointer;
|
|
transition: background 0.2s, border-color 0.2s;
|
|
}
|
|
.lesson-card:hover {
|
|
background: #222;
|
|
border-color: #00a4dc;
|
|
}
|
|
.lesson-title {
|
|
font-weight: 600;
|
|
color: #fff;
|
|
font-size: 1.05em;
|
|
}
|
|
.lesson-meta {
|
|
font-size: 0.85em;
|
|
color: #999;
|
|
margin-top: 0.25em;
|
|
}
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 3em;
|
|
color: #666;
|
|
}
|
|
.error-state {
|
|
text-align: center;
|
|
padding: 3em;
|
|
color: #c44;
|
|
}
|
|
.loading {
|
|
text-align: center;
|
|
padding: 3em;
|
|
color: #666;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
<h1>📚 Lessons</h1>
|
|
<div id="content" class="loading">Loading lessons…</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
var container = document.getElementById('content');
|
|
|
|
function apiUrl() {
|
|
// Use the Jellyfin base URL from the current page context
|
|
var base = window.location.origin;
|
|
return base + '/Plugins/Lessons/List';
|
|
}
|
|
|
|
function renderLessons(lessons) {
|
|
if (!lessons || lessons.length === 0) {
|
|
container.className = 'empty-state';
|
|
container.innerHTML = '<p>No lessons found. Lessons will appear here after you build them.</p>';
|
|
return;
|
|
}
|
|
|
|
// Group by grade
|
|
var gradeMap = {};
|
|
lessons.forEach(function(l) {
|
|
var grade = l.grade || 'Unknown';
|
|
if (!gradeMap[grade]) gradeMap[grade] = [];
|
|
gradeMap[grade].push(l);
|
|
});
|
|
|
|
var html = '';
|
|
var grades = Object.keys(gradeMap).sort(function(a, b) { return a - b; });
|
|
grades.forEach(function(grade) {
|
|
html += '<div class="grade-group">';
|
|
html += '<div class="grade-header">Grade ' + grade + '</div>';
|
|
gradeMap[grade].forEach(function(l) {
|
|
html += '<div class="lesson-card">';
|
|
html += '<div class="lesson-title">' + esc(l.title) + '</div>';
|
|
html += '<div class="lesson-meta">';
|
|
html += esc(l.subject || '');
|
|
if (l.lessonDate) html += ' · ' + esc(l.lessonDate);
|
|
html += '</div>';
|
|
if (l.description) {
|
|
html += '<div class="lesson-meta">' + esc(l.description) + '</div>';
|
|
}
|
|
html += '</div>';
|
|
});
|
|
html += '</div>';
|
|
});
|
|
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
function esc(str) {
|
|
var div = document.createElement('div');
|
|
div.appendChild(document.createTextNode(str));
|
|
return div.innerHTML;
|
|
}
|
|
|
|
fetch(apiUrl())
|
|
.then(function(resp) {
|
|
if (!resp.ok) throw new Error('HTTP ' + resp.status);
|
|
return resp.json();
|
|
})
|
|
.then(function(data) {
|
|
renderLessons(data);
|
|
})
|
|
.catch(function(err) {
|
|
container.className = 'error-state';
|
|
container.innerHTML = '<p>Failed to load lessons: ' + esc(err.message) + '</p>';
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|