@putkoff/abstract-securefiles 0.0.48 → 0.0.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ConfirmButton.d.ts +5 -0
- package/dist/CopyButton.d.ts +4 -0
- package/dist/FolderSelect.d.ts +6 -0
- package/dist/SecureFiles.d.ts +3 -0
- package/dist/ServerFiles.d.ts +6 -0
- package/dist/ShareDialog.d.ts +6 -0
- package/dist/UploadPanel.d.ts +6 -0
- package/dist/api.d.ts +47 -0
- package/dist/index.cjs +529 -1004
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.js +522 -951
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +60 -0
- package/package.json +15 -11
- package/src/ConfirmButton.tsx +35 -0
- package/src/CopyButton.tsx +24 -0
- package/src/FolderSelect.tsx +68 -0
- package/src/SecureFiles.tsx +346 -0
- package/src/ServerFiles.tsx +339 -0
- package/src/ShareDialog.tsx +148 -0
- package/src/UploadPanel.tsx +217 -0
- package/src/api.ts +108 -0
- package/src/index.ts +4 -8
- package/src/styles.css +442 -0
- package/src/types.ts +56 -0
- package/css.d.ts +0 -2
- package/dist/App/SecureFiles.d.ts +0 -4
- package/dist/App/index.d.ts +0 -1
- package/dist/FileHandlers/FileRow/imports.d.ts +0 -2
- package/dist/FileHandlers/FileRow/index.d.ts +0 -1
- package/dist/FileHandlers/FileRow/src/index.d.ts +0 -1
- package/dist/FileHandlers/FileRow/src/row_utils.d.ts +0 -2
- package/dist/FileHandlers/FileTable/imports.d.ts +0 -4
- package/dist/FileHandlers/FileTable/index.d.ts +0 -1
- package/dist/FileHandlers/FileTable/src/index.d.ts +0 -1
- package/dist/FileHandlers/FileTable/src/table_utils.d.ts +0 -2
- package/dist/FileHandlers/ShareModal/imports.d.ts +0 -2
- package/dist/FileHandlers/ShareModal/index.d.ts +0 -1
- package/dist/FileHandlers/ShareModal/src/index.d.ts +0 -1
- package/dist/FileHandlers/ShareModal/src/share_utils.d.ts +0 -2
- package/dist/FileHandlers/Upload/imports.d.ts +0 -2
- package/dist/FileHandlers/Upload/index.d.ts +0 -1
- package/dist/FileHandlers/Upload/src/index.d.ts +0 -2
- package/dist/FileHandlers/Upload/src/upload_utils.d.ts +0 -2
- package/dist/FileHandlers/imports.d.ts +0 -4
- package/dist/FileHandlers/index.d.ts +0 -4
- package/dist/UI/index.d.ts +0 -28
- package/dist/file_utils/imports.d.ts +0 -2
- package/dist/file_utils/index.d.ts +0 -1
- package/dist/file_utils/src/cookieFetch.d.ts +0 -33
- package/dist/file_utils/src/delete_utils/imports.d.ts +0 -1
- package/dist/file_utils/src/delete_utils/index.d.ts +0 -1
- package/dist/file_utils/src/delete_utils/src/delete_row.d.ts +0 -2
- package/dist/file_utils/src/delete_utils/src/delete_select.d.ts +0 -4
- package/dist/file_utils/src/delete_utils/src/delete_selected.d.ts +0 -2
- package/dist/file_utils/src/delete_utils/src/index.d.ts +0 -3
- package/dist/file_utils/src/download_utils/imports.d.ts +0 -2
- package/dist/file_utils/src/download_utils/index.d.ts +0 -1
- package/dist/file_utils/src/download_utils/src/direct_download.d.ts +0 -3
- package/dist/file_utils/src/download_utils/src/download_file.d.ts +0 -6
- package/dist/file_utils/src/download_utils/src/download_select.d.ts +0 -2
- package/dist/file_utils/src/download_utils/src/index.d.ts +0 -5
- package/dist/file_utils/src/download_utils/src/target_downloads.d.ts +0 -4
- package/dist/file_utils/src/download_utils/src/trigger_download.d.ts +0 -2
- package/dist/file_utils/src/imports.d.ts +0 -2
- package/dist/file_utils/src/index.d.ts +0 -6
- package/dist/file_utils/src/list_utils/imports.d.ts +0 -1
- package/dist/file_utils/src/list_utils/index.d.ts +0 -1
- package/dist/file_utils/src/list_utils/src/index.d.ts +0 -1
- package/dist/file_utils/src/list_utils/src/list_utils.d.ts +0 -2
- package/dist/file_utils/src/select_utils/index.d.ts +0 -1
- package/dist/file_utils/src/select_utils/src/index.d.ts +0 -3
- package/dist/file_utils/src/select_utils/src/init_select_all.d.ts +0 -2
- package/dist/file_utils/src/select_utils/src/sync_header_checkbox.d.ts +0 -5
- package/dist/file_utils/src/select_utils/src/toggle_checkboxes.d.ts +0 -2
- package/dist/file_utils/src/share_utils/imports.d.ts +0 -1
- package/dist/file_utils/src/share_utils/index.d.ts +0 -1
- package/dist/file_utils/src/share_utils/src/index.d.ts +0 -1
- package/dist/file_utils/src/share_utils/src/share_utils.d.ts +0 -7
- package/dist/file_utils/src/upload_utils/imports.d.ts +0 -0
- package/dist/file_utils/src/upload_utils/index.d.ts +0 -1
- package/dist/file_utils/src/upload_utils/src/index.d.ts +0 -3
- package/dist/file_utils/src/upload_utils/src/patch_file_settings.d.ts +0 -2
- package/dist/file_utils/src/upload_utils/src/upload_file.d.ts +0 -2
- package/dist/file_utils/src/upload_utils/src/upload_files.d.ts +0 -5
- package/dist/hooks/imports.d.ts +0 -3
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/useFiles/imports.d.ts +0 -2
- package/dist/hooks/useFiles/index.d.ts +0 -1
- package/dist/hooks/useFiles/src/deleteFile.d.ts +0 -3
- package/dist/hooks/useFiles/src/index.d.ts +0 -6
- package/dist/hooks/useFiles/src/load.d.ts +0 -3
- package/dist/hooks/useFiles/src/patchShareSettings.d.ts +0 -3
- package/dist/hooks/useFiles/src/toggleShare.d.ts +0 -3
- package/dist/hooks/useFiles/src/useFiles.d.ts +0 -13
- package/dist/hooks/useFiles/src/useSaveShareSettings.d.ts +0 -7
- package/dist/imports.d.ts +0 -6
- package/dist/index.css +0 -1
- package/dist/styles/index.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/types.d.ts +0 -75
- package/index.ts +0 -1
- package/postcss.config.cjs +0 -8
- package/rollup.config.js +0 -38
- package/rollup.config.mjs +0 -35
- package/src/App/SecureFiles.tsx +0 -45
- package/src/App/index.ts +0 -1
- package/src/FileHandlers/FileRow/imports.ts +0 -2
- package/src/FileHandlers/FileRow/index.ts +0 -1
- package/src/FileHandlers/FileRow/src/index.ts +0 -1
- package/src/FileHandlers/FileRow/src/row_utils.tsx +0 -143
- package/src/FileHandlers/FileTable/imports.ts +0 -15
- package/src/FileHandlers/FileTable/index.ts +0 -1
- package/src/FileHandlers/FileTable/src/index.ts +0 -1
- package/src/FileHandlers/FileTable/src/table_utils.tsx +0 -251
- package/src/FileHandlers/ShareModal/imports.ts +0 -2
- package/src/FileHandlers/ShareModal/index.ts +0 -1
- package/src/FileHandlers/ShareModal/src/index.ts +0 -1
- package/src/FileHandlers/ShareModal/src/share_utils.tsx +0 -155
- package/src/FileHandlers/Upload/imports.ts +0 -3
- package/src/FileHandlers/Upload/index.ts +0 -1
- package/src/FileHandlers/Upload/src/index.ts +0 -2
- package/src/FileHandlers/Upload/src/upload_utils.tsx +0 -369
- package/src/FileHandlers/imports.ts +0 -17
- package/src/FileHandlers/index.ts +0 -4
- package/src/UI/index.tsx +0 -122
- package/src/custom.d.ts +0 -7
- package/src/file_utils/imports.ts +0 -2
- package/src/file_utils/index.ts +0 -1
- package/src/file_utils/src/cookieFetch.ts +0 -109
- package/src/file_utils/src/delete_utils/imports.ts +0 -1
- package/src/file_utils/src/delete_utils/index.ts +0 -1
- package/src/file_utils/src/delete_utils/src/delete_row.ts +0 -11
- package/src/file_utils/src/delete_utils/src/delete_select.ts +0 -10
- package/src/file_utils/src/delete_utils/src/delete_selected.ts +0 -15
- package/src/file_utils/src/delete_utils/src/index.ts +0 -3
- package/src/file_utils/src/download_utils/imports.ts +0 -3
- package/src/file_utils/src/download_utils/index.ts +0 -1
- package/src/file_utils/src/download_utils/src/direct_download.ts +0 -22
- package/src/file_utils/src/download_utils/src/download_file.ts +0 -25
- package/src/file_utils/src/download_utils/src/download_select.ts +0 -25
- package/src/file_utils/src/download_utils/src/index.ts +0 -5
- package/src/file_utils/src/download_utils/src/target_downloads.ts +0 -21
- package/src/file_utils/src/download_utils/src/trigger_download.ts +0 -14
- package/src/file_utils/src/imports.ts +0 -3
- package/src/file_utils/src/index.ts +0 -6
- package/src/file_utils/src/list_utils/imports.ts +0 -2
- package/src/file_utils/src/list_utils/index.ts +0 -1
- package/src/file_utils/src/list_utils/src/index.ts +0 -1
- package/src/file_utils/src/list_utils/src/list_utils.ts +0 -28
- package/src/file_utils/src/select_utils/index.ts +0 -1
- package/src/file_utils/src/select_utils/src/index.ts +0 -3
- package/src/file_utils/src/select_utils/src/init_select_all.ts +0 -37
- package/src/file_utils/src/select_utils/src/sync_header_checkbox.ts +0 -18
- package/src/file_utils/src/select_utils/src/toggle_checkboxes.ts +0 -11
- package/src/file_utils/src/share_utils/imports.ts +0 -1
- package/src/file_utils/src/share_utils/index.ts +0 -1
- package/src/file_utils/src/share_utils/src/index.ts +0 -1
- package/src/file_utils/src/share_utils/src/share_utils.ts +0 -20
- package/src/file_utils/src/upload_utils/imports.ts +0 -1
- package/src/file_utils/src/upload_utils/index.ts +0 -1
- package/src/file_utils/src/upload_utils/src/index.ts +0 -3
- package/src/file_utils/src/upload_utils/src/patch_file_settings.ts +0 -20
- package/src/file_utils/src/upload_utils/src/upload_file.ts +0 -27
- package/src/file_utils/src/upload_utils/src/upload_files.ts +0 -19
- package/src/hooks/imports.ts +0 -3
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useFiles/imports.ts +0 -3
- package/src/hooks/useFiles/index.ts +0 -1
- package/src/hooks/useFiles/src/deleteFile.ts +0 -23
- package/src/hooks/useFiles/src/index.ts +0 -6
- package/src/hooks/useFiles/src/load.ts +0 -39
- package/src/hooks/useFiles/src/logs/clipit_logs.log +0 -0
- package/src/hooks/useFiles/src/logs/routes_bp.log +0 -0
- package/src/hooks/useFiles/src/patchShareSettings.ts +0 -27
- package/src/hooks/useFiles/src/toggleShare.ts +0 -28
- package/src/hooks/useFiles/src/useFiles.ts +0 -35
- package/src/hooks/useFiles/src/useSaveShareSettings.ts +0 -31
- package/src/imports.ts +0 -18
- package/src/styles/SecureFiles/App.css +0 -42
- package/src/styles/SecureFiles/index.css +0 -10
- package/src/styles/SecureFiles/logs/clipit_logs.log +0 -0
- package/src/styles/SecureFiles/logs/routes_bp.log +0 -0
- package/src/styles/SecureFiles/tailwind.css +0 -3
- package/src/styles/SecureFiles/window-manager.css +0 -283
- package/src/styles/SecureFilesStyles.module.css +0 -287
- package/src/styles/index.ts +0 -1
- package/src/types/index.ts +0 -1
- package/src/types/src/index.ts +0 -1
- package/src/types/src/types.ts +0 -88
- package/tailwind.config.cjs +0 -7
- package/testit.mjs +0 -11
- package/testit.ts +0 -3
- package/tsconfig.json +0 -27
- /package/src/{global.d.ts → css.d.ts} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {triggerDownload} from './trigger_download';
|
|
2
|
-
import {FileItem} from './../imports';
|
|
3
|
-
/** Non-React “direct download” used by some old links (kept for parity) */
|
|
4
|
-
export async function directDownload(item: FileItem): Promise<void> {
|
|
5
|
-
const token = localStorage.getItem("token");
|
|
6
|
-
if (!token) throw new Error("No auth token found");
|
|
7
|
-
|
|
8
|
-
const res = await fetch("https://abstractendeavors.com/api/secure-files/secure-download/", {
|
|
9
|
-
method: "POST",
|
|
10
|
-
headers: {
|
|
11
|
-
Authorization: `Bearer ${token}`,
|
|
12
|
-
"Content-Type": "application/json",
|
|
13
|
-
Accept: "application/octet-stream",
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
body: JSON.stringify(item),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
if (!res.ok) throw new Error(`Download failed: ${res.status}`);
|
|
20
|
-
const blob = await res.blob();
|
|
21
|
-
triggerDownload(blob, item.filename);
|
|
22
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { FileItem } from './../imports';
|
|
2
|
-
import { triggerDownload } from './trigger_download';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Download a file using the current session cookie.
|
|
6
|
-
* No JWT / localStorage token required.
|
|
7
|
-
*/
|
|
8
|
-
export async function downloadFile(item: FileItem): Promise<void> {
|
|
9
|
-
const res = await fetch("/api/secure-files/download", {
|
|
10
|
-
method: "POST",
|
|
11
|
-
credentials: "include",
|
|
12
|
-
headers: { "Content-Type": "application/json" },
|
|
13
|
-
body: JSON.stringify({
|
|
14
|
-
id: item.id,
|
|
15
|
-
filepath: item.filepath,
|
|
16
|
-
filename: item.filename,
|
|
17
|
-
}),
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (res.status === 401) throw new Error("Not authenticated – please log in.");
|
|
21
|
-
if (!res.ok) throw new Error(`Download failed: HTTP ${res.status}`);
|
|
22
|
-
|
|
23
|
-
const blob = await res.blob();
|
|
24
|
-
triggerDownload(blob, item.filename || "download");
|
|
25
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { FileItem } from './../imports';
|
|
2
|
-
import { triggerDownload } from './trigger_download';
|
|
3
|
-
import { SECURE_FILES_API_BASE } from './../../cookieFetch';
|
|
4
|
-
|
|
5
|
-
export async function downloadSelect(item: FileItem): Promise<void> {
|
|
6
|
-
const res = await fetch(`${SECURE_FILES_API_BASE}/download`, {
|
|
7
|
-
method: "POST",
|
|
8
|
-
credentials: "include",
|
|
9
|
-
headers: {
|
|
10
|
-
"Content-Type": "application/json",
|
|
11
|
-
Accept: "application/octet-stream",
|
|
12
|
-
},
|
|
13
|
-
body: JSON.stringify(item),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
if (res.status === 401) throw new Error("Not authenticated – please log in.");
|
|
17
|
-
if (!res.ok) throw new Error(`Download failed: HTTP ${res.status}`);
|
|
18
|
-
|
|
19
|
-
const blob = await res.blob();
|
|
20
|
-
if (!blob || blob.size === 0) {
|
|
21
|
-
throw new Error(`Received empty file data for "${item.filename}"`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
triggerDownload(blob, item.filename);
|
|
25
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {downloadSelect} from './download_select';
|
|
2
|
-
import type {FileItem} from './../imports'
|
|
3
|
-
/** Given a checkbox inside a table-row → download that row’s file. */
|
|
4
|
-
export async function downloadRow(cb: HTMLInputElement): Promise<void> {
|
|
5
|
-
const row = cb.closest("tr") as HTMLTableRowElement | null;
|
|
6
|
-
const filepath = cb.value;
|
|
7
|
-
const filename = row?.children[1]?.textContent?.trim() || "downloaded_file";
|
|
8
|
-
if (filepath) await downloadSelect({filepath,filename} as any);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Bulk download: pass a NodeList or array of checkboxes. */
|
|
12
|
-
export async function downloadSelected(checkboxes: Iterable<HTMLInputElement>): Promise<void> {
|
|
13
|
-
const list = Array.from(checkboxes);
|
|
14
|
-
if (!list.length) {
|
|
15
|
-
alert("No files selected.");
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
for (const cb of list) {
|
|
19
|
-
await downloadRow(cb);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** Helper function to trigger file download */
|
|
2
|
-
export function triggerDownload(blob: Blob, filename: string): void {
|
|
3
|
-
const url = URL.createObjectURL(blob);
|
|
4
|
-
const a = Object.assign(document.createElement("a"), {
|
|
5
|
-
href: url,
|
|
6
|
-
download: filename,
|
|
7
|
-
});
|
|
8
|
-
document.body.appendChild(a);
|
|
9
|
-
a.click();
|
|
10
|
-
a.remove();
|
|
11
|
-
URL.revokeObjectURL(url);
|
|
12
|
-
|
|
13
|
-
console.log(`✅ Successfully downloaded: ${filename}`);
|
|
14
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './list_utils';
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { cookieFetch } from './../../cookieFetch';
|
|
2
|
-
import type { ApiRow, FileItem } from './../imports';
|
|
3
|
-
|
|
4
|
-
export async function listFiles(
|
|
5
|
-
setFiles: ((rows: FileItem[]) => void) | null = null,
|
|
6
|
-
): Promise<FileItem[]> {
|
|
7
|
-
const result = await cookieFetch<ApiRow[] | { result: ApiRow[] }>("list", undefined, "GET");
|
|
8
|
-
const apiRows: ApiRow[] = Array.isArray(result)
|
|
9
|
-
? result
|
|
10
|
-
: ((result as any)?.result ?? []);
|
|
11
|
-
|
|
12
|
-
const rows: FileItem[] = apiRows.map((r: ApiRow) => ({
|
|
13
|
-
id: r.id,
|
|
14
|
-
filename: r.filename,
|
|
15
|
-
uploader_id: r.uploader_id,
|
|
16
|
-
filepath: r.filepath,
|
|
17
|
-
created_at: r.created_at,
|
|
18
|
-
download_count: r.download_count,
|
|
19
|
-
download_limit: r.download_limit,
|
|
20
|
-
shareable: Boolean(r.shareable),
|
|
21
|
-
needsPassword: !!r.share_password,
|
|
22
|
-
share_password: r.share_password,
|
|
23
|
-
password_str: r.password_str,
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
if (setFiles) setFiles(rows);
|
|
27
|
-
return rows;
|
|
28
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {syncHeaderCheckbox} from './sync_header_checkbox';
|
|
2
|
-
/** Wire up header + row checkboxes once the table is in the DOM. */
|
|
3
|
-
export function initSelectAll(): void {
|
|
4
|
-
const header = document.getElementById(
|
|
5
|
-
"select-all-checkbox"
|
|
6
|
-
) as HTMLInputElement;
|
|
7
|
-
const btn = document.getElementById("select-all") as HTMLButtonElement;
|
|
8
|
-
|
|
9
|
-
// 1) header → toggle all
|
|
10
|
-
header.addEventListener("change", (e) => {
|
|
11
|
-
const on = (e.target as HTMLInputElement).checked;
|
|
12
|
-
document
|
|
13
|
-
.querySelectorAll<HTMLInputElement>(".file-checkbox")
|
|
14
|
-
.forEach((cb) => (cb.checked = on));
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// 2) button → toggle all
|
|
18
|
-
btn.addEventListener("click", () => {
|
|
19
|
-
const cbs = Array.from(
|
|
20
|
-
document.querySelectorAll<HTMLInputElement>(".file-checkbox")
|
|
21
|
-
);
|
|
22
|
-
if (!cbs.length) {
|
|
23
|
-
alert("No files to select.");
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
27
|
-
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
28
|
-
syncHeaderCheckbox();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// 3) row boxes → keep header state
|
|
32
|
-
document
|
|
33
|
-
.querySelectorAll<HTMLInputElement>(".file-checkbox")
|
|
34
|
-
.forEach((cb) => cb.addEventListener("change", syncHeaderCheckbox));
|
|
35
|
-
|
|
36
|
-
syncHeaderCheckbox();
|
|
37
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Classic “select all rows” logic (still handy in non-React views
|
|
3
|
-
* such as the admin dashboard).
|
|
4
|
-
*/
|
|
5
|
-
export function syncHeaderCheckbox(): void {
|
|
6
|
-
const all = document.querySelectorAll<HTMLInputElement>(".file-checkbox");
|
|
7
|
-
const checked = document.querySelectorAll<HTMLInputElement>(
|
|
8
|
-
".file-checkbox:checked"
|
|
9
|
-
);
|
|
10
|
-
const header = document.getElementById(
|
|
11
|
-
"select-all-checkbox"
|
|
12
|
-
) as HTMLInputElement;
|
|
13
|
-
|
|
14
|
-
header.indeterminate =
|
|
15
|
-
checked.length > 0 && checked.length < all.length;
|
|
16
|
-
header.checked = checked.length === all.length;
|
|
17
|
-
}
|
|
18
|
-
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {syncHeaderCheckbox} from './sync_header_checkbox';
|
|
2
|
-
/** Utility for other screens: toggle a list of checkboxes on/off. */
|
|
3
|
-
export function toggleCheckboxes(cbs: HTMLInputElement[]): void {
|
|
4
|
-
if (!cbs.length) {
|
|
5
|
-
alert("No files to select.");
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
const anyUnchecked = cbs.some((cb) => !cb.checked);
|
|
9
|
-
cbs.forEach((cb) => (cb.checked = anyUnchecked));
|
|
10
|
-
syncHeaderCheckbox();
|
|
11
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type { FileItem } from './../../../types/src/types'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './share_utils';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { cookieFetch } from './../../cookieFetch';
|
|
2
|
-
import type { FileItem } from './../imports';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Toggle sharing on a file.
|
|
6
|
-
* Sends the updated settings to /api/secure-files/files/share.
|
|
7
|
-
* Does NOT update local state – the caller is responsible for that.
|
|
8
|
-
*/
|
|
9
|
-
export async function toggleShare(file: FileItem): Promise<void> {
|
|
10
|
-
const updated: FileItem = { ...file, shareable: !file.shareable };
|
|
11
|
-
if (!updated.shareable) updated.needsPassword = false;
|
|
12
|
-
|
|
13
|
-
await cookieFetch("files/share", {
|
|
14
|
-
id: updated.id,
|
|
15
|
-
shareable: updated.shareable,
|
|
16
|
-
share_password: updated.share_password ?? null,
|
|
17
|
-
password_str: updated.password_str ?? null,
|
|
18
|
-
download_limit: updated.download_limit ?? null,
|
|
19
|
-
}, "POST");
|
|
20
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// No legacy auth imports needed — upload_file.ts uses cookieUpload directly.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const API_BASE = '/api/secure-files';
|
|
2
|
-
|
|
3
|
-
/** Generic PATCH helper for file-level admin settings. */
|
|
4
|
-
export async function patchFileSetting(
|
|
5
|
-
fileId: string,
|
|
6
|
-
field: string,
|
|
7
|
-
value: unknown,
|
|
8
|
-
): Promise<Record<string, unknown>> {
|
|
9
|
-
const res = await fetch(`${API_BASE}/files/${fileId}/settings/${field}`, {
|
|
10
|
-
method: 'PATCH',
|
|
11
|
-
credentials: 'include',
|
|
12
|
-
headers: { 'Content-Type': 'application/json' },
|
|
13
|
-
body: JSON.stringify({ value }),
|
|
14
|
-
});
|
|
15
|
-
if (!res.ok) {
|
|
16
|
-
const err = await res.json().catch(() => ({}));
|
|
17
|
-
throw new Error((err as any).error || res.statusText);
|
|
18
|
-
}
|
|
19
|
-
return (await res.json()) as Record<string, unknown>;
|
|
20
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { cookieUpload } from './../../cookieFetch';
|
|
2
|
-
|
|
3
|
-
/** File-upload helper (used by non-React fallback pages). */
|
|
4
|
-
export async function uploadFile(file: any, subdir: any): Promise<any> {
|
|
5
|
-
const fileInput = file || document.getElementById('file-browser') as HTMLInputElement;
|
|
6
|
-
const subdirInput = subdir || document.getElementById('subdir') as HTMLInputElement;
|
|
7
|
-
const banner = document.getElementById('banner') as HTMLElement;
|
|
8
|
-
|
|
9
|
-
if (!fileInput.files?.length) {
|
|
10
|
-
alert('No file selected.');
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const f = fileInput.files[0];
|
|
15
|
-
const dir = (subdirInput?.value ?? '').trim();
|
|
16
|
-
const relPath = dir ? `${dir}/${f.name}` : f.name;
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
const json = await cookieUpload(f, relPath) as { filepath: string };
|
|
20
|
-
if (banner) banner.textContent = `Uploaded: ${json.filepath}`;
|
|
21
|
-
fileInput.value = '';
|
|
22
|
-
if (subdirInput) subdirInput.value = '';
|
|
23
|
-
window.location.reload();
|
|
24
|
-
} catch (err: any) {
|
|
25
|
-
console.error('Upload failed', err);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { cookieUpload } from './../../cookieFetch';
|
|
2
|
-
|
|
3
|
-
interface UploadResponse {
|
|
4
|
-
filepath: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export async function uploadFiles(
|
|
8
|
-
file: File,
|
|
9
|
-
subdir: string = '',
|
|
10
|
-
): Promise<UploadResponse> {
|
|
11
|
-
if (!(file instanceof File)) throw new Error('Invalid file: must be a File object.');
|
|
12
|
-
if (typeof subdir !== 'string') throw new Error('Invalid subdir: must be a string.');
|
|
13
|
-
|
|
14
|
-
const relPath = subdir.trim() ? `${subdir.trim()}/${file.name}` : file.name;
|
|
15
|
-
const json = await cookieUpload(file, relPath) as { filepath?: string };
|
|
16
|
-
|
|
17
|
-
if (!json?.filepath) throw new Error('Server response missing filepath.');
|
|
18
|
-
return { filepath: json.filepath };
|
|
19
|
-
}
|
package/src/hooks/imports.ts
DELETED
package/src/hooks/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './useFiles';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCallback } from './../imports';
|
|
3
|
-
import type { FileItem } from './../imports';
|
|
4
|
-
import { cookieFetch } from '../../../file_utils/src/cookieFetch';
|
|
5
|
-
|
|
6
|
-
export const useDeleteFile = (
|
|
7
|
-
setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>,
|
|
8
|
-
) => {
|
|
9
|
-
return useCallback(
|
|
10
|
-
async (file: FileItem | FileItem[]) => {
|
|
11
|
-
const targets = Array.isArray(file) ? file : [file];
|
|
12
|
-
for (const f of targets) {
|
|
13
|
-
try {
|
|
14
|
-
await cookieFetch("remove", { id: f.id }, "POST");
|
|
15
|
-
setFiles(curr => curr.filter(item => item.id !== f.id));
|
|
16
|
-
} catch (err) {
|
|
17
|
-
console.error(`Failed to delete "${f.filename}":`, err);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
[setFiles],
|
|
22
|
-
);
|
|
23
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCallback } from './../imports';
|
|
3
|
-
import type { FileItem, ApiRow } from './../imports';
|
|
4
|
-
import { cookieFetch } from '../../../file_utils/src/cookieFetch';
|
|
5
|
-
|
|
6
|
-
export const useLoadFiles = (
|
|
7
|
-
setLoading: React.Dispatch<React.SetStateAction<boolean>>,
|
|
8
|
-
setError: React.Dispatch<React.SetStateAction<Error | null>>,
|
|
9
|
-
setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>,
|
|
10
|
-
) => {
|
|
11
|
-
return useCallback(async () => {
|
|
12
|
-
setLoading(true);
|
|
13
|
-
setError(null);
|
|
14
|
-
try {
|
|
15
|
-
const result = await cookieFetch<ApiRow[] | { result: ApiRow[] }>("list", undefined, "GET");
|
|
16
|
-
const apiRows: ApiRow[] = Array.isArray(result)
|
|
17
|
-
? result
|
|
18
|
-
: ((result as any)?.result ?? []);
|
|
19
|
-
|
|
20
|
-
setFiles(apiRows.map((r: ApiRow) => ({
|
|
21
|
-
id: r.id,
|
|
22
|
-
filename: r.filename,
|
|
23
|
-
uploader_id: r.uploader_id,
|
|
24
|
-
filepath: r.filepath,
|
|
25
|
-
created_at: r.created_at,
|
|
26
|
-
download_count: r.download_count,
|
|
27
|
-
download_limit: r.download_limit,
|
|
28
|
-
shareable: Boolean(r.shareable),
|
|
29
|
-
needsPassword: !!r.share_password,
|
|
30
|
-
share_password: r.share_password,
|
|
31
|
-
password_str: r.password_str,
|
|
32
|
-
})));
|
|
33
|
-
} catch (err) {
|
|
34
|
-
setError(err instanceof Error ? err : new Error('Failed to load files'));
|
|
35
|
-
} finally {
|
|
36
|
-
setLoading(false);
|
|
37
|
-
}
|
|
38
|
-
}, [setLoading, setError, setFiles]);
|
|
39
|
-
};
|
|
File without changes
|
|
File without changes
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCallback } from './../imports';
|
|
3
|
-
import { cookieFetch } from '../../../file_utils/src/cookieFetch';
|
|
4
|
-
|
|
5
|
-
export const usePatchShareSettings = (
|
|
6
|
-
setFiles: React.Dispatch<React.SetStateAction<any[]>>,
|
|
7
|
-
) => {
|
|
8
|
-
return useCallback(
|
|
9
|
-
async (file: any) => {
|
|
10
|
-
const body = {
|
|
11
|
-
id: file.id,
|
|
12
|
-
shareable: file.shareable,
|
|
13
|
-
share_password: file.share_password ?? null,
|
|
14
|
-
password_str: file.password_str ?? null,
|
|
15
|
-
download_limit: file.download_limit ?? null,
|
|
16
|
-
};
|
|
17
|
-
try {
|
|
18
|
-
await cookieFetch("files/share", body, "POST");
|
|
19
|
-
setFiles(curr => curr.map(f => f.id === body.id ? { ...f, ...body } : f));
|
|
20
|
-
} catch (err) {
|
|
21
|
-
console.error('Failed to update share settings:', err);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
[setFiles],
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
export default usePatchShareSettings;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCallback } from './../imports';
|
|
3
|
-
import type { FileItem } from './../imports';
|
|
4
|
-
import { cookieFetch } from '../../../file_utils/src/cookieFetch';
|
|
5
|
-
|
|
6
|
-
export const useToggleShare = (
|
|
7
|
-
setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>,
|
|
8
|
-
) => {
|
|
9
|
-
return useCallback(
|
|
10
|
-
async (file: FileItem) => {
|
|
11
|
-
const updated: FileItem = { ...file, shareable: !file.shareable };
|
|
12
|
-
if (!updated.shareable) updated.needsPassword = false;
|
|
13
|
-
try {
|
|
14
|
-
await cookieFetch("files/share", {
|
|
15
|
-
id: updated.id,
|
|
16
|
-
shareable: updated.shareable,
|
|
17
|
-
share_password: updated.share_password ?? null,
|
|
18
|
-
password_str: updated.password_str ?? null,
|
|
19
|
-
download_limit: updated.download_limit ?? null,
|
|
20
|
-
}, "POST");
|
|
21
|
-
setFiles(curr => curr.map(f => f.id === file.id ? updated : f));
|
|
22
|
-
} catch (err) {
|
|
23
|
-
console.error('Failed to toggle share:', err);
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
[setFiles],
|
|
27
|
-
);
|
|
28
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import type {FileItem} from './../imports';
|
|
3
|
-
import { useLoadFiles } from './load';
|
|
4
|
-
import { useToggleShare } from './toggleShare';
|
|
5
|
-
import {useSaveShareSettings} from './useSaveShareSettings';
|
|
6
|
-
import { useDeleteFile } from './deleteFile';
|
|
7
|
-
|
|
8
|
-
export function useFiles() {
|
|
9
|
-
const [files, setFiles] = useState<FileItem[]>([]);
|
|
10
|
-
const [loading, setLoading] = useState<boolean>(false);
|
|
11
|
-
const [error, setError] = useState<Error | null>(null);
|
|
12
|
-
|
|
13
|
-
const loadCallback = useLoadFiles(setLoading, setError, setFiles);
|
|
14
|
-
const toggleShareCallback = useToggleShare(setFiles);
|
|
15
|
-
const patchShareSettingsCallback = useSaveShareSettings(setFiles);
|
|
16
|
-
const deleteFileCallback = useDeleteFile(setFiles);
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
loadCallback();
|
|
20
|
-
}, [loadCallback]);
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
files,
|
|
24
|
-
loading,
|
|
25
|
-
error,
|
|
26
|
-
load: loadCallback,
|
|
27
|
-
toggleShare: toggleShareCallback,
|
|
28
|
-
patchShareSettings: patchShareSettingsCallback,
|
|
29
|
-
deleteFile: deleteFileCallback,
|
|
30
|
-
setFiles,
|
|
31
|
-
setLoading,
|
|
32
|
-
setError,
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useCallback } from './../imports';
|
|
3
|
-
import { cookieFetch } from '../../../file_utils/src/cookieFetch';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook alias used by useFiles.ts. Patches share settings via the session-cookie
|
|
7
|
-
* authenticated /files/share endpoint.
|
|
8
|
-
*/
|
|
9
|
-
export const useSaveShareSettings = (
|
|
10
|
-
setFiles: React.Dispatch<React.SetStateAction<any[]>>,
|
|
11
|
-
) => {
|
|
12
|
-
return useCallback(
|
|
13
|
-
async (file: any) => {
|
|
14
|
-
const body = {
|
|
15
|
-
id: file.id,
|
|
16
|
-
shareable: file.shareable,
|
|
17
|
-
share_password: file.share_password ?? null,
|
|
18
|
-
password_str: file.password_str ?? null,
|
|
19
|
-
download_limit: file.download_limit ?? null,
|
|
20
|
-
};
|
|
21
|
-
try {
|
|
22
|
-
await cookieFetch("files/share", body, "POST");
|
|
23
|
-
setFiles(curr => curr.map(f => f.id === body.id ? { ...f, ...body } : f));
|
|
24
|
-
} catch (err) {
|
|
25
|
-
console.error('Failed to save share settings:', err);
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
[setFiles],
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
export default useSaveShareSettings;
|
package/src/imports.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export { createPortal } from "react-dom";
|
|
2
|
-
export { ClipboardIcon, CloudArrowUpIcon } from "@heroicons/react/24/outline";
|
|
3
|
-
export {useEffect,useRef,useState,useCallback} from 'react';
|
|
4
|
-
export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps, ApiRow, EnhancedInputProps } from './types';
|
|
5
|
-
export {
|
|
6
|
-
currentUsername,
|
|
7
|
-
alertit,
|
|
8
|
-
requireToken,
|
|
9
|
-
isLoggedIn,
|
|
10
|
-
fetchIt,
|
|
11
|
-
stripPrefixes,
|
|
12
|
-
make_path
|
|
13
|
-
} from "@putkoff/abstract-utilities";
|
|
14
|
-
export {
|
|
15
|
-
Button,
|
|
16
|
-
Checkbox,
|
|
17
|
-
Input,
|
|
18
|
-
Spinner} from './UI';
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
body {
|
|
3
|
-
margin: 0;
|
|
4
|
-
font-family:
|
|
5
|
-
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
6
|
-
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
7
|
-
sans-serif;
|
|
8
|
-
-webkit-font-smoothing: antialiased;
|
|
9
|
-
-moz-osx-font-smoothing: grayscale;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
code {
|
|
13
|
-
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.logo {
|
|
18
|
-
height: 6em;
|
|
19
|
-
padding: 1.5em;
|
|
20
|
-
will-change: filter;
|
|
21
|
-
transition: filter 300ms;
|
|
22
|
-
}
|
|
23
|
-
.logo:hover {
|
|
24
|
-
filter: drop-shadow(0 0 2em #646cffaa);
|
|
25
|
-
}
|
|
26
|
-
.logo.react:hover {
|
|
27
|
-
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@keyframes logo-spin {
|
|
31
|
-
from { transform: rotate(0deg); }
|
|
32
|
-
to { transform: rotate(360deg); }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
36
|
-
a:nth-of-type(2) .logo {
|
|
37
|
-
animation: logo-spin infinite 20s linear;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.card { padding: 2em; }
|
|
42
|
-
.read-the-docs { color: #888; }
|