feat: Add NFO UI features (Task 6)
- Extended AnimeSummary model with NFO fields (has_nfo, nfo_created_at, nfo_updated_at, tmdb_id, tvdb_id) - Updated list_anime endpoint to fetch and return NFO data from database - Added NFO status badges to series cards (green=exists, gray=missing) - Created nfo-manager.js module with createNFO, refreshNFO, viewNFO operations - Added NFO action buttons to series cards (Create/View/Refresh) - Integrated WebSocket handlers for real-time NFO events (creating, completed, failed) - Added CSS styles for NFO badges and action buttons - All 34 NFO API tests passing, all 32 anime endpoint tests passing - Documented in docs/task6_status.md (90% complete, NFO status page deferred)
This commit is contained in:
@@ -77,7 +77,12 @@ AniWorld.SeriesManager = (function() {
|
||||
folder: anime.folder,
|
||||
episodeDict: episodeDict,
|
||||
missing_episodes: totalMissing,
|
||||
has_missing: anime.has_missing || totalMissing > 0
|
||||
has_missing: anime.has_missing || totalMissing > 0,
|
||||
has_nfo: anime.has_nfo || false,
|
||||
nfo_created_at: anime.nfo_created_at || null,
|
||||
nfo_updated_at: anime.nfo_updated_at || null,
|
||||
tmdb_id: anime.tmdb_id || null,
|
||||
tvdb_id: anime.tvdb_id || null
|
||||
};
|
||||
});
|
||||
} else if (data.status === 'success') {
|
||||
@@ -226,6 +231,47 @@ AniWorld.SeriesManager = (function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Bind NFO button events
|
||||
grid.querySelectorAll('.nfo-create-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
const seriesKey = e.currentTarget.dataset.key;
|
||||
if (AniWorld.NFOManager) {
|
||||
AniWorld.NFOManager.createNFO(seriesKey).then(function() {
|
||||
// Reload series to reflect new NFO status
|
||||
loadSeries();
|
||||
}).catch(function(error) {
|
||||
console.error('Error creating NFO:', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
grid.querySelectorAll('.nfo-view-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
const seriesKey = e.currentTarget.dataset.key;
|
||||
if (AniWorld.NFOManager) {
|
||||
AniWorld.NFOManager.showNFOModal(seriesKey);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
grid.querySelectorAll('.nfo-refresh-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
const seriesKey = e.currentTarget.dataset.key;
|
||||
if (AniWorld.NFOManager) {
|
||||
AniWorld.NFOManager.refreshNFO(seriesKey).then(function() {
|
||||
// Reload series to reflect updated NFO
|
||||
loadSeries();
|
||||
}).catch(function(error) {
|
||||
console.error('Error refreshing NFO:', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,6 +283,7 @@ AniWorld.SeriesManager = (function() {
|
||||
const isSelected = AniWorld.SelectionManager ? AniWorld.SelectionManager.isSelected(serie.key) : false;
|
||||
const hasMissingEpisodes = serie.missing_episodes > 0;
|
||||
const canBeSelected = hasMissingEpisodes;
|
||||
const hasNfo = serie.has_nfo || false;
|
||||
|
||||
return '<div class="series-card ' + (isSelected ? 'selected' : '') + ' ' +
|
||||
(hasMissingEpisodes ? 'has-missing' : 'complete') + '" ' +
|
||||
@@ -250,6 +297,8 @@ AniWorld.SeriesManager = (function() {
|
||||
'</div>' +
|
||||
'<div class="series-status">' +
|
||||
(hasMissingEpisodes ? '' : '<i class="fas fa-check-circle status-complete" title="Complete"></i>') +
|
||||
(hasNfo ? '<i class="fas fa-file-alt nfo-badge nfo-exists" title="NFO metadata available"></i>' :
|
||||
'<i class="fas fa-file-alt nfo-badge nfo-missing" title="No NFO metadata"></i>') +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="series-stats">' +
|
||||
@@ -259,6 +308,15 @@ AniWorld.SeriesManager = (function() {
|
||||
'</div>' +
|
||||
'<span class="series-site">' + serie.site + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="series-actions">' +
|
||||
(hasNfo ?
|
||||
'<button class="btn btn-sm btn-secondary nfo-view-btn" data-key="' + serie.key + '" title="View NFO">' +
|
||||
'<i class="fas fa-eye"></i> View NFO</button>' +
|
||||
'<button class="btn btn-sm btn-secondary nfo-refresh-btn" data-key="' + serie.key + '" title="Refresh NFO">' +
|
||||
'<i class="fas fa-sync-alt"></i> Refresh</button>' :
|
||||
'<button class="btn btn-sm btn-primary nfo-create-btn" data-key="' + serie.key + '" title="Create NFO">' +
|
||||
'<i class="fas fa-plus"></i> Create NFO</button>') +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user