0.10.2-8 Layout
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"dependencies": {
|
||||
"archiver": "^7.0.1",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
|
||||
@@ -11562,6 +11562,7 @@ class PipelineService extends EventEmitter {
|
||||
{
|
||||
contextPatch: {
|
||||
outputPath: incompleteOutputPath,
|
||||
completedChapterCount: index,
|
||||
currentChapter: {
|
||||
index: index + 1,
|
||||
total: outputFiles.length,
|
||||
@@ -11618,6 +11619,24 @@ class PipelineService extends EventEmitter {
|
||||
chapterTitle,
|
||||
outputPath: entry.outputPath
|
||||
});
|
||||
|
||||
await this.updateProgress(
|
||||
'ENCODING',
|
||||
endPercent,
|
||||
null,
|
||||
`Audiobook-Encoding Kapitel ${index + 1}/${outputFiles.length} abgeschlossen`,
|
||||
jobId,
|
||||
{
|
||||
contextPatch: {
|
||||
completedChapterCount: index + 1,
|
||||
currentChapter: {
|
||||
index: index + 1,
|
||||
total: outputFiles.length,
|
||||
title: chapterTitle
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ffmpegRunInfo = {
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"dependencies": {
|
||||
"primeicons": "^7.0.0",
|
||||
"primereact": "^10.9.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -158,8 +158,13 @@ export default function AudiobookConfigPanel({
|
||||
const schema = AUDIOBOOK_FORMAT_SCHEMAS[format] || AUDIOBOOK_FORMAT_SCHEMAS.mp3;
|
||||
const canStart = Boolean(jobId) && (state === 'READY_TO_START' || state === 'ERROR' || state === 'CANCELLED');
|
||||
const isRunning = state === 'ENCODING';
|
||||
const isFinished = state === 'FINISHED';
|
||||
const progress = Number.isFinite(Number(pipeline?.progress)) ? Math.max(0, Math.min(100, Number(pipeline.progress))) : 0;
|
||||
const outputPath = String(context?.outputPath || '').trim() || null;
|
||||
const isSplitOutput = format === 'mp3' || format === 'flac';
|
||||
const currentChapter = context?.currentChapter && typeof context.currentChapter === 'object' ? context.currentChapter : null;
|
||||
const completedChapterCount = Number(context?.completedChapterCount ?? -1);
|
||||
const chapterTotal = Number(currentChapter?.total || editableChapters.length || 0);
|
||||
const statusLabel = getStatusLabel(state);
|
||||
const statusSeverity = getStatusSeverity(state);
|
||||
const description = String(metadata?.description || '').trim();
|
||||
@@ -290,7 +295,29 @@ export default function AudiobookConfigPanel({
|
||||
{isRunning ? (
|
||||
<div className="dashboard-job-row-progress" aria-label={`Audiobook Fortschritt ${Math.round(progress)}%`}>
|
||||
<ProgressBar value={progress} showValue={false} />
|
||||
<small>{Math.round(progress)}%</small>
|
||||
<small>{Math.round(progress)}%{currentChapter ? ` | Kapitel ${currentChapter.index}/${currentChapter.total}: ${currentChapter.title}` : ''}</small>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{isSplitOutput && (isRunning || isFinished) && editableChapters.length > 0 ? (
|
||||
<div className="audiobook-chapter-status">
|
||||
<strong>Kapitel-Status ({completedChapterCount >= 0 ? completedChapterCount : (isFinished ? editableChapters.length : 0)}/{chapterTotal || editableChapters.length} fertig)</strong>
|
||||
<div className="audiobook-chapter-status-list">
|
||||
{editableChapters.map((chapter, idx) => {
|
||||
const chIdx = chapter.index || idx + 1;
|
||||
const isDone = isFinished || (completedChapterCount >= 0 && chIdx <= completedChapterCount);
|
||||
const isActive = !isDone && currentChapter?.index === chIdx;
|
||||
const statusIcon = isDone ? 'pi pi-check-circle' : isActive ? 'pi pi-spin pi-spinner' : 'pi pi-circle';
|
||||
const statusClass = isDone ? 'chapter-status-done' : isActive ? 'chapter-status-active' : 'chapter-status-pending';
|
||||
return (
|
||||
<div key={chIdx} className={`audiobook-chapter-status-row ${statusClass}`}>
|
||||
<i className={statusIcon} />
|
||||
<span className="chapter-status-nr">#{String(chIdx).padStart(2, '0')}</span>
|
||||
<span className="chapter-status-title">{chapter.title}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -866,6 +866,7 @@ export default function DashboardPage({
|
||||
const [insertWaitSeconds, setInsertWaitSeconds] = useState(30);
|
||||
const toastRef = useRef(null);
|
||||
const audiobookFileUploadRef = useRef(null);
|
||||
const [audiobookUploadStatusVisible, setAudiobookUploadStatusVisible] = useState(false);
|
||||
|
||||
const state = String(pipeline?.state || 'IDLE').trim().toUpperCase();
|
||||
const currentPipelineJobId = normalizeJobId(pipeline?.activeJobId || pipeline?.context?.jobId);
|
||||
@@ -1123,6 +1124,19 @@ export default function DashboardPage({
|
||||
setExpandedJobId(normalizeJobId(dashboardJobs[0]?.id));
|
||||
}, [dashboardJobs, expandedJobId, currentPipelineJobId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (audiobookUploadPhase === 'idle') {
|
||||
setAudiobookUploadStatusVisible(false);
|
||||
return undefined;
|
||||
}
|
||||
setAudiobookUploadStatusVisible(true);
|
||||
if (audiobookUploadPhase === 'completed') {
|
||||
const timer = setTimeout(() => setAudiobookUploadStatusVisible(false), 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
return undefined;
|
||||
}, [audiobookUploadPhase]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentPipelineJobId || !isProcessing) {
|
||||
setLiveJobLog('');
|
||||
@@ -2531,14 +2545,6 @@ export default function DashboardPage({
|
||||
<span className="aax-file-name" title={file.name}>{file.name}</span>
|
||||
<small>{options.formatSize}</small>
|
||||
</div>
|
||||
<Button
|
||||
label="Hochladen"
|
||||
icon="pi pi-upload"
|
||||
size="small"
|
||||
onClick={() => void handleAudiobookUpload()}
|
||||
loading={audiobookUploadBusy}
|
||||
disabled={audiobookUploadBusy}
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-times"
|
||||
text
|
||||
@@ -2558,7 +2564,7 @@ export default function DashboardPage({
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
{audiobookUploadPhase !== 'idle' ? (
|
||||
{audiobookUploadStatusVisible ? (
|
||||
<div className={`audiobook-upload-status tone-${audiobookUploadStatusTone}`}>
|
||||
<div className="audiobook-upload-status-head">
|
||||
<strong>{audiobookUploadStatusLabel}</strong>
|
||||
|
||||
@@ -3802,7 +3802,7 @@ body {
|
||||
|
||||
.audiobook-config-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@@ -3859,6 +3859,55 @@ body {
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.audiobook-chapter-status {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.audiobook-chapter-status-list {
|
||||
display: grid;
|
||||
gap: 0.25rem;
|
||||
max-height: 16rem;
|
||||
overflow: auto;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.audiobook-chapter-status-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.3rem 0.5rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.chapter-status-done {
|
||||
background: var(--green-50, #f0fdf4);
|
||||
color: var(--green-700, #15803d);
|
||||
}
|
||||
|
||||
.chapter-status-active {
|
||||
background: var(--blue-50, #eff6ff);
|
||||
color: var(--blue-700, #1d4ed8);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chapter-status-pending {
|
||||
color: var(--rip-muted, #666);
|
||||
}
|
||||
|
||||
.chapter-status-nr {
|
||||
font-variant-numeric: tabular-nums;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chapter-status-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.audiobook-description-dialog p {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster",
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.1.2"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ripster",
|
||||
"private": true,
|
||||
"version": "0.10.2-7",
|
||||
"version": "0.10.2-8",
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
|
||||
"dev:backend": "npm run dev --prefix backend",
|
||||
|
||||
Reference in New Issue
Block a user