Skip to content
Merged
1 change: 1 addition & 0 deletions cmd/altmount/cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func runServe(cmd *cobra.Command, args []string) error {

apiServer := setupAPIServer(app, repos, authService, configManager, metadataReader, metadataService, fs, poolManager, importerService, arrsService, mountService, progressBroadcaster, streamTracker, cacheSource)
apiServer.SetLogFilePath(slogutil.GetLogFilePath(cfg.Log))
apiServer.SetMigrationRepo(db.MigrationRepo)

webdavHandler, err := setupWebDAV(cfg, fs, authService, repos.UserRepo, configManager, streamTracker)
if err != nil {
Expand Down
32 changes: 31 additions & 1 deletion frontend/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type {
ImportStatusResponse,
LibrarySyncStatus,
ManualScanRequest,
NzbdavMigrateSymlinksRequest,
NzbdavMigrateSymlinksResponse,
PoolMetrics,
QueueHistoricalStatsResponse,
QueueItem,
Expand Down Expand Up @@ -86,7 +88,13 @@ export class APIClient {
if (response.status === 401) {
window.dispatchEvent(new CustomEvent("api:unauthorized"));
}
const errorData = await response.json();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let errorData: any = {};
try {
errorData = await response.json();
} catch {
// empty or non-JSON error body — fall through to status-based message
}
const errorMessage =
(typeof errorData.error === "object" ? errorData.error?.message : errorData.error) ||
errorData.message ||
Expand Down Expand Up @@ -844,6 +852,28 @@ export class APIClient {
});
}

async clearPendingNzbdavMigrations() {
return this.request<{ message: string; data: { deleted: number } }>(
"/import/nzbdav/pending-migrations",
{ method: "DELETE" },
);
}

async clearAllNzbdavMigrations() {
return this.request<{ message: string; data: { deleted: number } }>(
"/import/nzbdav/migrations",
{ method: "DELETE" },
);
}

async migrateNzbdavSymlinks(req: NzbdavMigrateSymlinksRequest) {
return this.request<NzbdavMigrateSymlinksResponse>("/import/nzbdav/migrate-symlinks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(req),
});
}

// SABnzbd file upload endpoint
async uploadNzbFile(file: File, apiKey: string): Promise<SABnzbdAddResponse> {
const formData = new FormData();
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/files/FileBrowserModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ export function FileBrowserModal({
<table className="table-zebra table-sm table">
<thead className="sticky top-0 z-10 bg-base-100">
<tr>
<th /> {/* Icon */}
<th />
{/* Icon */}
<th>Name</th>
<th>Size</th>
<th>Modified</th>
Expand Down
Loading
Loading