0.13.1-10 Misc fixes
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.13.1-9",
|
||||
"version": "0.13.1-10",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.13.1-9",
|
||||
"version": "0.13.1-10",
|
||||
"dependencies": {
|
||||
"primeicons": "^7.0.0",
|
||||
"primereact": "^10.9.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.13.1-9",
|
||||
"version": "0.13.1-10",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -823,6 +823,7 @@ export const api = {
|
||||
async deleteJobEntry(jobId, target = 'none', options = {}) {
|
||||
const includeRelated = Boolean(options?.includeRelated);
|
||||
const resetDriveState = Boolean(options?.resetDriveState);
|
||||
const preserveRawForImportJobs = Boolean(options?.preserveRawForImportJobs);
|
||||
const selectedMoviePaths = Array.isArray(options?.selectedMoviePaths)
|
||||
? options.selectedMoviePaths
|
||||
.map((item) => String(item || '').trim())
|
||||
@@ -838,6 +839,7 @@ export const api = {
|
||||
target,
|
||||
includeRelated,
|
||||
resetDriveState,
|
||||
preserveRawForImportJobs,
|
||||
...(hasKeepDetectedDevice ? { keepDetectedDevice } : {}),
|
||||
...(selectedMoviePaths ? { selectedMoviePaths } : {})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { Button } from 'primereact/button';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
@@ -45,11 +45,13 @@ export default function MetadataSelectionDialog({
|
||||
const [manualImdb, setManualImdb] = useState('');
|
||||
const [manualDiscNumber, setManualDiscNumber] = useState('');
|
||||
const [extraResults, setExtraResults] = useState([]);
|
||||
const [hasSearchOverride, setHasSearchOverride] = useState(false);
|
||||
const [searchBusy, setSearchBusy] = useState(false);
|
||||
const [searchError, setSearchError] = useState('');
|
||||
const [submitError, setSubmitError] = useState('');
|
||||
const [seasonFilter, setSeasonFilter] = useState('');
|
||||
const [discValidationError, setDiscValidationError] = useState('');
|
||||
const activeSearchRequestRef = useRef(0);
|
||||
const contextWorkflowKind = normalizeWorkflowKind(
|
||||
context?.selectedMetadata?.workflowKind
|
||||
|| context?.workflowKind
|
||||
@@ -102,12 +104,14 @@ export default function MetadataSelectionDialog({
|
||||
setManualImdb(defaultImdb);
|
||||
setManualDiscNumber('');
|
||||
setExtraResults([]);
|
||||
setHasSearchOverride(false);
|
||||
setSearchBusy(false);
|
||||
setSearchError('');
|
||||
setSubmitError('');
|
||||
setSeasonFilter('');
|
||||
setDiscValidationError('');
|
||||
setSelectedMetadataProvider(contextMetadataProvider);
|
||||
activeSearchRequestRef.current += 1;
|
||||
}, [visible, context]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -129,7 +133,8 @@ export default function MetadataSelectionDialog({
|
||||
const base = Array.isArray(context?.metadataCandidates)
|
||||
? context.metadataCandidates
|
||||
: (context?.omdbCandidates || []);
|
||||
const all = [...base, ...extraResults];
|
||||
const sourceRows = hasSearchOverride ? extraResults : base;
|
||||
const all = Array.isArray(sourceRows) ? sourceRows : [];
|
||||
const map = new Map();
|
||||
|
||||
all.forEach((item) => {
|
||||
@@ -149,7 +154,7 @@ export default function MetadataSelectionDialog({
|
||||
});
|
||||
|
||||
return Array.from(map.values());
|
||||
}, [context, extraResults]);
|
||||
}, [context, extraResults, hasSearchOverride]);
|
||||
|
||||
const filteredRows = useMemo(() => {
|
||||
if (metadataProvider !== 'tmdb') {
|
||||
@@ -192,18 +197,28 @@ export default function MetadataSelectionDialog({
|
||||
if (!trimmedQuery || typeof onSearch !== 'function') {
|
||||
return;
|
||||
}
|
||||
const requestId = activeSearchRequestRef.current + 1;
|
||||
activeSearchRequestRef.current = requestId;
|
||||
setHasSearchOverride(true);
|
||||
setSearchBusy(true);
|
||||
setSearchError('');
|
||||
try {
|
||||
const results = await onSearch(trimmedQuery, {
|
||||
metadataProvider
|
||||
});
|
||||
if (activeSearchRequestRef.current !== requestId) {
|
||||
return;
|
||||
}
|
||||
setExtraResults(Array.isArray(results) ? results : []);
|
||||
} catch (error) {
|
||||
setExtraResults([]);
|
||||
if (activeSearchRequestRef.current !== requestId) {
|
||||
return;
|
||||
}
|
||||
setSearchError(error?.message || 'Suche fehlgeschlagen.');
|
||||
} finally {
|
||||
setSearchBusy(false);
|
||||
if (activeSearchRequestRef.current === requestId) {
|
||||
setSearchBusy(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -262,10 +277,6 @@ export default function MetadataSelectionDialog({
|
||||
};
|
||||
|
||||
const handleHideRequest = () => {
|
||||
if (requiresDiscNumber && !hasValidDiscNumber) {
|
||||
setDiscValidationError('Disk-Nummer ist Pflicht und muss eine ganze Zahl >= 1 sein.');
|
||||
return;
|
||||
}
|
||||
onHide?.();
|
||||
};
|
||||
|
||||
@@ -291,6 +302,7 @@ export default function MetadataSelectionDialog({
|
||||
setSelectedMetadataProvider(nextProvider);
|
||||
setSelected(null);
|
||||
setExtraResults([]);
|
||||
setHasSearchOverride(false);
|
||||
setSearchError('');
|
||||
setSubmitError('');
|
||||
setDiscValidationError('');
|
||||
@@ -331,7 +343,7 @@ export default function MetadataSelectionDialog({
|
||||
/>
|
||||
<small className="metadata-filter-subtitle">
|
||||
{requiresDiscNumber
|
||||
? 'Pflichtfeld fuer Serien-DVDs. Ohne Disk-Nummer koennen die Metadaten nicht verlassen werden.'
|
||||
? 'Pflichtfeld fuer Serien-DVDs. Ohne Disk-Nummer koennen die Metadaten nicht uebernommen werden.'
|
||||
: 'Optionale Disc-Nummer fuer internes Mapping und Output-Templates. Nur Werte groesser 0 werden gespeichert.'}
|
||||
</small>
|
||||
</div>
|
||||
@@ -394,7 +406,6 @@ export default function MetadataSelectionDialog({
|
||||
severity="secondary"
|
||||
text
|
||||
onClick={handleHideRequest}
|
||||
disabled={requiresDiscNumber && !hasValidDiscNumber}
|
||||
/>
|
||||
<Button
|
||||
label="Auswahl übernehmen"
|
||||
|
||||
@@ -669,15 +669,16 @@ function formatTemplateTwoDigit(value) {
|
||||
return String(value || '').trim() || String(numeric);
|
||||
}
|
||||
|
||||
function resolveEpisodeAssignmentRange(assignment = null, title = null, fallbackEpisodeNumber = 1) {
|
||||
function resolveEpisodeAssignmentRange(assignment = null, title = null, fallbackEpisodeNumber = 1, options = {}) {
|
||||
const assignmentSource = assignment && typeof assignment === 'object' ? assignment : {};
|
||||
const titleSource = title && typeof title === 'object' ? title : {};
|
||||
const allowTitleEpisodeNumber = options?.allowTitleEpisodeNumber !== false;
|
||||
const fallbackNumber = normalizePositiveInt(fallbackEpisodeNumber) || 1;
|
||||
const episodeStart = normalizePositiveInt(
|
||||
assignmentSource?.episodeNumberStart
|
||||
?? assignmentSource?.episodeNoStart
|
||||
?? assignmentSource?.episodeNumber
|
||||
?? titleSource?.episodeNumber
|
||||
?? (allowTitleEpisodeNumber ? titleSource?.episodeNumber : null)
|
||||
?? fallbackNumber
|
||||
) || fallbackNumber;
|
||||
const explicitEpisodeEnd = normalizePositiveInt(
|
||||
@@ -939,7 +940,135 @@ function resolveEffectiveEpisodeRangeForTitle(assignment = null, title = null, a
|
||||
};
|
||||
}
|
||||
|
||||
function buildDvdSeriesEpisodeOutputPathPreview(settings, metadata, title, assignment = null, fallbackJobId = null, allTitles = []) {
|
||||
function resolveSeriesTitleOrderForPreview(allTitles = [], selectedTitleIds = [], targetTitleId = null) {
|
||||
const explicitSelectedIds = normalizeTitleIdList(selectedTitleIds);
|
||||
const fallbackSelectedIds = explicitSelectedIds.length > 0
|
||||
? explicitSelectedIds
|
||||
: normalizeTitleIdList(
|
||||
(Array.isArray(allTitles) ? allTitles : [])
|
||||
.filter((item) => Boolean(item?.selectedForEncode || item?.encodeInput))
|
||||
.map((item) => item?.id)
|
||||
);
|
||||
let ordered = fallbackSelectedIds;
|
||||
const normalizedTarget = normalizeTitleId(targetTitleId);
|
||||
if (normalizedTarget && !ordered.some((id) => Number(id) === Number(normalizedTarget))) {
|
||||
ordered = [...ordered, Number(normalizedTarget)];
|
||||
}
|
||||
if (ordered.length === 0 && normalizedTarget) {
|
||||
ordered = [Number(normalizedTarget)];
|
||||
}
|
||||
return ordered;
|
||||
}
|
||||
|
||||
function resolveEpisodeRangeForTitleFromAssignments({
|
||||
assignmentByTitle = {},
|
||||
allTitles = [],
|
||||
selectedTitleIds = [],
|
||||
targetTitle = null,
|
||||
fallbackEpisodeNumber = 1
|
||||
}) {
|
||||
const titles = Array.isArray(allTitles) ? allTitles : [];
|
||||
const titlesById = new Map();
|
||||
for (const item of titles) {
|
||||
const id = normalizeTitleId(item?.id);
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
titlesById.set(Number(id), item);
|
||||
}
|
||||
const targetTitleId = normalizeTitleId(targetTitle?.id || null);
|
||||
const orderedTitleIds = resolveSeriesTitleOrderForPreview(titles, selectedTitleIds, targetTitleId);
|
||||
const fallbackStart = normalizePositiveInt(fallbackEpisodeNumber) || 1;
|
||||
let cursor = fallbackStart;
|
||||
let targetRange = null;
|
||||
|
||||
for (const rawId of orderedTitleIds) {
|
||||
const currentId = normalizeTitleId(rawId);
|
||||
if (!currentId) {
|
||||
continue;
|
||||
}
|
||||
const assignment = assignmentByTitle?.[currentId] || assignmentByTitle?.[String(currentId)] || null;
|
||||
const currentTitle = titlesById.get(Number(currentId)) || null;
|
||||
const hasExplicitRange = hasExplicitEpisodeAssignmentRange(assignment);
|
||||
const range = resolveEpisodeAssignmentRange(
|
||||
assignment,
|
||||
currentTitle,
|
||||
cursor,
|
||||
{ allowTitleEpisodeNumber: hasExplicitRange }
|
||||
);
|
||||
const normalizedEnd = normalizePositiveInt(range?.end);
|
||||
if (normalizedEnd !== null) {
|
||||
cursor = normalizedEnd + 1;
|
||||
}
|
||||
if (targetTitleId && Number(currentId) === Number(targetTitleId)) {
|
||||
targetRange = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetRange) {
|
||||
const assignment = targetTitleId
|
||||
? (assignmentByTitle?.[targetTitleId] || assignmentByTitle?.[String(targetTitleId)] || null)
|
||||
: null;
|
||||
const hasExplicitRange = hasExplicitEpisodeAssignmentRange(assignment);
|
||||
targetRange = resolveEpisodeAssignmentRange(
|
||||
assignment,
|
||||
targetTitle,
|
||||
cursor,
|
||||
{ allowTitleEpisodeNumber: hasExplicitRange }
|
||||
);
|
||||
}
|
||||
|
||||
return targetRange;
|
||||
}
|
||||
|
||||
function templateUsesLeadingZeroForToken(template, token) {
|
||||
const source = String(template || '').trim();
|
||||
const normalizedToken = String(token || '').trim();
|
||||
if (!source || !normalizedToken) {
|
||||
return false;
|
||||
}
|
||||
const pattern = new RegExp(`\\{\\s*0\\s*:\\s*${normalizedToken}\\s*\\}`, 'i');
|
||||
return pattern.test(source);
|
||||
}
|
||||
|
||||
function formatEpisodeNumberByTemplate(rawValue, template, token = 'episodeNr') {
|
||||
const numeric = Number(rawValue);
|
||||
if (!Number.isFinite(numeric) || numeric <= 0) {
|
||||
return String(rawValue || '').trim() || '0';
|
||||
}
|
||||
if (!Number.isInteger(numeric)) {
|
||||
return String(numeric);
|
||||
}
|
||||
const normalized = String(Math.trunc(numeric));
|
||||
if (templateUsesLeadingZeroForToken(template, token)) {
|
||||
return normalized.padStart(2, '0');
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function buildFallbackEpisodeTitleForOutput(episodeRange = null, template = '') {
|
||||
const start = normalizePositiveInt(episodeRange?.start) || 1;
|
||||
const end = normalizePositiveInt(episodeRange?.end) || start;
|
||||
if (end > start) {
|
||||
const startToken = formatEpisodeNumberByTemplate(start, template, 'episodeNr');
|
||||
const endToken = formatEpisodeNumberByTemplate(end, template, 'episodeNr');
|
||||
return `Folge ${startToken}-${endToken}`;
|
||||
}
|
||||
const token = formatEpisodeNumberByTemplate(start, template, 'episodeNr');
|
||||
return `Folge ${token}`;
|
||||
}
|
||||
|
||||
function buildDvdSeriesEpisodeOutputPathPreview(
|
||||
settings,
|
||||
metadata,
|
||||
title,
|
||||
assignment = null,
|
||||
fallbackJobId = null,
|
||||
allTitles = [],
|
||||
assignmentByTitle = {},
|
||||
selectedTitleIds = []
|
||||
) {
|
||||
const seriesRootDir = String(
|
||||
settings?.series_dir_dvd
|
||||
|| settings?.movie_dir_dvd
|
||||
@@ -953,15 +1082,28 @@ function buildDvdSeriesEpisodeOutputPathPreview(settings, metadata, title, assig
|
||||
const seasonNumber = normalizePositiveInt(
|
||||
assignment?.seasonNumber ?? metadata?.seasonNumber ?? title?.seasonNumber ?? 1
|
||||
) || 1;
|
||||
const normalizedSelectedIds = normalizeTitleIdList(selectedTitleIds);
|
||||
const targetTitleId = normalizeTitleId(title?.id);
|
||||
const fallbackEpisodeNumber = targetTitleId && normalizedSelectedIds.length > 0
|
||||
? (normalizedSelectedIds.findIndex((id) => Number(id) === Number(targetTitleId)) + 1)
|
||||
: 1;
|
||||
const inferredRange = resolveEpisodeRangeForTitleFromAssignments({
|
||||
assignmentByTitle,
|
||||
allTitles,
|
||||
selectedTitleIds: normalizedSelectedIds,
|
||||
targetTitle: title,
|
||||
fallbackEpisodeNumber: fallbackEpisodeNumber > 0 ? fallbackEpisodeNumber : 1
|
||||
});
|
||||
const episodeRange = resolveEffectiveEpisodeRangeForTitle(
|
||||
assignment,
|
||||
assignment || {},
|
||||
title,
|
||||
allTitles,
|
||||
title?.id || 1
|
||||
inferredRange?.start || (fallbackEpisodeNumber > 0 ? fallbackEpisodeNumber : 1)
|
||||
);
|
||||
const episodeNumber = episodeRange.start;
|
||||
const episodeRangeToken = buildEpisodeRangeToken(episodeRange.start, episodeRange.end);
|
||||
const partsToken = buildEpisodePartsToken(episodeRange);
|
||||
const effectiveEpisodeRange = episodeRange;
|
||||
const episodeNumber = effectiveEpisodeRange.start;
|
||||
const episodeRangeToken = buildEpisodeRangeToken(effectiveEpisodeRange.start, effectiveEpisodeRange.end);
|
||||
const partsToken = buildEpisodePartsToken(effectiveEpisodeRange);
|
||||
const discNumber = normalizePositiveInt(metadata?.discNumber ?? assignment?.discNumber ?? null);
|
||||
const seriesTitleRaw = String(
|
||||
metadata?.title
|
||||
@@ -969,16 +1111,6 @@ function buildDvdSeriesEpisodeOutputPathPreview(settings, metadata, title, assig
|
||||
|| (fallbackJobId ? `job-${fallbackJobId}` : 'series')
|
||||
).trim();
|
||||
const seriesTitle = seriesTitleRaw || 'series';
|
||||
const episodeTitleRaw = String(
|
||||
assignment?.episodeTitle
|
||||
|| title?.episodeTitle
|
||||
|| title?.fileName
|
||||
|| `Episode ${episodeNumber}`
|
||||
).trim();
|
||||
const episodeTitle = normalizeEpisodeTitleForOutput(
|
||||
episodeTitleRaw || `Episode ${episodeRangeToken}`,
|
||||
episodeRange
|
||||
);
|
||||
const year = String(metadata?.year || new Date().getFullYear()).trim();
|
||||
const language = normalizeSeriesLanguage(settings?.dvd_series_language || metadata?.language || null);
|
||||
|
||||
@@ -992,21 +1124,28 @@ function buildDvdSeriesEpisodeOutputPathPreview(settings, metadata, title, assig
|
||||
).trim();
|
||||
const singleTemplate = singleTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeNr} - {episodeTitle}';
|
||||
const multiTemplate = multiTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{0:seasonNr}E{episodeRange} - {episodeTitle} (Teil {parts})';
|
||||
const template = episodeRange.isMulti ? multiTemplate : singleTemplate;
|
||||
const template = effectiveEpisodeRange.isMulti ? multiTemplate : singleTemplate;
|
||||
const fallbackEpisodeTitle = buildFallbackEpisodeTitleForOutput(effectiveEpisodeRange, template);
|
||||
const episodeTitleRaw = String(
|
||||
assignment?.episodeTitle
|
||||
|| title?.episodeTitle
|
||||
|| fallbackEpisodeTitle
|
||||
).trim();
|
||||
const rendered = renderTemplate(template, {
|
||||
seriesTitle,
|
||||
seasonNr: seasonNumber,
|
||||
seasonNo: String(seasonNumber),
|
||||
episodeNr: episodeNumber,
|
||||
episodeNo: String(episodeNumber),
|
||||
episodeNoStart: episodeRange.start,
|
||||
episodeNoEnd: episodeRange.end,
|
||||
episodeNumberStart: episodeRange.start,
|
||||
episodeNumberEnd: episodeRange.end,
|
||||
episodeNoStart: effectiveEpisodeRange.start,
|
||||
episodeNoEnd: effectiveEpisodeRange.end,
|
||||
episodeNumberStart: effectiveEpisodeRange.start,
|
||||
episodeNumberEnd: effectiveEpisodeRange.end,
|
||||
episodeRange: episodeRangeToken,
|
||||
episodeSpan: episodeRange.span,
|
||||
episodeSpan: effectiveEpisodeRange.span,
|
||||
parts: partsToken,
|
||||
episodeTitle,
|
||||
episodeTitle: normalizeEpisodeTitleForOutput(
|
||||
episodeTitleRaw || fallbackEpisodeTitle,
|
||||
effectiveEpisodeRange
|
||||
) || fallbackEpisodeTitle,
|
||||
discNr: discNumber || '',
|
||||
year,
|
||||
language
|
||||
@@ -2380,14 +2519,24 @@ export default function PipelineStatusCard({
|
||||
title,
|
||||
assignment,
|
||||
retryJobId,
|
||||
Array.isArray(mediaInfoReview?.titles) ? mediaInfoReview.titles : []
|
||||
Array.isArray(mediaInfoReview?.titles) ? mediaInfoReview.titles : [],
|
||||
episodeAssignmentsByTitle,
|
||||
selectedEncodeTitleIds
|
||||
);
|
||||
if (path) {
|
||||
map[titleId] = path;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}, [isSeriesDvdReview, mediaInfoReview?.titles, episodeAssignmentsByTitle, settingsMap, selectedMetadata, retryJobId]);
|
||||
}, [
|
||||
isSeriesDvdReview,
|
||||
mediaInfoReview?.titles,
|
||||
episodeAssignmentsByTitle,
|
||||
settingsMap,
|
||||
selectedMetadata,
|
||||
retryJobId,
|
||||
selectedEncodeTitleIds
|
||||
]);
|
||||
const multiEpisodeReviewWarnings = useMemo(() => {
|
||||
if (!isSeriesDvdReview) {
|
||||
return [];
|
||||
|
||||
@@ -1948,9 +1948,17 @@ export default function RipperPage({
|
||||
return;
|
||||
}
|
||||
const job = ripperJobs.find((item) => normalizeJobId(item?.id) === normalizedJobId) || null;
|
||||
const orphanImportSource = String(
|
||||
job?.makemkvInfo?.source
|
||||
|| job?.makemkvInfo?.importRecovery?.source
|
||||
|| ''
|
||||
).trim().toLowerCase();
|
||||
const isOrphanRawImportJob = orphanImportSource === 'orphan_raw_import';
|
||||
const ripSuccessful = Number(job?.rip_successful || 0) === 1;
|
||||
const deleteIncompleteRaw = !ripSuccessful && isIncompleteRawPath(job?.raw_path);
|
||||
const deleteIncompleteRaw = !isOrphanRawImportJob && !ripSuccessful && isIncompleteRawPath(job?.raw_path);
|
||||
const deleteTarget = deleteIncompleteRaw ? 'raw' : 'none';
|
||||
const resetDriveStateOnDelete = !isOrphanRawImportJob;
|
||||
const keepDetectedDeviceOnDelete = isOrphanRawImportJob;
|
||||
const title = String(job?.title || job?.detected_title || `Job #${normalizedJobId}`).trim();
|
||||
const confirmed = await confirmModal({
|
||||
header: 'Job löschen',
|
||||
@@ -1959,9 +1967,13 @@ export default function RipperPage({
|
||||
`${title}\n\n` +
|
||||
(deleteIncompleteRaw
|
||||
? 'Hinweis: Unvollständiges RAW wird gelöscht. Für einen neuen Versuch bitte das Laufwerk erneut analysieren.'
|
||||
: 'Hinweis: Dateien bleiben erhalten. Vollständiges RAW ist anschließend über /database wiederherstellbar.') +
|
||||
: (isOrphanRawImportJob
|
||||
? 'Hinweis: Dieser /database-Job löscht beim Entfernen aus dem Ripper keine RAW-Dateien.'
|
||||
: 'Hinweis: Dateien bleiben erhalten. Vollständiges RAW ist anschließend über /database wiederherstellbar.')) +
|
||||
'\nZugehörige Einträge (z.B. Serien-Container oder Folgejobs) werden ebenfalls entfernt.' +
|
||||
'\nDas zugeordnete Laufwerk wird freigegeben und auf Leerzustand zurückgesetzt.',
|
||||
(isOrphanRawImportJob
|
||||
? '\nOrphan-Import-Job: Das zugeordnete Laufwerk bleibt unverändert.'
|
||||
: '\nDas zugeordnete Laufwerk wird freigegeben und auf Leerzustand zurückgesetzt.'),
|
||||
acceptLabel: 'Löschen',
|
||||
rejectLabel: 'Abbrechen',
|
||||
danger: true
|
||||
@@ -1987,8 +1999,9 @@ export default function RipperPage({
|
||||
}
|
||||
await api.deleteJobEntry(normalizedJobId, deleteTarget, {
|
||||
includeRelated: true,
|
||||
resetDriveState: true,
|
||||
keepDetectedDevice: false
|
||||
resetDriveState: resetDriveStateOnDelete,
|
||||
keepDetectedDevice: keepDetectedDeviceOnDelete,
|
||||
preserveRawForImportJobs: true
|
||||
});
|
||||
await refreshPipeline();
|
||||
await loadRipperJobs();
|
||||
|
||||
Reference in New Issue
Block a user