diff --git a/pytorrent/static/js/torrentRowRenderer.js b/pytorrent/static/js/torrentRowRenderer.js index c4cf432..506c6f4 100644 --- a/pytorrent/static/js/torrentRowRenderer.js +++ b/pytorrent/static/js/torrentRowRenderer.js @@ -1 +1 @@ -export const torrentRowRendererSource = " function statusMeta(t){\n const op=activeOperationFor(t);\n if(op) return {cls:'text-bg-info operation-status-badge', icon:actionIcon(op.action), color:'text-info', label:op.label};\n const status=String(t.status||'').toLowerCase();\n if(t.paused || status==='paused') return {cls:'text-bg-warning', icon:'fa-pause', color:'text-warning'};\n if(status==='checking' || Number(t.hashing||0)>0) return {cls:'text-bg-info', icon:'fa-rotate', color:'text-info'};\n if(status==='post-check' || t.post_check) return {cls:'text-bg-dark', icon:'fa-clipboard-check', color:'text-secondary', label:'Post-check'};\n if(status==='seeding') return {cls:'text-bg-success', icon:'fa-seedling', color:'text-success'};\n if(status==='downloading') return {cls:'text-bg-primary', icon:'fa-download', color:'text-primary'};\n if(status==='stopped') return {cls:'text-bg-secondary', icon:'fa-stop', color:'text-secondary'};\n return t.state ? {cls:'text-bg-success', icon:'fa-play', color:'text-success'} : {cls:'text-bg-secondary', icon:'fa-circle', color:'text-secondary'};\n }\n function statusBadge(t){ const m=statusMeta(t); return `${esc(m.label || t.status)}`; }\n function torrentErrorLog(t){\n // Note: The name-column status icon is useful only when the torrent has an error log to show in the tooltip.\n const status=String(t.status||'').trim().toLowerCase();\n const msg=String(t.message||'').trim();\n if(status==='error') return msg || 'Torrent reported an error.';\n if(!msg) return null;\n const patterns=['error','failed','failure','timeout','timed out','tracker','could not','cannot','refused','unreachable','denied'];\n return patterns.some(p=>msg.toLowerCase().includes(p)) ? msg : null;\n }\n function torrentNameStatusIcon(t){\n // Note: Non-error torrents keep the name cell clean; the Status column still shows their normal state.\n const errorLog=torrentErrorLog(t);\n return errorLog ? ` ` : '';\n }\n function boolCell(value){ return Number(value||0) ? 'yes' : 'no'; }\n function renderRow(t){\n const labels=labelNames(t.label).map(l=>` ${esc(l)}`).join(' ');\n const errorLog=torrentErrorLog(t);\n const op=activeOperationFor(t);\n const classes=[selected.has(t.hash)?'selected':'', t.paused?'torrent-paused':'', op?'torrent-operating':'', errorLog?'torrent-warning':''].filter(Boolean).join(' ');\n const title=[t.name,errorLog,op?op.label:''].filter(Boolean).join('\\n');\n return ``+\n ``+\n `${torrentNameStatusIcon(t)}${esc(t.name)}`+\n `${statusBadge(t)}`+\n `${esc(t.size_h)}`+\n `${progress(t)}`+\n `${esc(t.down_rate_h)}`+\n `${esc(t.up_rate_h)}`+\n `${esc(t.eta_h||\"-\")}`+\n `${esc(t.seeds)}`+\n `${esc(t.peers)}`+\n `${esc(t.ratio)}`+\n `${esc(t.path)}`+\n `${labels||'-'}`+\n `${esc(t.ratio_group||'')}`+\n `${esc(t.down_total_h||'-')}`+\n `${esc(t.to_download_h||'-')}`+\n `${esc(t.up_total_h||'-')}`+\n `${esc(formatDateTime(t.created))}`+\n `${esc(formatDateTime(t.last_activity))}`+\n `${esc(t.priority ?? '-')}`+\n `${boolCell(t.state)}`+\n `${boolCell(t.active)}`+\n `${boolCell(t.complete)}`+\n `${esc(t.hashing ?? 0)}`+\n `${compactCell(t.message||'', 80)}`+\n `${esc(t.hash||'')}`+\n ``;\n }\n\n\n\n\n"; +export const torrentRowRendererSource = " function statusMeta(t){\n const op=activeOperationFor(t);\n if(op) return {cls:'text-bg-info operation-status-badge', icon:actionIcon(op.action), color:'text-info', label:op.label};\n const status=String(t.status||'').toLowerCase();\n if(t.paused || status==='paused') return {cls:'text-bg-warning', icon:'fa-pause', color:'text-warning'};\n if(status==='checking' || Number(t.hashing||0)>0) return {cls:'text-bg-info', icon:'fa-rotate', color:'text-info'};\n if(status==='post-check' || t.post_check) return {cls:'text-bg-dark', icon:'fa-clipboard-check', color:'text-secondary', label:'Post-check'};\n if(status==='seeding') return {cls:'text-bg-success', icon:'fa-seedling', color:'text-success'};\n if(status==='downloading') return {cls:'text-bg-primary', icon:'fa-download', color:'text-primary'};\n if(status==='stopped') return {cls:'text-bg-secondary', icon:'fa-stop', color:'text-secondary'};\n return t.state ? {cls:'text-bg-success', icon:'fa-play', color:'text-success'} : {cls:'text-bg-secondary', icon:'fa-circle', color:'text-secondary'};\n }\n function statusBadge(t){ const m=statusMeta(t); return `${esc(m.label || t.status)}`; }\n function torrentErrorLog(t){\n // Note: The name-column status icon is useful only when the torrent has an error log to show in the tooltip.\n const status=String(t.status||'').trim().toLowerCase();\n const msg=String(t.message||'').trim();\n if(status==='error') return msg || 'Torrent reported an error.';\n if(!msg) return null;\n const patterns=['error','failed','failure','timeout','timed out','tracker','could not','cannot','refused','unreachable','denied'];\n return patterns.some(p=>msg.toLowerCase().includes(p)) ? msg : null;\n }\n function torrentWarning(t){\n // Note: Backward-compatible alias used by health dashboards and smart views.\n return torrentErrorLog(t);\n }\n function torrentNameStatusIcon(t){\n // Note: Non-error torrents keep the name cell clean; the Status column still shows their normal state.\n const errorLog=torrentErrorLog(t);\n return errorLog ? ` ` : '';\n }\n function boolCell(value){ return Number(value||0) ? 'yes' : 'no'; }\n function renderRow(t){\n const labels=labelNames(t.label).map(l=>` ${esc(l)}`).join(' ');\n const errorLog=torrentErrorLog(t);\n const op=activeOperationFor(t);\n const classes=[selected.has(t.hash)?'selected':'', t.paused?'torrent-paused':'', op?'torrent-operating':'', errorLog?'torrent-warning':''].filter(Boolean).join(' ');\n const title=[t.name,errorLog,op?op.label:''].filter(Boolean).join('\\n');\n return ``+\n ``+\n `${torrentNameStatusIcon(t)}${esc(t.name)}`+\n `${statusBadge(t)}`+\n `${esc(t.size_h)}`+\n `${progress(t)}`+\n `${esc(t.down_rate_h)}`+\n `${esc(t.up_rate_h)}`+\n `${esc(t.eta_h||\"-\")}`+\n `${esc(t.seeds)}`+\n `${esc(t.peers)}`+\n `${esc(t.ratio)}`+\n `${esc(t.path)}`+\n `${labels||'-'}`+\n `${esc(t.ratio_group||'')}`+\n `${esc(t.down_total_h||'-')}`+\n `${esc(t.to_download_h||'-')}`+\n `${esc(t.up_total_h||'-')}`+\n `${esc(formatDateTime(t.created))}`+\n `${esc(formatDateTime(t.last_activity))}`+\n `${esc(t.priority ?? '-')}`+\n `${boolCell(t.state)}`+\n `${boolCell(t.active)}`+\n `${boolCell(t.complete)}`+\n `${esc(t.hashing ?? 0)}`+\n `${compactCell(t.message||'', 80)}`+\n `${esc(t.hash||'')}`+\n ``;\n }\n\n\n\n\n";