feat: upload - deel 03
This commit is contained in:
@@ -2,8 +2,7 @@ APP_HOST=0.0.0.0
|
|||||||
APP_PORT=8080
|
APP_PORT=8080
|
||||||
|
|
||||||
APP_DATA_DIR=/app/data
|
APP_DATA_DIR=/app/data
|
||||||
#MEDIA_ROOT=/data/media
|
ALLOWED_MEDIA_ROOTS=/Volumes/8TB/Shared_Folders/Downloads, /Volumes/8TB/Shared_Folders/TV_Shows, /Volumes/8TB_RAID1/Shared_Folders/Library/TV_Shows, /Volumes/8TB_RAID1/Shared_Folders/Library/TV_Shows/#Documentaires
|
||||||
ALLOWED_MEDIA_ROOTS=/Volumes/8TB/Shared_Folders/Downloads, /Volumes/8TB/Shared_Folders/TV_Shows, /Volumes/8TB/Shared_Folders/Library/TV_Shows
|
|
||||||
TVDB_API_KEY=2c951d0c-0b7e-405b-bdb2-e250491dc69d
|
TVDB_API_KEY=2c951d0c-0b7e-405b-bdb2-e250491dc69d
|
||||||
TVDB_PIN=
|
TVDB_PIN=
|
||||||
TVDB_BASE_URL=https://api4.thetvdb.com/v4
|
TVDB_BASE_URL=https://api4.thetvdb.com/v4
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@@ -49,8 +50,6 @@ class FileDiscoveryService:
|
|||||||
iterator = target.iterdir()
|
iterator = target.iterdir()
|
||||||
|
|
||||||
for entry in iterator:
|
for entry in iterator:
|
||||||
if len(files) >= limit:
|
|
||||||
break
|
|
||||||
if not entry.is_file():
|
if not entry.is_file():
|
||||||
continue
|
continue
|
||||||
ext = entry.suffix.lower()
|
ext = entry.suffix.lower()
|
||||||
@@ -74,6 +73,10 @@ class FileDiscoveryService:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
files.sort(key=lambda item: self._natural_sort_key(item.get("relative_path", "")))
|
||||||
|
if len(files) > limit:
|
||||||
|
files = files[:limit]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"root_id": root["id"],
|
"root_id": root["id"],
|
||||||
"root_path": str(root["path"]),
|
"root_path": str(root["path"]),
|
||||||
@@ -83,6 +86,10 @@ class FileDiscoveryService:
|
|||||||
"items": files,
|
"items": files,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _natural_sort_key(self, value: str):
|
||||||
|
text = str(value or "")
|
||||||
|
return [int(part) if part.isdigit() else part.lower() for part in re.split(r"(\d+)", text)]
|
||||||
|
|
||||||
def list_folders(
|
def list_folders(
|
||||||
self,
|
self,
|
||||||
root_id: str,
|
root_id: str,
|
||||||
|
|||||||
@@ -736,6 +736,8 @@ class SessionService:
|
|||||||
proposed_filename=proposed_filename,
|
proposed_filename=proposed_filename,
|
||||||
allowed_roots=allowed_roots,
|
allowed_roots=allowed_roots,
|
||||||
)
|
)
|
||||||
|
if source_path_str and source_path == destination_path:
|
||||||
|
errors = [err for err in errors if err != "source and destination paths are equal"]
|
||||||
|
|
||||||
status = "ready"
|
status = "ready"
|
||||||
if errors:
|
if errors:
|
||||||
@@ -777,17 +779,25 @@ class SessionService:
|
|||||||
for item in preflight_items:
|
for item in preflight_items:
|
||||||
source_path = Path(item["source_path"])
|
source_path = Path(item["source_path"])
|
||||||
destination_path = Path(item["destination_path"])
|
destination_path = Path(item["destination_path"])
|
||||||
os.replace(str(source_path), str(destination_path))
|
rename_needed = source_path != destination_path
|
||||||
|
|
||||||
|
if rename_needed:
|
||||||
|
os.replace(str(source_path), str(destination_path))
|
||||||
|
target_path = destination_path
|
||||||
|
item_status = "renamed"
|
||||||
|
else:
|
||||||
|
target_path = source_path
|
||||||
|
item_status = "unchanged"
|
||||||
|
|
||||||
file_date_status, file_date_detail = self._apply_file_date_after_rename(
|
file_date_status, file_date_detail = self._apply_file_date_after_rename(
|
||||||
enabled=set_file_date_to_first_aired,
|
enabled=set_file_date_to_first_aired,
|
||||||
aired_value=aired_by_index.get(int(item["index"])),
|
aired_value=aired_by_index.get(int(item["index"])),
|
||||||
destination_path=destination_path,
|
destination_path=target_path,
|
||||||
)
|
)
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
**item,
|
**item,
|
||||||
"status": "renamed",
|
"status": item_status,
|
||||||
"errors": [],
|
"errors": [],
|
||||||
"file_date_status": file_date_status,
|
"file_date_status": file_date_status,
|
||||||
"file_date_detail": file_date_detail,
|
"file_date_detail": file_date_detail,
|
||||||
|
|||||||
+13
-2
@@ -213,6 +213,17 @@
|
|||||||
return idx >= 0 ? normalized.slice(idx + 1) : normalized;
|
return idx >= 0 ? normalized.slice(idx + 1) : normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function compareModalFilesByName(a, b) {
|
||||||
|
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" });
|
||||||
|
const aName = (a && (a.name || basename(a.relative_path || a.path || ""))) || "";
|
||||||
|
const bName = (b && (b.name || basename(b.relative_path || b.path || ""))) || "";
|
||||||
|
const byName = collator.compare(aName, bName);
|
||||||
|
if (byName !== 0) return byName;
|
||||||
|
const aPath = (a && (a.relative_path || a.path || "")) || "";
|
||||||
|
const bPath = (b && (b.relative_path || b.path || "")) || "";
|
||||||
|
return collator.compare(aPath, bPath);
|
||||||
|
}
|
||||||
|
|
||||||
function fallbackText(value) {
|
function fallbackText(value) {
|
||||||
const text = (value || "").toString().trim();
|
const text = (value || "").toString().trim();
|
||||||
return text || "-";
|
return text || "-";
|
||||||
@@ -890,7 +901,7 @@
|
|||||||
const visible = (state.modalFiles || []).filter((file) => {
|
const visible = (state.modalFiles || []).filter((file) => {
|
||||||
const text = `${file.relative_path || ""} ${file.name || ""}`.toLowerCase();
|
const text = `${file.relative_path || ""} ${file.name || ""}`.toLowerCase();
|
||||||
return !filter || text.includes(filter);
|
return !filter || text.includes(filter);
|
||||||
});
|
}).sort(compareModalFilesByName);
|
||||||
state.modalVisibleFiles = visible;
|
state.modalVisibleFiles = visible;
|
||||||
|
|
||||||
el.modalFilesList.innerHTML = "";
|
el.modalFilesList.innerHTML = "";
|
||||||
@@ -966,7 +977,7 @@
|
|||||||
|
|
||||||
const recursive = el.modalRecursiveInput.checked ? "true" : "false";
|
const recursive = el.modalRecursiveInput.checked ? "true" : "false";
|
||||||
const data = await api(
|
const data = await api(
|
||||||
`/api/files/discover?root_id=${encodeURIComponent(rootId)}&subpath=${encodeURIComponent(chosenSubpath)}&recursive=${recursive}&limit=200`
|
`/api/files/discover?root_id=${encodeURIComponent(rootId)}&subpath=${encodeURIComponent(chosenSubpath)}&recursive=${recursive}&limit=1000`
|
||||||
);
|
);
|
||||||
state.modalSelectionAnchorPath = null;
|
state.modalSelectionAnchorPath = null;
|
||||||
state.modalFiles = data.items || [];
|
state.modalFiles = data.items || [];
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user