@putkoff/abstract-securefiles 0.0.25 → 0.0.28
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/css.d.ts +0 -0
- package/dist/index.cjs +3 -933
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -8
- package/dist/index.js +5 -884
- package/dist/index.js.map +1 -1
- package/dist/{App/SecureFiles.d.ts → secure_files.d.ts} +1 -1
- package/index.ts +0 -0
- package/package.json +4 -4
- package/postcss.config.cjs +0 -0
- package/rollup.config.mjs +0 -0
- package/src/index.ts +1 -8
- package/src/{App/SecureFiles.tsx → secure_files.tsx} +4 -3
- package/tailwind.config.cjs +0 -0
- package/tsconfig.json +0 -0
- 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 -19
- package/dist/file_utils/imports.d.ts +0 -2
- package/dist/file_utils/index.d.ts +0 -1
- 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 -1
- 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 -2
- 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 -2
- 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 -2
- 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 -1
- 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 -6
- package/dist/hooks/useFiles/src/index.d.ts +0 -6
- package/dist/hooks/useFiles/src/load.d.ts +0 -6
- package/dist/hooks/useFiles/src/patchShareSettings.d.ts +0 -7
- package/dist/hooks/useFiles/src/toggleShare.d.ts +0 -6
- package/dist/hooks/useFiles/src/useFiles.d.ts +0 -13
- package/dist/hooks/useFiles/src/useSaveShareSettings.d.ts +0 -3
- package/dist/imports.d.ts +0 -5
- 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/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 -16
- 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 -158
- 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 -267
- package/src/FileHandlers/imports.ts +0 -20
- package/src/FileHandlers/index.ts +0 -4
- package/src/UI/index.tsx +0 -113
- 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/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 -9
- 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 -24
- package/src/file_utils/src/download_utils/src/download_select.ts +0 -20
- 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 -24
- 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 -2
- 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 -29
- 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 -18
- package/src/file_utils/src/upload_utils/src/upload_file.ts +0 -28
- package/src/file_utils/src/upload_utils/src/upload_files.ts +0 -34
- package/src/global.d.ts +0 -1
- 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 -22
- package/src/hooks/useFiles/src/index.ts +0 -6
- package/src/hooks/useFiles/src/load.ts +0 -52
- package/src/hooks/useFiles/src/logs/routes_bp.log +0 -0
- package/src/hooks/useFiles/src/patchShareSettings.ts +0 -37
- 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 -25
- package/src/imports.ts +0 -20
- package/src/styles/SecureFiles/logs/clipit_logs.log +0 -0
- package/src/styles/SecureFiles/logs/routes_bp.log +0 -0
- 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/test/package-lock.json +0 -979
- package/test/package.json +0 -23
- package/test/test_entry.ts +0 -8
- package/test/tsconfig.json +0 -12
- /package/{src/hooks/useFiles/src/logs/clipit_logs.log → package.tmp.json} +0 -0
- /package/src/styles/{SecureFiles/App.css → App.css} +0 -0
- /package/src/styles/{SecureFiles/index.css → index.css} +0 -0
- /package/src/styles/{SecureFiles/tailwind.css → tailwind.css} +0 -0
- /package/src/styles/{SecureFiles/window-manager.css → window-manager.css} +0 -0
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ShareModalProps
|
|
3
|
-
} from './../../imports';
|
|
4
|
-
import {
|
|
5
|
-
Button,
|
|
6
|
-
Checkbox,
|
|
7
|
-
Input,
|
|
8
|
-
ClipboardIcon,
|
|
9
|
-
createPortal,
|
|
10
|
-
useEffect,
|
|
11
|
-
useRef,
|
|
12
|
-
useState,
|
|
13
|
-
} from './../imports';
|
|
14
|
-
import { alertit } from '@putkoff/abstract-utilities'
|
|
15
|
-
|
|
16
|
-
export default function ShareModal({ file, onClose, onSave }: ShareModalProps) {
|
|
17
|
-
const [fileId, setFileId] = useState<string | number | "">("");
|
|
18
|
-
const [enabled, setEnabled] = useState<any>(false);
|
|
19
|
-
const [password, setPassword] = useState<any>(undefined);
|
|
20
|
-
const [strPassword, setStrPassword] = useState<any>("");
|
|
21
|
-
const [download_limit, setDownloadLimit] = useState<number | "">(0);
|
|
22
|
-
const [error, setError] = useState("");
|
|
23
|
-
const [busy, setBusy] = useState(false);
|
|
24
|
-
const modalRef = useRef<HTMLDivElement>(null);
|
|
25
|
-
|
|
26
|
-
const shareLink =
|
|
27
|
-
file && enabled
|
|
28
|
-
? `https://abstractendeavors.com/api/secure-files/secure-download/${file.id}`
|
|
29
|
-
: "";
|
|
30
|
-
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
if (!file) return;
|
|
33
|
-
setFileId(file.id);
|
|
34
|
-
setEnabled(file.shareable);
|
|
35
|
-
// load both values from the `file` prop
|
|
36
|
-
setPassword(file.share_password);
|
|
37
|
-
setStrPassword(file.password_str ?? "");
|
|
38
|
-
setDownloadLimit(file.download_limit ?? 0);
|
|
39
|
-
setError("");
|
|
40
|
-
|
|
41
|
-
modalRef.current?.focus();
|
|
42
|
-
}, [file]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
const h = (e: KeyboardEvent) => e.key === "Escape" && onClose();
|
|
47
|
-
window.addEventListener("keydown", h);
|
|
48
|
-
return () => window.removeEventListener("keydown", h);
|
|
49
|
-
}, [onClose]);
|
|
50
|
-
|
|
51
|
-
if (!file) return null;
|
|
52
|
-
|
|
53
|
-
async function handleSave() {
|
|
54
|
-
if (strPassword && strPassword.length < 4) {
|
|
55
|
-
setError("Password must be at least 4 characters");
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
setBusy(true);
|
|
59
|
-
const save_dict = {
|
|
60
|
-
id: fileId,
|
|
61
|
-
shareable: enabled,
|
|
62
|
-
needsPassword: !!strPassword,
|
|
63
|
-
share_password: strPassword || null,
|
|
64
|
-
password_str: strPassword || null,
|
|
65
|
-
download_limit: download_limit === "" ? null : Number(download_limit),
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const resp = await onSave(save_dict);
|
|
70
|
-
|
|
71
|
-
onClose();
|
|
72
|
-
} catch (err) {
|
|
73
|
-
setError(`${err} Failed to save settings. Please try again.`);
|
|
74
|
-
} finally {
|
|
75
|
-
setBusy(false);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return createPortal(
|
|
80
|
-
<>
|
|
81
|
-
<div
|
|
82
|
-
className="modal-backdrop z-100"
|
|
83
|
-
onClick={(e) => e.target === e.currentTarget && onClose()}
|
|
84
|
-
/>
|
|
85
|
-
<div className="modal-wrapper z-110">
|
|
86
|
-
<div
|
|
87
|
-
ref={modalRef}
|
|
88
|
-
role="dialog"
|
|
89
|
-
aria-modal="true"
|
|
90
|
-
tabIndex={-1}
|
|
91
|
-
className="modal-panel"
|
|
92
|
-
>
|
|
93
|
-
<h3 className="form-title">
|
|
94
|
-
Share settings for <span className="font-mono">{file.filename}</span>
|
|
95
|
-
</h3>
|
|
96
|
-
|
|
97
|
-
{error && <p className="form-error">{error}</p>}
|
|
98
|
-
|
|
99
|
-
<Checkbox
|
|
100
|
-
label="Enable sharing"
|
|
101
|
-
checked={enabled}
|
|
102
|
-
onChange={(e) => setEnabled(e.target.checked)}
|
|
103
|
-
className="checkbox"
|
|
104
|
-
/>
|
|
105
|
-
|
|
106
|
-
{/* This is the admin-editable plain-text password */}
|
|
107
|
-
<Input
|
|
108
|
-
label="Password (optional)"
|
|
109
|
-
type="text"
|
|
110
|
-
value={strPassword}
|
|
111
|
-
onChange={(e) => setStrPassword(e.target.value)}
|
|
112
|
-
disabled={!enabled}
|
|
113
|
-
className="form-input"
|
|
114
|
-
/>
|
|
115
|
-
<Input
|
|
116
|
-
label="Download limit (0 = ∞)"
|
|
117
|
-
type="number"
|
|
118
|
-
min={0}
|
|
119
|
-
value={download_limit}
|
|
120
|
-
onChange={(e) =>
|
|
121
|
-
setDownloadLimit(e.target.value === "" ? "" : Number(e.target.value))
|
|
122
|
-
}
|
|
123
|
-
disabled={!enabled}
|
|
124
|
-
className="form-input"
|
|
125
|
-
/>
|
|
126
|
-
|
|
127
|
-
{enabled && shareLink && (
|
|
128
|
-
<Input
|
|
129
|
-
label="Share link"
|
|
130
|
-
readOnly
|
|
131
|
-
value={shareLink}
|
|
132
|
-
className="form-input"
|
|
133
|
-
trailing={
|
|
134
|
-
<Button
|
|
135
|
-
variant="icon"
|
|
136
|
-
className="btn-icon"
|
|
137
|
-
onClick={() => navigator.clipboard.writeText(shareLink)}
|
|
138
|
-
>
|
|
139
|
-
<ClipboardIcon className="h-5 w-5" />
|
|
140
|
-
</Button>
|
|
141
|
-
}
|
|
142
|
-
/>
|
|
143
|
-
)}
|
|
144
|
-
|
|
145
|
-
<div className="mt-6 flex justify-end gap-2">
|
|
146
|
-
<Button color="green" variant="primary" onClick={handleSave} disabled={busy} className="btn-primary">
|
|
147
|
-
{busy ? "Saving…" : "Save"}
|
|
148
|
-
</Button>
|
|
149
|
-
<Button variant="secondary" onClick={onClose} disabled={busy} className="btn-secondary">
|
|
150
|
-
Cancel
|
|
151
|
-
</Button>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
</>,
|
|
156
|
-
document.body
|
|
157
|
-
);
|
|
158
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {Upload} from './src';
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
ChangeEvent,
|
|
3
|
-
useRef,
|
|
4
|
-
useState,
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect,
|
|
7
|
-
} from 'react';
|
|
8
|
-
import {
|
|
9
|
-
CloudArrowUpIcon,
|
|
10
|
-
Button,
|
|
11
|
-
uploadFiles,
|
|
12
|
-
useFiles,
|
|
13
|
-
currentUsername
|
|
14
|
-
} from './../imports';
|
|
15
|
-
import type { QueuedFile, UploadProps } from './../imports';
|
|
16
|
-
|
|
17
|
-
export default function Upload({ onUploaded }: UploadProps) {
|
|
18
|
-
const [queue, setQueue] = useState<QueuedFile[]>([]);
|
|
19
|
-
const [busy, setBusy] = useState(false);
|
|
20
|
-
const [message, setMessage] = useState<string | null>(null);
|
|
21
|
-
const [drag, setDrag] = useState(false);
|
|
22
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
23
|
-
const [dirs, setDirs] = useState<string[]>([]);
|
|
24
|
-
|
|
25
|
-
// — existing files → directory list —
|
|
26
|
-
const { files, load } = useFiles();
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
const dirSet = new Set<string>();
|
|
30
|
-
files.forEach(f => {
|
|
31
|
-
const parts = f.filepath.split('/');
|
|
32
|
-
if (parts.length > 1) {
|
|
33
|
-
parts.pop();
|
|
34
|
-
dirSet.add(parts.join('/') + '/');
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
setDirs(Array.from(dirSet).sort());
|
|
38
|
-
}, [files]);
|
|
39
|
-
|
|
40
|
-
// — directory selection state —
|
|
41
|
-
const [uploadDir, setUploadDir] = useState<string>('');
|
|
42
|
-
const [creatingNew, setCreatingNew] = useState(false);
|
|
43
|
-
const [newDirName, setNewDirName] = useState('');
|
|
44
|
-
|
|
45
|
-
// — queue logic —
|
|
46
|
-
const enqueue = useCallback((files: QueuedFile[]) => {
|
|
47
|
-
setQueue(prev => {
|
|
48
|
-
const map = new Map(prev.map(q => [`${q.file.name}-${q.file.size}`, q]));
|
|
49
|
-
files.forEach(q => map.set(`${q.file.name}-${q.file.size}`, q));
|
|
50
|
-
return Array.from(map.values());
|
|
51
|
-
});
|
|
52
|
-
}, []);
|
|
53
|
-
|
|
54
|
-
const extractFromDataTransfer = useCallback(
|
|
55
|
-
async (dt: DataTransfer): Promise<QueuedFile[]> => {
|
|
56
|
-
const out: QueuedFile[] = [];
|
|
57
|
-
const walk = async (entry: any, path = "") => {
|
|
58
|
-
if (!entry) return;
|
|
59
|
-
if (entry.isFile) {
|
|
60
|
-
const file: File = await new Promise(res => entry.file(res));
|
|
61
|
-
out.push({ file, relPath: path, progress: 0 });
|
|
62
|
-
} else if (entry.isDirectory) {
|
|
63
|
-
const reader = entry.createReader();
|
|
64
|
-
const entries: any[] = await new Promise(r => reader.readEntries(r));
|
|
65
|
-
await Promise.all(entries.map(e => walk(e, `${path}${entry.name}/`)));
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
await Promise.all(Array.from(dt.items).map(i => walk(i.webkitGetAsEntry())));
|
|
69
|
-
return out;
|
|
70
|
-
},
|
|
71
|
-
[]
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const handleSelect = (e: ChangeEvent<HTMLInputElement>) => {
|
|
75
|
-
const files = Array.from(e.target.files || []);
|
|
76
|
-
const queued: any = files.map(f => ({
|
|
77
|
-
file: f,
|
|
78
|
-
relPath: (f as any).webkitRelativePath.replace(/[^/]*$/, ""),
|
|
79
|
-
progress: 0,
|
|
80
|
-
}));
|
|
81
|
-
enqueue(queued);
|
|
82
|
-
e.target.value = "";
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const handleDrop = async (e: React.DragEvent) => {
|
|
86
|
-
e.preventDefault();
|
|
87
|
-
const files = await extractFromDataTransfer(e.dataTransfer);
|
|
88
|
-
enqueue(files.length ? files : []);
|
|
89
|
-
setDrag(false);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const handleUploadAll = async () => {
|
|
93
|
-
if (!queue.length) {
|
|
94
|
-
setMessage("No files queued.");
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
setBusy(true);
|
|
98
|
-
setMessage(null);
|
|
99
|
-
const targetDir = creatingNew
|
|
100
|
-
? (newDirName.trim().replace(/^\/+|\/+$/g, "") + "/")
|
|
101
|
-
: uploadDir;
|
|
102
|
-
try {
|
|
103
|
-
for (const { file, relPath } of queue) {
|
|
104
|
-
await uploadFiles(file, targetDir + relPath);
|
|
105
|
-
setQueue(cur =>
|
|
106
|
-
cur.map(item =>
|
|
107
|
-
item.file === file ? { ...item, progress: 100 } : item
|
|
108
|
-
)
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
setQueue([]);
|
|
112
|
-
await onUploaded();
|
|
113
|
-
setMessage("Upload complete");
|
|
114
|
-
load();
|
|
115
|
-
} catch {
|
|
116
|
-
setMessage("Upload failed");
|
|
117
|
-
} finally {
|
|
118
|
-
setBusy(false);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// — directory selector handlers —
|
|
123
|
-
const handleDirChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
|
124
|
-
const v = e.target.value;
|
|
125
|
-
if (v === "__new__") {
|
|
126
|
-
setCreatingNew(true);
|
|
127
|
-
setNewDirName("");
|
|
128
|
-
} else {
|
|
129
|
-
setCreatingNew(false);
|
|
130
|
-
setUploadDir(v);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
const acceptNewDir = () => {
|
|
134
|
-
// normalize like before
|
|
135
|
-
const cleanName = newDirName.trim().replace(/^\/+|\/+$/g, '');
|
|
136
|
-
const normalized = `${uploadDir}${cleanName}/`;
|
|
137
|
-
// ① add it to our dirs list if it isn't there already
|
|
138
|
-
setDirs(prev => {
|
|
139
|
-
if (prev.includes(normalized)) return prev;
|
|
140
|
-
return [...prev, normalized].sort();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// ② select it & flip back to the <select>
|
|
144
|
-
setUploadDir(normalized);
|
|
145
|
-
setCreatingNew(false);
|
|
146
|
-
setNewDirName('');
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return (
|
|
150
|
-
<div className="form-container max-w-2xl mx-auto">
|
|
151
|
-
{/* drop area */}
|
|
152
|
-
<div
|
|
153
|
-
className={`flex items-center border-2 border-dashed rounded-lg p-6 bg-white shadow-md space-x-4 transition-shadow duration-150
|
|
154
|
-
${drag ? 'border-indigo-500 bg-indigo-50 shadow-lg' : 'border-gray-300 hover:shadow-lg'}`}
|
|
155
|
-
onClick={() => inputRef.current?.click()}
|
|
156
|
-
onDragEnter={e => { e.preventDefault(); setDrag(true); }}
|
|
157
|
-
onDragOver={e => e.preventDefault()}
|
|
158
|
-
onDragLeave={() => setDrag(false)}
|
|
159
|
-
onDrop={handleDrop}
|
|
160
|
-
role="region"
|
|
161
|
-
aria-label="File upload area"
|
|
162
|
-
>
|
|
163
|
-
<CloudArrowUpIcon
|
|
164
|
-
style={{ width: 300, height: 300 }}
|
|
165
|
-
className="text-gray-500 mb-3"
|
|
166
|
-
aria-hidden="true"
|
|
167
|
-
/>
|
|
168
|
-
<div className="flex-1">
|
|
169
|
-
<p className="text-base font-semibold text-gray-700">
|
|
170
|
-
Drag & drop files or folders here
|
|
171
|
-
</p>
|
|
172
|
-
{queue.length > 0 && (
|
|
173
|
-
<p className="mt-1 text-sm text-gray-600">
|
|
174
|
-
{queue.length} item{queue.length > 1 && 's'} queued
|
|
175
|
-
</p>
|
|
176
|
-
)}
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
|
|
180
|
-
{/* hidden file input */}
|
|
181
|
-
<input
|
|
182
|
-
ref={inputRef}
|
|
183
|
-
type="file"
|
|
184
|
-
multiple
|
|
185
|
-
className="hidden"
|
|
186
|
-
{...({ webkitdirectory: true, directory: '' } as any)}
|
|
187
|
-
onChange={handleSelect}
|
|
188
|
-
/>
|
|
189
|
-
|
|
190
|
-
{/* bottom controls */}
|
|
191
|
-
<div className="flex items-center justify-between mt-4">
|
|
192
|
-
{/* directory selector / new dir input */}
|
|
193
|
-
<div className="flex-1 mr-4">
|
|
194
|
-
{!creatingNew ? (
|
|
195
|
-
<select
|
|
196
|
-
value={uploadDir}
|
|
197
|
-
onChange={handleDirChange}
|
|
198
|
-
className="form-select w-full"
|
|
199
|
-
>
|
|
200
|
-
{dirs.map(d => (
|
|
201
|
-
<option key={d} value={d}>{d}</option>
|
|
202
|
-
))}
|
|
203
|
-
<option value="__new__">+ Create new directory…</option>
|
|
204
|
-
</select>
|
|
205
|
-
) : (
|
|
206
|
-
<div className="flex">
|
|
207
|
-
<input
|
|
208
|
-
type="text"
|
|
209
|
-
value={newDirName}
|
|
210
|
-
placeholder="new-folder-name"
|
|
211
|
-
onChange={e => setNewDirName(e.target.value)}
|
|
212
|
-
onBlur={acceptNewDir}
|
|
213
|
-
onKeyDown={e => e.key === 'Enter' && acceptNewDir()}
|
|
214
|
-
className="form-input flex-1"
|
|
215
|
-
/>
|
|
216
|
-
<Button onClick={acceptNewDir} className="ml-2">
|
|
217
|
-
OK
|
|
218
|
-
</Button>
|
|
219
|
-
</div>
|
|
220
|
-
)}
|
|
221
|
-
</div>
|
|
222
|
-
|
|
223
|
-
{/* upload button */}
|
|
224
|
-
<Button
|
|
225
|
-
color="blue"
|
|
226
|
-
variant="primary"
|
|
227
|
-
onClick={handleUploadAll}
|
|
228
|
-
disabled={busy || !queue.length}
|
|
229
|
-
>
|
|
230
|
-
{busy ? 'Uploading…' : `Upload ${queue.length}`}
|
|
231
|
-
</Button>
|
|
232
|
-
</div>
|
|
233
|
-
|
|
234
|
-
{message && (
|
|
235
|
-
<p
|
|
236
|
-
className={`text-center text-sm ${message.includes('failed') ? 'text-red-600' : 'text-gray-600'
|
|
237
|
-
}`}
|
|
238
|
-
role="alert"
|
|
239
|
-
>
|
|
240
|
-
{message}
|
|
241
|
-
</p>
|
|
242
|
-
)}
|
|
243
|
-
|
|
244
|
-
{/* queued list */}
|
|
245
|
-
{queue.length > 0 && (
|
|
246
|
-
<div className="wm-container mt-4">
|
|
247
|
-
<h3 className="mb-2 text-sm font-semibold text-gray-700">Queued Files</h3>
|
|
248
|
-
<ul className="max-h-64 space-y-4 overflow-y-auto">
|
|
249
|
-
{queue.map(({ file, relPath, progress }) => (
|
|
250
|
-
<li key={`${file.name}-${file.size}`} className="space-y-1">
|
|
251
|
-
<div className="flex justify-between items-center">
|
|
252
|
-
<span className="truncate text-sm text-gray-800">
|
|
253
|
-
{relPath}{file.name}
|
|
254
|
-
</span>
|
|
255
|
-
<span className="text-xs text-gray-500">{progress}%</span>
|
|
256
|
-
</div>
|
|
257
|
-
<div className="w-full bg-gray-200 rounded-full h-2 overflow-hidden">
|
|
258
|
-
<div className="bg-indigo-600 h-2" style={{ width: `${progress}%` }} />
|
|
259
|
-
</div>
|
|
260
|
-
</li>
|
|
261
|
-
))}
|
|
262
|
-
</ul>
|
|
263
|
-
</div>
|
|
264
|
-
)}
|
|
265
|
-
</div>
|
|
266
|
-
);
|
|
267
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export type {QueuedFile, FileItem,FileTableProps,UploadProps,ShareModalProps,FileRowProps } from './../imports';
|
|
2
|
-
export {
|
|
3
|
-
CloudArrowUpIcon,
|
|
4
|
-
currentUsername,
|
|
5
|
-
fetchSharePatch,
|
|
6
|
-
Button,
|
|
7
|
-
Checkbox,
|
|
8
|
-
Input,
|
|
9
|
-
Spinner,
|
|
10
|
-
useEffect,
|
|
11
|
-
useRef,
|
|
12
|
-
useState,
|
|
13
|
-
useCallback,
|
|
14
|
-
ClipboardIcon,
|
|
15
|
-
createPortal,
|
|
16
|
-
secureFetchIt,
|
|
17
|
-
|
|
18
|
-
} from './../imports';
|
|
19
|
-
export {useFiles} from './../hooks'
|
|
20
|
-
export { downloadFile,uploadFiles} from './../file_utils'
|
package/src/UI/index.tsx
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
export type String = string | undefined | null;
|
|
4
|
-
export type Astring = any[] | string | undefined | null;
|
|
5
|
-
export type Trailing = React.ReactNode
|
|
6
|
-
export type ImportElem = {
|
|
7
|
-
reaxlEle:React.InputHTMLAttributes<HTMLInputElement>;
|
|
8
|
-
label?: String;
|
|
9
|
-
trailing?:Trailing;
|
|
10
|
-
className?: String;
|
|
11
|
-
classNames?:Astring;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Utility to convert input to array
|
|
15
|
-
function ensure_list(obj: Astring | null | undefined): string[] {
|
|
16
|
-
if (Array.isArray(obj)) return obj.filter(Boolean);
|
|
17
|
-
if (typeof obj === 'string') return obj.split(' ').filter(Boolean);
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Get list and length safely
|
|
22
|
-
function getListAndLen(obj: Astring | null | undefined): { return_obj: string[]; ob_len: number } {
|
|
23
|
-
const return_obj = ensure_list(obj);
|
|
24
|
-
const ob_len = return_obj.length;
|
|
25
|
-
return { return_obj, ob_len };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Combine class names with defaults
|
|
29
|
-
function combineClassNames(classNames: Astring = [], defaultClasses: Astring = ['form-group', 'form-label', 'flex', 'gap-2']): string[] {
|
|
30
|
-
const { return_obj: inputClasses } = getListAndLen(classNames);
|
|
31
|
-
const { return_obj: defaultClassList } = getListAndLen(defaultClasses);
|
|
32
|
-
|
|
33
|
-
// Combine and remove duplicates
|
|
34
|
-
const combined = [...new Set([...defaultClassList, ...inputClasses])];
|
|
35
|
-
|
|
36
|
-
console.log(`Combined classes (length: ${combined.length}): ${combined.join(' ')}`);
|
|
37
|
-
return combined;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function Button({
|
|
41
|
-
children,
|
|
42
|
-
color = 'gray',
|
|
43
|
-
variant = 'default',
|
|
44
|
-
className = '',
|
|
45
|
-
...rest
|
|
46
|
-
}: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
47
|
-
color?: 'gray' | 'green' | 'blue';
|
|
48
|
-
variant?: 'default' | 'icon' | 'primary' | 'secondary';
|
|
49
|
-
className?: string;
|
|
50
|
-
}) {
|
|
51
|
-
const variantClasses = {
|
|
52
|
-
default: 'btn',
|
|
53
|
-
icon: 'btn-icon',
|
|
54
|
-
primary: 'btn-primary',
|
|
55
|
-
secondary: 'btn-secondary',
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const colorClasses = {
|
|
59
|
-
gray: '',
|
|
60
|
-
green: variant === 'primary' ? 'btn-success' : 'btn-secondary',
|
|
61
|
-
blue: variant === 'primary' ? 'btn-primary' : 'btn-secondary',
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const classes = combineClassNames([variantClasses[variant], colorClasses[color], className]);
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<button className={classes.join(' ')} {...rest}>
|
|
68
|
-
{children}
|
|
69
|
-
</button>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function Checkbox({
|
|
74
|
-
label,
|
|
75
|
-
className = '',
|
|
76
|
-
classNames = [],
|
|
77
|
-
...rest
|
|
78
|
-
}: ImportElem) {
|
|
79
|
-
const classes = combineClassNames(classNames, ['checkbox', 'wm-checkbox']);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<label className={classes.join(' ')}>
|
|
83
|
-
<input type="checkbox" className="wm-checkbox" {...rest} />
|
|
84
|
-
{label && <span>{label}</span>}
|
|
85
|
-
</label>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function Input({
|
|
90
|
-
label,
|
|
91
|
-
trailing,
|
|
92
|
-
className = '',
|
|
93
|
-
classNames = [],
|
|
94
|
-
...rest
|
|
95
|
-
}: ImportElem) {
|
|
96
|
-
const classes = combineClassNames(classNames, ['form-group', 'flex', 'gap-2']);
|
|
97
|
-
const inputClasses = combineClassNames(className, ['form-input']);
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<label className={classes.join(' ')}>
|
|
101
|
-
{label && <span className="form-label">{label}</span>}
|
|
102
|
-
<div className="flex gap-2">
|
|
103
|
-
<input className={inputClasses.join(' ')} {...rest} />
|
|
104
|
-
{trailing}
|
|
105
|
-
</div>
|
|
106
|
-
</label>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function Spinner() {
|
|
111
|
-
const classes = combineClassNames('animate-pulse');
|
|
112
|
-
return <p className={classes.join(' ')}>Loading…</p>;
|
|
113
|
-
}
|
package/src/custom.d.ts
DELETED
package/src/file_utils/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { secureFetchIt,requireToken,alertit } from "./../imports";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import {removeFile} from './delete_select'
|
|
3
|
-
import {alertit} from './../imports'
|
|
4
|
-
/** Given a checkbox inside a table-row → download that row’s file. */
|
|
5
|
-
export async function removeRow(cb: HTMLInputElement): Promise<void> {
|
|
6
|
-
const row = cb.closest("tr") as HTMLTableRowElement | null;
|
|
7
|
-
alertit(row)
|
|
8
|
-
if (row && row?.id) await removeFile(row);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import {requireToken,secureFetchIt} from './../imports';
|
|
2
|
-
|
|
3
|
-
export async function removeFile(item: any): Promise<void> {
|
|
4
|
-
const resp = await secureFetchIt( "remove", item, "POST", null, false,false,true) as any;
|
|
5
|
-
if (!resp || resp === false || resp?.result === false) {
|
|
6
|
-
throw new Error(`could not delete data: “${item.filename}”`);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import {removeFile} from './delete_select';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/** Bulk download: pass a NodeList or array of checkboxes. */
|
|
5
|
-
export async function removeSelected(checkboxes: Iterable<HTMLInputElement>): Promise<void> {
|
|
6
|
-
const list = Array.from(checkboxes);
|
|
7
|
-
if (!list.length) {
|
|
8
|
-
alert("No files selected.");
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
for (const cb of list) {
|
|
12
|
-
alert(cb);
|
|
13
|
-
await removeFile(cb);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -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
|
-
}
|