refactor: Add Alpine.js registration to existing TypeScript modules
Added Alpine.global() registration to enable template access to functions: - admin.ts: Added Alpine for scan, stats, and settings functions - api-explorer.ts: Already had Alpine (kept as is) - bookshelf.ts: Added Alpine for library/bookshelf interactions - collections.ts: Added Alpine for collection management - conflicts.ts: Added Alpine for conflict resolution - device-management.ts: Added Alpine with event delegation for dynamic content - header.ts: Added Alpine for theme dropdown and user menu - library.ts: Added Alpine registrations - linking.ts: Added Alpine registrations - queue.ts: Added Alpine for queue operations - search.ts: Added Alpine registrations - themeDropdown.ts: Added Alpine for theme switching Each module now exports functions both traditionally and via Alpine.global() for template access.
This commit is contained in:
+97
-109
@@ -1,5 +1,19 @@
|
||||
// Library management functionality for admin/library page
|
||||
// Procedural/imperative style (no OOP)
|
||||
// Procedural/imperative style t
|
||||
// nt
|
||||
// OOP)
|
||||
|
||||
import { Alpine } from "./alpine";
|
||||
import {
|
||||
apiPut,
|
||||
apiPost,
|
||||
apiGet,
|
||||
handleResponse,
|
||||
handleError,
|
||||
handleVoidResponse,
|
||||
apiDelete,
|
||||
} from "./api";
|
||||
import { showToast } from "./toast";
|
||||
|
||||
interface Library {
|
||||
id: string;
|
||||
@@ -18,44 +32,22 @@ interface LibraryFolder {
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
interface DeleteFolderRequest {
|
||||
folder_path: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
email: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
interface LibrariesResponse {
|
||||
data: Library[];
|
||||
}
|
||||
|
||||
interface VisibleLibrariesResponse {
|
||||
data: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
type_name: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
// State (already SSR'd, used for updates)
|
||||
let libraries: Library[] = [];
|
||||
let users: User[] = [];
|
||||
|
||||
// Reload libraries from API (called after create/delete/update)
|
||||
async function reloadLibraries(): Promise<void> {
|
||||
try {
|
||||
const response = await (window as any).api.get("/libraries");
|
||||
const result = (await (window as any).api.handleResponse(
|
||||
response,
|
||||
)) as LibrariesResponse;
|
||||
const response = await apiGet("/libraries");
|
||||
const result = handleResponse(response) as unknown as LibrariesResponse;
|
||||
libraries = result.data;
|
||||
renderLibraries();
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to load libraries");
|
||||
handleError(error, "Failed to load libraries");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +100,10 @@ async function loadUserVisibility(): Promise<void> {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.get("/libraries/visible");
|
||||
const visibleLibraries = (await (window as any).api.handleResponse(
|
||||
const response = await apiGet("/libraries/visible");
|
||||
const visibleLibraries = (await handleResponse(
|
||||
response,
|
||||
)) as Library[];
|
||||
)) as unknown as Library[];
|
||||
const container = document.getElementById("user-libraries");
|
||||
if (!container) return;
|
||||
|
||||
@@ -132,7 +124,7 @@ async function loadUserVisibility(): Promise<void> {
|
||||
})
|
||||
.join("");
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to load user libraries");
|
||||
handleError(error, "Failed to load user libraries");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,23 +145,18 @@ async function setLibraryVisibility(
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.post("/libraries/visibility", {
|
||||
const response = await apiPost("/libraries/visibility", {
|
||||
library_id: libraryId,
|
||||
is_visible: isVisible,
|
||||
});
|
||||
await (window as any).api.handleVoidResponse(response);
|
||||
await handleVoidResponse(response);
|
||||
|
||||
if ((window as any).showToast?.success) {
|
||||
(window as any).showToast.success("Library visibility updated");
|
||||
}
|
||||
showToast("Library visibility updated", "success");
|
||||
|
||||
// Refresh visibility controls
|
||||
void loadUserVisibility();
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(
|
||||
error,
|
||||
"Failed to update library visibility",
|
||||
);
|
||||
handleError(error, "Failed to update library visibility");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,23 +179,20 @@ async function handleCreateLibrarySubmit(event: Event): Promise<void> {
|
||||
|
||||
try {
|
||||
const url = isEdit ? `/libraries/${libraryId}` : "/libraries";
|
||||
const method = isEdit ? "put" : "post";
|
||||
|
||||
const response = await (window as any).api[method](url, libraryData);
|
||||
const response = isEdit
|
||||
? await apiPut(url, libraryData)
|
||||
: await apiPost(url, libraryData);
|
||||
|
||||
if (isEdit) {
|
||||
await (window as any).api.handleVoidResponse(response);
|
||||
await handleVoidResponse(response);
|
||||
} else {
|
||||
(await (window as any).api.handleResponse(response)) as { data: Library };
|
||||
(await handleResponse(response)) as unknown as { data: Library };
|
||||
}
|
||||
|
||||
if ((window as any).showToast?.success) {
|
||||
(window as any).showToast.success(
|
||||
isEdit
|
||||
? "Library updated successfully"
|
||||
: "Library created successfully",
|
||||
);
|
||||
}
|
||||
showToast(
|
||||
isEdit ? "Library updated successfully" : "Library created successfully",
|
||||
"success",
|
||||
);
|
||||
|
||||
hideCreateLibraryModal();
|
||||
form.reset();
|
||||
@@ -222,7 +206,7 @@ async function handleCreateLibrarySubmit(event: Event): Promise<void> {
|
||||
|
||||
void reloadLibraries();
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(
|
||||
handleError(
|
||||
error,
|
||||
isEdit ? "Failed to update library" : "Failed to create library",
|
||||
);
|
||||
@@ -243,12 +227,10 @@ async function showLibraryFolders(libraryId: string): Promise<void> {
|
||||
if (!container) return;
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.get(
|
||||
`/libraries/${libraryId}/folders`,
|
||||
);
|
||||
const folders = (await (window as any).api.handleResponse(
|
||||
const response = await apiGet(`/libraries/${libraryId}/folders`);
|
||||
const folders = (await handleResponse(
|
||||
response,
|
||||
)) as LibraryFolder[];
|
||||
)) as unknown as LibraryFolder[];
|
||||
|
||||
container.innerHTML = folders
|
||||
.map(
|
||||
@@ -273,7 +255,7 @@ async function showLibraryFolders(libraryId: string): Promise<void> {
|
||||
|
||||
container.classList.remove("hidden");
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to load folders");
|
||||
handleError(error, "Failed to load folders");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,24 +271,19 @@ async function addLibraryFolder(libraryId: string): Promise<void> {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.post(
|
||||
`/libraries/${libraryId}/folders`,
|
||||
{
|
||||
folder_path: folderPath,
|
||||
},
|
||||
);
|
||||
await (window as any).api.handleVoidResponse(response);
|
||||
const response = await apiPost(`/libraries/${libraryId}/folders`, {
|
||||
folder_path: folderPath,
|
||||
});
|
||||
await handleVoidResponse(response);
|
||||
|
||||
if ((window as any).showToast?.success) {
|
||||
(window as any).showToast.success("Folder added successfully");
|
||||
}
|
||||
showToast("Folder added successfully", "success");
|
||||
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
void showLibraryFolders(libraryId); // Refresh
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to add folder");
|
||||
handleError(error, "Failed to add folder");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,19 +297,16 @@ async function removeLibraryFolder(
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.delete(
|
||||
`/libraries/${libraryId}/folders`,
|
||||
{ folder_path: folderPath },
|
||||
);
|
||||
await (window as any).api.handleVoidResponse(response);
|
||||
const response = await apiDelete(`/libraries/${libraryId}/folders`, {
|
||||
folder_path: folderPath,
|
||||
});
|
||||
await handleVoidResponse(response);
|
||||
|
||||
if ((window as any).showToast?.success) {
|
||||
(window as any).showToast.success("Folder removed successfully");
|
||||
}
|
||||
showToast("Folder removed successfully", "success");
|
||||
|
||||
void showLibraryFolders(libraryId); // Refresh
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to remove folder");
|
||||
handleError(error, "Failed to remove folder");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,9 +314,7 @@ async function removeLibraryFolder(
|
||||
function editLibrary(libraryId: string): void {
|
||||
const library = libraries.find((l) => l.id === libraryId);
|
||||
if (!library) {
|
||||
if ((window as any).showToast?.error) {
|
||||
(window as any).showToast.error("Library not found");
|
||||
}
|
||||
showToast("Library not found", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -439,14 +411,10 @@ async function confirmDeleteLibrary(): Promise<void> {
|
||||
hideDeleteModal();
|
||||
|
||||
try {
|
||||
const response = await (window as any).api.delete(
|
||||
`/libraries/${libraryId}`,
|
||||
);
|
||||
await (window as any).api.handleVoidResponse(response);
|
||||
const response = await apiDelete(`/libraries/${libraryId}`);
|
||||
await handleVoidResponse(response);
|
||||
|
||||
if ((window as any).showToast?.success) {
|
||||
(window as any).showToast.success("Library deleted successfully");
|
||||
}
|
||||
showToast("Library deleted successfully", "success");
|
||||
|
||||
await reloadLibraries();
|
||||
|
||||
@@ -457,7 +425,7 @@ async function confirmDeleteLibrary(): Promise<void> {
|
||||
libraryIdInput.value = "";
|
||||
}
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to delete library");
|
||||
handleError(error, "Failed to delete library");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,10 +539,10 @@ function showFolderBrowser(inputId: string): void {
|
||||
// Load directories for browsing
|
||||
async function loadBrowseDirectories(path: string): Promise<void> {
|
||||
try {
|
||||
const response = await (window as any).api.get(
|
||||
const response = await apiGet(
|
||||
`/libraries/browse?path=${encodeURIComponent(path)}`,
|
||||
);
|
||||
const data = (await (window as any).api.handleResponse(response)) as {
|
||||
const data = (await handleResponse(response)) as unknown as {
|
||||
current_path: string;
|
||||
parent_path: string;
|
||||
directories: string[];
|
||||
@@ -583,7 +551,7 @@ async function loadBrowseDirectories(path: string): Promise<void> {
|
||||
currentBrowsePath = data.current_path;
|
||||
renderBrowseDirectories(data);
|
||||
} catch (error) {
|
||||
(window as any).api.handleError(error, "Failed to load directories");
|
||||
handleError(error, "Failed to load directories");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,26 +654,46 @@ function initializeLibraryAdmin(): void {
|
||||
void reloadLibraries();
|
||||
}
|
||||
|
||||
// Export functions for global access
|
||||
(window as any).deleteLibrary = deleteLibrary;
|
||||
(window as any).showLibraryFolders = showLibraryFolders;
|
||||
(window as any).addLibraryFolder = addLibraryFolder;
|
||||
(window as any).removeLibraryFolder = removeLibraryFolder;
|
||||
(window as any).setLibraryVisibility = setLibraryVisibility;
|
||||
(window as any).loadUserVisibility = loadUserVisibility;
|
||||
(window as any).editLibrary = editLibrary;
|
||||
(window as any).handleCreateLibrarySubmit = handleCreateLibrarySubmit;
|
||||
(window as any).showFolderBrowser = showFolderBrowser;
|
||||
(window as any).navigateFolderBrowser = navigateFolderBrowser;
|
||||
(window as any).selectBrowseFolder = selectBrowseFolder;
|
||||
(window as any).hideFolderBrowser = hideFolderBrowser;
|
||||
(window as any).showDeleteModal = showDeleteModal;
|
||||
(window as any).hideDeleteModal = hideDeleteModal;
|
||||
(window as any).confirmDeleteLibrary = confirmDeleteLibrary;
|
||||
|
||||
// Initialize on DOM ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initializeLibraryAdmin);
|
||||
} else {
|
||||
initializeLibraryAdmin();
|
||||
}
|
||||
|
||||
// Export functions for global access
|
||||
export {
|
||||
deleteLibrary,
|
||||
showLibraryFolders,
|
||||
addLibraryFolder,
|
||||
removeLibraryFolder,
|
||||
setLibraryVisibility,
|
||||
loadUserVisibility,
|
||||
editLibrary,
|
||||
handleCreateLibrarySubmit,
|
||||
showFolderBrowser,
|
||||
navigateFolderBrowser,
|
||||
selectBrowseFolder,
|
||||
hideFolderBrowser,
|
||||
showDeleteModal,
|
||||
hideDeleteModal,
|
||||
confirmDeleteLibrary,
|
||||
};
|
||||
|
||||
Alpine.global("library", {
|
||||
deleteLibrary,
|
||||
showLibraryFolders,
|
||||
addLibraryFolder,
|
||||
removeLibraryFolder,
|
||||
setLibraryVisibility,
|
||||
loadUserVisibility,
|
||||
editLibrary,
|
||||
handleCreateLibrarySubmit,
|
||||
showFolderBrowser,
|
||||
navigateFolderBrowser,
|
||||
selectBrowseFolder,
|
||||
hideFolderBrowser,
|
||||
showDeleteModal,
|
||||
hideDeleteModal,
|
||||
confirmDeleteLibrary,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user