0.10.2-5 Upload

This commit is contained in:
2026-03-16 07:59:19 +00:00
parent 30b066ece8
commit 01766785b4
8 changed files with 128 additions and 42 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "ripster-backend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster-backend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"dependencies": {
"archiver": "^7.0.1",
"cors": "^2.8.5",

View File

@@ -1,6 +1,6 @@
{
"name": "ripster-backend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"private": true,
"type": "commonjs",
"scripts": {

View File

@@ -1,12 +1,12 @@
{
"name": "ripster-frontend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster-frontend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"dependencies": {
"primeicons": "^7.0.0",
"primereact": "^10.9.2",

View File

@@ -1,6 +1,6 @@
{
"name": "ripster-frontend",
"version": "0.10.2-4",
"version": "0.10.2-5",
"private": true,
"type": "module",
"scripts": {

View File

@@ -6,6 +6,7 @@ import { Button } from 'primereact/button';
import { Tag } from 'primereact/tag';
import { ProgressBar } from 'primereact/progressbar';
import { Dialog } from 'primereact/dialog';
import { FileUpload } from 'primereact/fileupload';
import { InputNumber } from 'primereact/inputnumber';
import { InputText } from 'primereact/inputtext';
import { api } from '../api/client';
@@ -864,6 +865,7 @@ export default function DashboardPage({
const [queueCatalog, setQueueCatalog] = useState({ scripts: [], chains: [] });
const [insertWaitSeconds, setInsertWaitSeconds] = useState(30);
const toastRef = useRef(null);
const audiobookFileUploadRef = useRef(null);
const state = String(pipeline?.state || 'IDLE').trim().toUpperCase();
const currentPipelineJobId = normalizeJobId(pipeline?.activeJobId || pipeline?.context?.jobId);
@@ -2060,13 +2062,8 @@ export default function DashboardPage({
<div className="dashboard-3col-grid">
<div className="dashboard-col dashboard-col-left">
<Card title="Hardware Monitoring" subTitle="CPU (inkl. Temperatur), RAM, GPU und freier Speicher in den konfigurierten Pfaden.">
<Card title="Hardware Monitoring">
<div className="hardware-monitor-head">
<Tag
value={monitoringState.enabled ? 'Aktiv' : 'Deaktiviert'}
severity={monitoringState.enabled ? 'success' : 'secondary'}
/>
<Tag value={`Intervall: ${monitoringState.intervalMs || 0} ms`} severity="info" />
<Tag value={`Letztes Update: ${formatUpdatedAt(monitoringState.updatedAt)}`} severity="warning" />
</div>
@@ -2494,27 +2491,57 @@ export default function DashboardPage({
<div className="dashboard-col dashboard-col-right">
<Card title="Audiobook Upload" subTitle="AAX-Datei hochladen, analysieren und danach Format/Qualität vor dem Start auswählen.">
<div className="actions-row">
<input
key={audiobookUploadFile ? `${audiobookUploadFile.name}-${audiobookUploadFile.size}` : 'audiobook-upload-input'}
type="file"
accept=".aax"
onChange={(event) => {
const nextFile = event.target?.files?.[0] || null;
setAudiobookUploadFile(nextFile);
}}
disabled={audiobookUploadBusy}
/>
<Button
label="Audiobook hochladen"
icon="pi pi-upload"
onClick={() => {
void handleAudiobookUpload();
}}
loading={audiobookUploadBusy}
disabled={!audiobookUploadFile}
/>
</div>
<FileUpload
ref={audiobookFileUploadRef}
accept=".aax"
maxFileSize={10737418240}
disabled={audiobookUploadBusy}
onSelect={(e) => setAudiobookUploadFile(e.files[0] || null)}
onClear={() => setAudiobookUploadFile(null)}
onRemove={() => setAudiobookUploadFile(null)}
chooseLabel="Auswählen"
chooseOptions={{ icon: 'pi pi-folder-open' }}
cancelOptions={{ icon: 'pi pi-times', className: 'p-button-outlined p-button-secondary' }}
headerTemplate={(options) => (
<div className="aax-upload-header">
{options.chooseButton}
{options.cancelButton}
</div>
)}
itemTemplate={(file, options) => (
<div className="aax-file-item">
<i className="pi pi-headphones aax-file-icon" />
<div className="aax-file-info">
<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
rounded
severity="danger"
size="small"
onClick={options.onRemove}
disabled={audiobookUploadBusy}
/>
</div>
)}
emptyTemplate={() => (
<div className="aax-drop-zone">
<i className="pi pi-headphones aax-drop-icon" />
<p>AAX-Datei hier ablegen</p>
<small>oder oben Auswählen" klicken</small>
</div>
)}
/>
{audiobookUploadPhase !== 'idle' ? (
<div className={`audiobook-upload-status tone-${audiobookUploadStatusTone}`}>
<div className="audiobook-upload-status-head">
@@ -2542,11 +2569,6 @@ export default function DashboardPage({
</div>
</div>
) : null}
<small>
{audiobookUploadFileName && audiobookUploadPhase === 'idle'
? `Ausgewählt: ${audiobookUploadFileName}`
: 'Unterstützt im MVP: AAX-Upload. Danach erscheint ein eigener Audiobook-Startschritt mit Format- und Qualitätswahl.'}
</small>
</Card>
<Card title="Job Queue" subTitle="Starts werden nach Typ- und Gesamtlimit abgearbeitet. Queue-Elemente können per Drag-and-Drop umsortiert werden.">

View File

@@ -683,7 +683,7 @@ body {
.pipeline-queue-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-columns: minmax(0, 1fr);
gap: 0.75rem;
}
@@ -1112,6 +1112,70 @@ body {
white-space: normal;
}
.aax-upload-header {
display: flex;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--rip-border);
background: var(--rip-panel-soft);
border-radius: 0.5rem 0.5rem 0 0;
}
.aax-drop-zone {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.35rem;
padding: 2rem 1rem;
text-align: center;
color: var(--rip-muted);
}
.aax-drop-zone p {
margin: 0;
font-size: 0.95rem;
}
.aax-drop-zone small {
font-size: 0.8rem;
}
.aax-drop-icon {
font-size: 2.2rem;
color: var(--rip-gold-400);
}
.aax-file-item {
display: flex;
align-items: center;
gap: 0.65rem;
padding: 0.6rem 0.75rem;
border-top: 1px solid var(--rip-border);
}
.aax-file-icon {
font-size: 1.4rem;
color: var(--rip-brown-600);
flex-shrink: 0;
}
.aax-file-info {
display: flex;
flex-direction: column;
gap: 0.1rem;
min-width: 0;
flex: 1;
}
.aax-file-name {
font-size: 0.875rem;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.audiobook-upload-status {
margin-top: 0.8rem;
padding: 0.7rem 0.8rem;

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ripster",
"version": "0.10.2-4",
"version": "0.10.2-5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster",
"version": "0.10.2-4",
"version": "0.10.2-5",
"devDependencies": {
"concurrently": "^9.1.2"
}

View File

@@ -1,7 +1,7 @@
{
"name": "ripster",
"private": true,
"version": "0.10.2-4",
"version": "0.10.2-5",
"scripts": {
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
"dev:backend": "npm run dev --prefix backend",