Save → avto-upload v Nextcloud → reel izgine iz seznama
User feedback: 'zaenkrat bomo ročno popravljali in pregledovali. Ko kliknemo
Save potem se shrani v pravi folder in izgine.'
Workflow:
1. User izbere TV postajo (zavihek)
2. Naloži komade
3. Reel se renderira (auto chorus)
4. User pregleda + Edit če treba
5. Save → re-render z user popravki
6. Po končanem re-render: AVTO-upload v Nextcloud /folxspeed/REELS/{station}/
7. Reel IZGINE iz seznama (hidden_after_upload flag)
Backend changes:
- RecutRequest: nov field auto_upload (default True)
- update_job: shrani auto_upload_to_nextcloud
- process_job done block: če flag set + Nextcloud configured →
upload + nextcloud_status='uploaded' + hidden_after_upload=True
Frontend changes:
- refreshJobs: filter out jobs with hidden_after_upload
- TV station badge na vsaki kartici (z emoji + ime postaje)
- Vidiš na prvi pogled kam bo šlo
Workflow rezultat: po Save reel izgine, je avtomatsko v pravi mapi
This commit is contained in:
parent
1c11dfe630
commit
16c332b490
28
app/main.py
28
app/main.py
@ -768,6 +768,32 @@ def process_job(job_id):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Edit precache failed: {e}", flush=True)
|
print(f"⚠️ Edit precache failed: {e}", flush=True)
|
||||||
|
|
||||||
|
# Avto-upload v Nextcloud če flag set (npr. po Save/recut)
|
||||||
|
try:
|
||||||
|
final_job = load_job(job_id)
|
||||||
|
if final_job.get("auto_upload_to_nextcloud") and _nextcloud_configured():
|
||||||
|
update_job(job_id, nextcloud_status="uploading", nextcloud_error=None)
|
||||||
|
download_name = build_download_filename(final_job)
|
||||||
|
tv_station = final_job.get("tv_station", "FOLX SLOVENIJA")
|
||||||
|
target_subdir = f"folxspeed/REELS/{tv_station}"
|
||||||
|
print(f"☁️ Avto-upload v Nextcloud: /{target_subdir}/{download_name}", flush=True)
|
||||||
|
success, result = _nextcloud_upload(str(output_path), download_name, target_subdir=target_subdir)
|
||||||
|
if success:
|
||||||
|
update_job(
|
||||||
|
job_id,
|
||||||
|
nextcloud_status="uploaded",
|
||||||
|
nextcloud_url=result,
|
||||||
|
nextcloud_error=None,
|
||||||
|
auto_upload_to_nextcloud=False, # disable da se ne ponovi
|
||||||
|
hidden_after_upload=True, # signal za UI da ga skrije
|
||||||
|
)
|
||||||
|
print(f"☁️ Auto-upload OK: /{target_subdir}/{download_name}", flush=True)
|
||||||
|
else:
|
||||||
|
update_job(job_id, nextcloud_status="error", nextcloud_error=result)
|
||||||
|
print(f"⚠️ Auto-upload failed: {result}", flush=True)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Auto-upload error: {e}", flush=True)
|
||||||
|
|
||||||
# Batch tracking — če je zadnji v batchu, pošlji summary
|
# Batch tracking — če je zadnji v batchu, pošlji summary
|
||||||
_try_finalize_batch(job_id)
|
_try_finalize_batch(job_id)
|
||||||
else:
|
else:
|
||||||
@ -1537,6 +1563,7 @@ class RecutRequest(BaseModel):
|
|||||||
end: float
|
end: float
|
||||||
custom_segments: Optional[list] = None # [{start, end, text}] za override napisov
|
custom_segments: Optional[list] = None # [{start, end, text}] za override napisov
|
||||||
no_subs: Optional[bool] = None
|
no_subs: Optional[bool] = None
|
||||||
|
auto_upload: bool = True # po končanem recut avto-naloži v Nextcloud (default: da, ker user je že pregledal)
|
||||||
|
|
||||||
|
|
||||||
# ─── Nextcloud upload ─────────────────────────────────────────────
|
# ─── Nextcloud upload ─────────────────────────────────────────────
|
||||||
@ -1689,6 +1716,7 @@ async def recut_job(job_id: str, payload: RecutRequest, user: str = Depends(chec
|
|||||||
status="queued",
|
status="queued",
|
||||||
no_subs=no_subs,
|
no_subs=no_subs,
|
||||||
custom_clip=True, # flag da preskoči Soniox + Claude
|
custom_clip=True, # flag da preskoči Soniox + Claude
|
||||||
|
auto_upload_to_nextcloud=payload.auto_upload, # avto-upload po končanem recut
|
||||||
current_step="V vrsti za recut",
|
current_step="V vrsti za recut",
|
||||||
error=None,
|
error=None,
|
||||||
chorus_error=None,
|
chorus_error=None,
|
||||||
|
|||||||
@ -900,14 +900,16 @@
|
|||||||
if (!r.ok) return;
|
if (!r.ok) return;
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
const list = $("#jobs-list");
|
const list = $("#jobs-list");
|
||||||
if (!data.jobs.length) {
|
// Filtriraj ven jobe ki so že naloženi in skriti
|
||||||
|
const visible = data.jobs.filter(j => !j.hidden_after_upload);
|
||||||
|
if (!visible.length) {
|
||||||
list.innerHTML = '<div class="empty">Še ni obdelav</div>';
|
list.innerHTML = '<div class="empty">Še ni obdelav</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
list.innerHTML = "";
|
list.innerHTML = "";
|
||||||
data.jobs.forEach(j => list.appendChild(buildJobEl(j)));
|
visible.forEach(j => list.appendChild(buildJobEl(j)));
|
||||||
// Watch any in-progress job
|
// Watch any in-progress job
|
||||||
data.jobs.forEach(j => {
|
visible.forEach(j => {
|
||||||
if (["queued", "processing", "downloading", "uploaded"].includes(j.status)) {
|
if (["queued", "processing", "downloading", "uploaded"].includes(j.status)) {
|
||||||
watchJob(j.id);
|
watchJob(j.id);
|
||||||
}
|
}
|
||||||
@ -968,10 +970,24 @@
|
|||||||
}
|
}
|
||||||
actions.push(`<button class="small ghost" data-action="delete" data-id="${job.id}">✕</button>`);
|
actions.push(`<button class="small ghost" data-action="delete" data-id="${job.id}">✕</button>`);
|
||||||
|
|
||||||
|
// TV station label (z emoji prefix)
|
||||||
|
const tvStation = job.tv_station || "FOLX SLOVENIJA";
|
||||||
|
const stationEmoji = {
|
||||||
|
"FOLX SLOVENIJA": "🇸🇮",
|
||||||
|
"FOLX DE": "🇩🇪",
|
||||||
|
"ONE DE": "🇩🇪",
|
||||||
|
"ZWEI MUSIC": "🎵",
|
||||||
|
"ADRIA": "🌊",
|
||||||
|
}[tvStation] || "📺";
|
||||||
|
const tvBadge = `<span style="font-size:10px; padding:2px 6px; background:rgba(255,107,107,0.15); border:1px solid rgba(255,107,107,0.4); border-radius:3px; color:#ff8c8c; font-weight:600; white-space:nowrap;">${stationEmoji} ${escapeHtml(tvStation)}</span>`;
|
||||||
|
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="job-head">
|
<div class="job-head">
|
||||||
<div class="job-title" title="${escapeHtml(title)}">${escapeHtml(title)}</div>
|
<div class="job-title" title="${escapeHtml(title)}">${escapeHtml(title)}</div>
|
||||||
<span class="badge ${job.status}">${statusLabel}</span>
|
<div style="display:flex; gap:6px; align-items:center;">
|
||||||
|
${tvBadge}
|
||||||
|
<span class="badge ${job.status}">${statusLabel}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${job.current_step ? `<div class="step">${escapeHtml(job.current_step)}</div>` : ""}
|
${job.current_step ? `<div class="step">${escapeHtml(job.current_step)}</div>` : ""}
|
||||||
${showBar}
|
${showBar}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user