@putkoff/abstract-securefiles 0.0.25 → 0.0.27

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.
Files changed (177) hide show
  1. package/css.d.ts +0 -0
  2. package/dist/index.cjs +3 -933
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1 -1
  5. package/dist/index.d.ts +1 -8
  6. package/dist/index.js +5 -884
  7. package/dist/index.js.map +1 -1
  8. package/dist/{App/SecureFiles.d.ts → secure_files.d.ts} +1 -1
  9. package/index.ts +0 -0
  10. package/package.json +4 -4
  11. package/postcss.config.cjs +0 -0
  12. package/rollup.config.mjs +0 -0
  13. package/src/index.ts +1 -8
  14. package/src/{App/SecureFiles.tsx → secure_files.tsx} +4 -3
  15. package/tailwind.config.cjs +0 -0
  16. package/tsconfig.json +0 -0
  17. package/dist/App/index.d.ts +0 -1
  18. package/dist/FileHandlers/FileRow/imports.d.ts +0 -2
  19. package/dist/FileHandlers/FileRow/index.d.ts +0 -1
  20. package/dist/FileHandlers/FileRow/src/index.d.ts +0 -1
  21. package/dist/FileHandlers/FileRow/src/row_utils.d.ts +0 -2
  22. package/dist/FileHandlers/FileTable/imports.d.ts +0 -4
  23. package/dist/FileHandlers/FileTable/index.d.ts +0 -1
  24. package/dist/FileHandlers/FileTable/src/index.d.ts +0 -1
  25. package/dist/FileHandlers/FileTable/src/table_utils.d.ts +0 -2
  26. package/dist/FileHandlers/ShareModal/imports.d.ts +0 -2
  27. package/dist/FileHandlers/ShareModal/index.d.ts +0 -1
  28. package/dist/FileHandlers/ShareModal/src/index.d.ts +0 -1
  29. package/dist/FileHandlers/ShareModal/src/share_utils.d.ts +0 -2
  30. package/dist/FileHandlers/Upload/imports.d.ts +0 -2
  31. package/dist/FileHandlers/Upload/index.d.ts +0 -1
  32. package/dist/FileHandlers/Upload/src/index.d.ts +0 -2
  33. package/dist/FileHandlers/Upload/src/upload_utils.d.ts +0 -2
  34. package/dist/FileHandlers/imports.d.ts +0 -4
  35. package/dist/FileHandlers/index.d.ts +0 -4
  36. package/dist/UI/index.d.ts +0 -19
  37. package/dist/file_utils/imports.d.ts +0 -2
  38. package/dist/file_utils/index.d.ts +0 -1
  39. package/dist/file_utils/src/delete_utils/imports.d.ts +0 -1
  40. package/dist/file_utils/src/delete_utils/index.d.ts +0 -1
  41. package/dist/file_utils/src/delete_utils/src/delete_row.d.ts +0 -2
  42. package/dist/file_utils/src/delete_utils/src/delete_select.d.ts +0 -1
  43. package/dist/file_utils/src/delete_utils/src/delete_selected.d.ts +0 -2
  44. package/dist/file_utils/src/delete_utils/src/index.d.ts +0 -3
  45. package/dist/file_utils/src/download_utils/imports.d.ts +0 -2
  46. package/dist/file_utils/src/download_utils/index.d.ts +0 -1
  47. package/dist/file_utils/src/download_utils/src/direct_download.d.ts +0 -3
  48. package/dist/file_utils/src/download_utils/src/download_file.d.ts +0 -2
  49. package/dist/file_utils/src/download_utils/src/download_select.d.ts +0 -2
  50. package/dist/file_utils/src/download_utils/src/index.d.ts +0 -5
  51. package/dist/file_utils/src/download_utils/src/target_downloads.d.ts +0 -4
  52. package/dist/file_utils/src/download_utils/src/trigger_download.d.ts +0 -2
  53. package/dist/file_utils/src/imports.d.ts +0 -2
  54. package/dist/file_utils/src/index.d.ts +0 -6
  55. package/dist/file_utils/src/list_utils/imports.d.ts +0 -2
  56. package/dist/file_utils/src/list_utils/index.d.ts +0 -1
  57. package/dist/file_utils/src/list_utils/src/index.d.ts +0 -1
  58. package/dist/file_utils/src/list_utils/src/list_utils.d.ts +0 -2
  59. package/dist/file_utils/src/select_utils/index.d.ts +0 -1
  60. package/dist/file_utils/src/select_utils/src/index.d.ts +0 -3
  61. package/dist/file_utils/src/select_utils/src/init_select_all.d.ts +0 -2
  62. package/dist/file_utils/src/select_utils/src/sync_header_checkbox.d.ts +0 -5
  63. package/dist/file_utils/src/select_utils/src/toggle_checkboxes.d.ts +0 -2
  64. package/dist/file_utils/src/share_utils/imports.d.ts +0 -2
  65. package/dist/file_utils/src/share_utils/index.d.ts +0 -1
  66. package/dist/file_utils/src/share_utils/src/index.d.ts +0 -1
  67. package/dist/file_utils/src/share_utils/src/share_utils.d.ts +0 -7
  68. package/dist/file_utils/src/upload_utils/imports.d.ts +0 -1
  69. package/dist/file_utils/src/upload_utils/index.d.ts +0 -1
  70. package/dist/file_utils/src/upload_utils/src/index.d.ts +0 -3
  71. package/dist/file_utils/src/upload_utils/src/patch_file_settings.d.ts +0 -2
  72. package/dist/file_utils/src/upload_utils/src/upload_file.d.ts +0 -2
  73. package/dist/file_utils/src/upload_utils/src/upload_files.d.ts +0 -5
  74. package/dist/hooks/imports.d.ts +0 -3
  75. package/dist/hooks/index.d.ts +0 -1
  76. package/dist/hooks/useFiles/imports.d.ts +0 -2
  77. package/dist/hooks/useFiles/index.d.ts +0 -1
  78. package/dist/hooks/useFiles/src/deleteFile.d.ts +0 -6
  79. package/dist/hooks/useFiles/src/index.d.ts +0 -6
  80. package/dist/hooks/useFiles/src/load.d.ts +0 -6
  81. package/dist/hooks/useFiles/src/patchShareSettings.d.ts +0 -7
  82. package/dist/hooks/useFiles/src/toggleShare.d.ts +0 -6
  83. package/dist/hooks/useFiles/src/useFiles.d.ts +0 -13
  84. package/dist/hooks/useFiles/src/useSaveShareSettings.d.ts +0 -3
  85. package/dist/imports.d.ts +0 -5
  86. package/dist/styles/index.d.ts +0 -1
  87. package/dist/types/index.d.ts +0 -1
  88. package/dist/types/src/index.d.ts +0 -1
  89. package/dist/types/src/types.d.ts +0 -75
  90. package/src/App/index.ts +0 -1
  91. package/src/FileHandlers/FileRow/imports.ts +0 -2
  92. package/src/FileHandlers/FileRow/index.ts +0 -1
  93. package/src/FileHandlers/FileRow/src/index.ts +0 -1
  94. package/src/FileHandlers/FileRow/src/row_utils.tsx +0 -143
  95. package/src/FileHandlers/FileTable/imports.ts +0 -16
  96. package/src/FileHandlers/FileTable/index.ts +0 -1
  97. package/src/FileHandlers/FileTable/src/index.ts +0 -1
  98. package/src/FileHandlers/FileTable/src/table_utils.tsx +0 -251
  99. package/src/FileHandlers/ShareModal/imports.ts +0 -2
  100. package/src/FileHandlers/ShareModal/index.ts +0 -1
  101. package/src/FileHandlers/ShareModal/src/index.ts +0 -1
  102. package/src/FileHandlers/ShareModal/src/share_utils.tsx +0 -158
  103. package/src/FileHandlers/Upload/imports.ts +0 -3
  104. package/src/FileHandlers/Upload/index.ts +0 -1
  105. package/src/FileHandlers/Upload/src/index.ts +0 -2
  106. package/src/FileHandlers/Upload/src/upload_utils.tsx +0 -267
  107. package/src/FileHandlers/imports.ts +0 -20
  108. package/src/FileHandlers/index.ts +0 -4
  109. package/src/UI/index.tsx +0 -113
  110. package/src/custom.d.ts +0 -7
  111. package/src/file_utils/imports.ts +0 -2
  112. package/src/file_utils/index.ts +0 -1
  113. package/src/file_utils/src/delete_utils/imports.ts +0 -1
  114. package/src/file_utils/src/delete_utils/index.ts +0 -1
  115. package/src/file_utils/src/delete_utils/src/delete_row.ts +0 -11
  116. package/src/file_utils/src/delete_utils/src/delete_select.ts +0 -9
  117. package/src/file_utils/src/delete_utils/src/delete_selected.ts +0 -15
  118. package/src/file_utils/src/delete_utils/src/index.ts +0 -3
  119. package/src/file_utils/src/download_utils/imports.ts +0 -3
  120. package/src/file_utils/src/download_utils/index.ts +0 -1
  121. package/src/file_utils/src/download_utils/src/direct_download.ts +0 -22
  122. package/src/file_utils/src/download_utils/src/download_file.ts +0 -24
  123. package/src/file_utils/src/download_utils/src/download_select.ts +0 -20
  124. package/src/file_utils/src/download_utils/src/index.ts +0 -5
  125. package/src/file_utils/src/download_utils/src/target_downloads.ts +0 -21
  126. package/src/file_utils/src/download_utils/src/trigger_download.ts +0 -14
  127. package/src/file_utils/src/imports.ts +0 -3
  128. package/src/file_utils/src/index.ts +0 -6
  129. package/src/file_utils/src/list_utils/imports.ts +0 -2
  130. package/src/file_utils/src/list_utils/index.ts +0 -1
  131. package/src/file_utils/src/list_utils/src/index.ts +0 -1
  132. package/src/file_utils/src/list_utils/src/list_utils.ts +0 -24
  133. package/src/file_utils/src/select_utils/index.ts +0 -1
  134. package/src/file_utils/src/select_utils/src/index.ts +0 -3
  135. package/src/file_utils/src/select_utils/src/init_select_all.ts +0 -37
  136. package/src/file_utils/src/select_utils/src/sync_header_checkbox.ts +0 -18
  137. package/src/file_utils/src/select_utils/src/toggle_checkboxes.ts +0 -11
  138. package/src/file_utils/src/share_utils/imports.ts +0 -2
  139. package/src/file_utils/src/share_utils/index.ts +0 -1
  140. package/src/file_utils/src/share_utils/src/index.ts +0 -1
  141. package/src/file_utils/src/share_utils/src/share_utils.ts +0 -29
  142. package/src/file_utils/src/upload_utils/imports.ts +0 -1
  143. package/src/file_utils/src/upload_utils/index.ts +0 -1
  144. package/src/file_utils/src/upload_utils/src/index.ts +0 -3
  145. package/src/file_utils/src/upload_utils/src/patch_file_settings.ts +0 -18
  146. package/src/file_utils/src/upload_utils/src/upload_file.ts +0 -28
  147. package/src/file_utils/src/upload_utils/src/upload_files.ts +0 -34
  148. package/src/global.d.ts +0 -1
  149. package/src/hooks/imports.ts +0 -3
  150. package/src/hooks/index.ts +0 -1
  151. package/src/hooks/useFiles/imports.ts +0 -3
  152. package/src/hooks/useFiles/index.ts +0 -1
  153. package/src/hooks/useFiles/src/deleteFile.ts +0 -22
  154. package/src/hooks/useFiles/src/index.ts +0 -6
  155. package/src/hooks/useFiles/src/load.ts +0 -52
  156. package/src/hooks/useFiles/src/logs/routes_bp.log +0 -0
  157. package/src/hooks/useFiles/src/patchShareSettings.ts +0 -37
  158. package/src/hooks/useFiles/src/toggleShare.ts +0 -28
  159. package/src/hooks/useFiles/src/useFiles.ts +0 -35
  160. package/src/hooks/useFiles/src/useSaveShareSettings.ts +0 -25
  161. package/src/imports.ts +0 -20
  162. package/src/styles/SecureFiles/logs/clipit_logs.log +0 -0
  163. package/src/styles/SecureFiles/logs/routes_bp.log +0 -0
  164. package/src/styles/SecureFilesStyles.module.css +0 -287
  165. package/src/styles/index.ts +0 -1
  166. package/src/types/index.ts +0 -1
  167. package/src/types/src/index.ts +0 -1
  168. package/src/types/src/types.ts +0 -88
  169. package/test/package-lock.json +0 -979
  170. package/test/package.json +0 -23
  171. package/test/test_entry.ts +0 -8
  172. package/test/tsconfig.json +0 -12
  173. /package/{src/hooks/useFiles/src/logs/clipit_logs.log → package.tmp.json} +0 -0
  174. /package/src/styles/{SecureFiles/App.css → App.css} +0 -0
  175. /package/src/styles/{SecureFiles/index.css → index.css} +0 -0
  176. /package/src/styles/{SecureFiles/tailwind.css → tailwind.css} +0 -0
  177. /package/src/styles/{SecureFiles/window-manager.css → window-manager.css} +0 -0
@@ -1,5 +0,0 @@
1
- interface UploadResponse {
2
- filepath: string;
3
- }
4
- export declare function uploadFiles(file: File, subdir?: string): Promise<UploadResponse>;
5
- export {};
@@ -1,3 +0,0 @@
1
- export type { FileItem, ApiRow } from './../imports';
2
- export { secureFetchIt, fetchSharePatch, alertit, useCallback, isLoggedIn } from './../imports';
3
- export { toggleShare, removeFile, listFiles, downloadFile } from './../file_utils';
@@ -1 +0,0 @@
1
- export * from './useFiles';
@@ -1,2 +0,0 @@
1
- export type { FileItem, ApiRow } from './../imports';
2
- export { secureFetchIt, fetchSharePatch, alertit, toggleShare, removeFile, listFiles, useCallback, downloadFile, isLoggedIn } from './../imports';
@@ -1 +0,0 @@
1
- export * from './src';
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { FileItem } from './../imports';
3
- /**
4
- * Custom hook to toggle share settings on a file item
5
- */
6
- export declare const useDeleteFile: (setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>) => (file: FileItem) => Promise<void>;
@@ -1,6 +0,0 @@
1
- export * from './load';
2
- export * from './toggleShare';
3
- export * from './patchShareSettings';
4
- export * from './useFiles';
5
- export * from './deleteFile';
6
- export * from './useSaveShareSettings';
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { FileItem } from './../imports';
3
- /**
4
- * Custom hook that returns a memoized loadFiles callback
5
- */
6
- export declare const useLoadFiles: (setLoading: React.Dispatch<React.SetStateAction<boolean>>, setError: React.Dispatch<React.SetStateAction<Error | null>>, setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>) => () => Promise<void>;
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- import { FileItem } from './../imports';
3
- /**
4
- * Custom hook to toggle share settings on a file item
5
- */
6
- export declare const usePatchShareSettings: (setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>) => (file: any) => Promise<void>;
7
- export default usePatchShareSettings;
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { FileItem } from './../imports';
3
- /**
4
- * Custom hook to toggle share settings on a file item
5
- */
6
- export declare const useToggleShare: (setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>) => (file: FileItem) => Promise<void>;
@@ -1,13 +0,0 @@
1
- import type { FileItem } from './../imports';
2
- export declare function useFiles(): {
3
- files: FileItem[];
4
- loading: boolean;
5
- error: Error | null;
6
- load: () => Promise<void>;
7
- toggleShare: (file: FileItem) => Promise<void>;
8
- patchShareSettings: (updated: any) => Promise<void>;
9
- deleteFile: (file: FileItem) => Promise<void>;
10
- setFiles: import("react").Dispatch<import("react").SetStateAction<FileItem[]>>;
11
- setLoading: import("react").Dispatch<import("react").SetStateAction<boolean>>;
12
- setError: import("react").Dispatch<import("react").SetStateAction<Error | null>>;
13
- };
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- import { FileItem } from './../imports';
3
- export declare const useSaveShareSettings: (setFiles: React.Dispatch<React.SetStateAction<FileItem[]>>) => (updated: any) => Promise<void>;
package/dist/imports.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export { createPortal } from "react-dom";
2
- export { ClipboardIcon, CloudArrowUpIcon } from "@heroicons/react/24/outline";
3
- export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps, ApiRow, EnhancedInputProps } from './types';
4
- export { currentUsername, alertit, Button, Checkbox, Input, Spinner, useEffect, useRef, useState, requireToken, useCallback, isLoggedIn, fetchIt, stripPrefixes, make_path } from "@putkoff/abstract-utilities";
5
- export { secureFetchIt, fetchSharePatch } from "@putkoff/abstract-apis";
@@ -1 +0,0 @@
1
- export * from './SecureFiles/index.css';
@@ -1 +0,0 @@
1
- export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps, ApiRow, EnhancedInputProps } from './src/types';
@@ -1 +0,0 @@
1
- export type { QueuedFile, FileItem, FileTableProps, UploadProps, ShareModalProps, FileRowProps, ApiRow, EnhancedInputProps } from './types';
@@ -1,75 +0,0 @@
1
- export interface FileItem {
2
- id: number | string;
3
- filename: string;
4
- uploader_id: string;
5
- filepath: string;
6
- created_at: string;
7
- download_count: number;
8
- download_limit: number | null;
9
- shareable: boolean;
10
- needsPassword: boolean;
11
- share_password: string | null;
12
- password_str: string | null;
13
- }
14
- export interface ApiRow {
15
- id: number | string;
16
- filename: string;
17
- uploader_id: string;
18
- filepath: string;
19
- created_at: string;
20
- download_count: number;
21
- download_limit: number | null;
22
- shareable: boolean;
23
- needsPassword: boolean;
24
- share_password: string;
25
- password_str: string | null;
26
- }
27
- export interface FileListResponse {
28
- files?: ApiRow[];
29
- }
30
- export interface FileTableProps {
31
- files: FileItem[];
32
- loading: boolean;
33
- error: Error | null;
34
- onDownload(id: any): Promise<void>;
35
- onToggleShare(id: any): Promise<void>;
36
- onPatchShare(id: any): Promise<void>;
37
- onDelete(id: any): Promise<void>;
38
- }
39
- export interface ShareModalProps {
40
- file: FileItem | null;
41
- onClose(): void;
42
- onSave(patch: Partial<FileItem>): Promise<void>;
43
- }
44
- export interface UploadProps {
45
- /** Called *after* a successful upload */
46
- onUploaded: () => Promise<void>;
47
- }
48
- export interface FileRowProps {
49
- file: FileItem;
50
- onDownload: () => Promise<void>;
51
- onSettings: () => void;
52
- onToggleShare: () => Promise<void>;
53
- onDelete: () => any;
54
- }
55
- export interface QueuedFile {
56
- file: File;
57
- relPath: string;
58
- progress: number;
59
- }
60
- export interface InputProps {
61
- label?: any;
62
- type?: any;
63
- value?: any;
64
- onChange?: any;
65
- disabled?: any;
66
- placeholder?: any;
67
- error?: string;
68
- }
69
- export interface FileInputExtra {
70
- directory?: boolean;
71
- multiple?: boolean;
72
- accept?: string;
73
- }
74
- /** keep other InputProps fields … */
75
- export type EnhancedInputProps = InputProps & FileInputExtra;
package/src/App/index.ts DELETED
@@ -1 +0,0 @@
1
- export { default as SecureFiles } from './SecureFiles'
@@ -1,2 +0,0 @@
1
- export type { FileRowProps } from './../imports';
2
- export { useState, Button, currentUsername } from './../imports';
@@ -1 +0,0 @@
1
- export {FileRow} from './src';
@@ -1 +0,0 @@
1
- export {default as FileRow} from './row_utils'
@@ -1,143 +0,0 @@
1
- import type { FileRowProps } from './../imports';
2
- import { useState, Button, currentUsername } from './../imports';
3
-
4
- export default function FileRow({
5
- file,
6
- onDownload,
7
- onSettings,
8
- onToggleShare,
9
- onDelete,
10
- }: FileRowProps) {
11
- const isOwner =
12
- file.uploader_id?.toLowerCase() === (currentUsername() ?? '').toLowerCase();
13
- const downloadAllowed = isOwner || file.shareable;
14
- const [isDownloading, setIsDownloading] = useState(false);
15
- const [isTogglingShare, setIsTogglingShare] = useState(false);
16
- const [isDeleting, setIsDeleting] = useState(false);
17
-
18
- // Mimic WindowManagerApp's unsaved heuristic
19
- const looksUnsaved =
20
- file.filename.toLowerCase().startsWith('untitled') ||
21
- file.filename.includes('*');
22
-
23
- const handleDownload = async () => {
24
- setIsDownloading(true);
25
- try {
26
- await onDownload();
27
- } finally {
28
- setIsDownloading(false);
29
- }
30
- };
31
-
32
- const handleToggleShare = async () => {
33
- setIsTogglingShare(true);
34
- try {
35
- await onToggleShare();
36
- } finally {
37
- setIsTogglingShare(false);
38
- }
39
- };
40
-
41
- const handleDeleteFile = async () => {
42
- setIsDeleting(true);
43
- try {
44
- await onDelete();
45
- } finally {
46
- setIsDeleting(false);
47
- }
48
- };
49
-
50
- return (
51
- <tr className="wm-row transition-colors duration-75">
52
- {/* Select checkbox */}
53
- <td className="wm-cell w-12 align-middle">
54
- <input
55
- type="checkbox"
56
- className="wm-checkbox"
57
- aria-label={`Select ${file.filename}`}
58
- />
59
- </td>
60
-
61
- {/* Filename */}
62
- <td className={`wm-cell ${looksUnsaved ? 'unsaved' : ''}`}>
63
- {file.filename}
64
- </td>
65
-
66
- {/* Download button or lock */}
67
- <td className="wm-cell w-12 align-middle">
68
- {downloadAllowed ? (
69
- <Button
70
- color="blue"
71
- variant="secondary"
72
- onClick={handleDownload}
73
- disabled={isDownloading}
74
- aria-label={`Download ${file.filename}`}
75
- className="wm-btn-link"
76
- >
77
- {isDownloading ? 'Downloading...' : 'Download'}
78
- </Button>
79
- ) : (
80
- <span
81
- className="text-gray-500 text-lg"
82
- aria-label="Download restricted"
83
- >
84
- 🔒
85
- </span>
86
- )}
87
- </td>
88
-
89
- {/* Settings cog */}
90
- <td className="wm-cell w-12 align-middle">
91
- {isOwner && (
92
- <Button
93
- color="gray"
94
- variant="icon"
95
- onClick={() => {
96
- console.log('⚙︎ clicked', file.id);
97
- onSettings();
98
- }}
99
- aria-label="Open share settings"
100
- className="wm-btn-icon text-lg"
101
- >
102
- ⚙️
103
- </Button>
104
- )}
105
- </td>
106
-
107
- {/* Share toggle */}
108
- <td className="wm-cell w-12 align-middle">
109
- {isOwner && (
110
- <Button
111
- color={file.shareable ? 'blue' : 'gray'}
112
- variant={file.shareable ? 'primary' : 'secondary'}
113
- onClick={handleToggleShare}
114
- disabled={isTogglingShare}
115
- className="btn"
116
- >
117
- {isTogglingShare
118
- ? 'Toggling...'
119
- : file.shareable
120
- ? 'Sharing'
121
- : 'Share'}
122
- </Button>
123
- )}
124
- </td>
125
-
126
- {/* Delete button */}
127
- <td className="wm-cell w-12 align-middle">
128
- {isOwner && (
129
- <Button
130
- color="gray"
131
- variant="icon"
132
- onClick={handleDeleteFile}
133
- disabled={isDeleting}
134
- className="wm-btn-icon text-lg"
135
- >
136
- 🗑
137
- </Button>
138
- )}
139
- </td>
140
- <td className="wm-cell">{file.download_count} / {file.download_limit ?? "∞"}</td>
141
- </tr>
142
- );
143
- }
@@ -1,16 +0,0 @@
1
- export {FileRow} from './../FileRow';
2
- export {ShareModal} from './../ShareModal';
3
- export type {
4
- FileItem ,
5
- FileTableProps
6
- } from './../imports';
7
- export {
8
- useState ,
9
- useFiles ,
10
- downloadFile ,
11
- Spinner ,
12
- fetchSharePatch,
13
- Input,
14
- currentUsername,
15
- Button
16
- } from './../imports';
@@ -1 +0,0 @@
1
- export {FileTable} from './src'
@@ -1 +0,0 @@
1
- export {default as FileTable} from './table_utils'
@@ -1,251 +0,0 @@
1
- import type { FileItem, FileTableProps } from './../imports';
2
- import React, { useState, useMemo, ChangeEvent } from 'react';
3
- import {
4
- useFiles,
5
- downloadFile,
6
- Spinner,
7
- ShareModal,
8
- Input,
9
- Button,
10
- currentUsername
11
- } from './../imports';
12
- import { downloadSelected } from './../../../file_utils';
13
-
14
- // Tree node type
15
- interface FileNode {
16
- name: string;
17
- path: string;
18
- children: Map<string, FileNode>;
19
- files: FileItem[];
20
- }
21
-
22
- // Build a directory tree from a flat file list
23
- function buildTree(files: FileItem[]): FileNode {
24
- const root: FileNode = { name: '', path: '', children: new Map(), files: [] };
25
- files.forEach(file => {
26
- const parts = file.filepath.split('/');
27
- let node = root;
28
- parts.slice(0, -1).forEach((seg, idx) => {
29
- const subPath = parts.slice(0, idx + 1).join('/');
30
- if (!node.children.has(seg)) {
31
- node.children.set(seg, { name: seg, path: subPath, children: new Map(), files: [] });
32
- }
33
- node = node.children.get(seg)!;
34
- });
35
- node.files.push(file);
36
- });
37
- return root;
38
- }
39
-
40
- // Collect all file IDs under a node (recursive)
41
- function collectNodeIds(node: FileNode): Array<number | string> {
42
- let ids: Array<number | string> = [];
43
- node.files.forEach(f => ids.push(f.id));
44
- node.children.forEach(child => {
45
- ids = ids.concat(collectNodeIds(child));
46
- });
47
- return ids;
48
- }
49
-
50
- export default function FileTable({
51
- files,
52
- loading,
53
- error,
54
- onToggleShare,
55
- onPatchShare,
56
- onDelete
57
- }: FileTableProps) {
58
- const { load } = useFiles();
59
- const [search, setSearch] = useState('');
60
- const [modalFile, setModalFile] = useState<FileItem | null>(null);
61
- const [selected, setSelected] = useState<Set<number | string>>(new Set());
62
- const [expanded, setExpanded] = useState<Set<string>>(new Set());
63
-
64
- // Upload controls
65
- const [uploadDir, setUploadDir] = useState<string>('');
66
- const [uploadFile, setUploadFile] = useState<File | null>(null);
67
- const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => setUploadFile(e.target.files?.[0] ?? null);
68
- const handleUpload = async () => {
69
- if (!uploadFile) return;
70
- const form = new FormData();
71
- form.append('file', uploadFile);
72
- const dirPart = uploadDir ? `${uploadDir}/` : '';
73
- const url = `/api/secure-files/upload/${dirPart}${encodeURIComponent(uploadFile.name)}`;
74
- await fetch(url, { method: 'POST', credentials: 'include', body: form });
75
- setUploadFile(null);
76
- load();
77
- };
78
-
79
- // Filter files by search term
80
- const filtered = useMemo(
81
- () => files.filter(f => f.filename.toLowerCase().includes(search.trim().toLowerCase())),
82
- [files, search]
83
- );
84
- // Build tree and directory paths list
85
- const tree = useMemo(() => buildTree(filtered), [filtered]);
86
- const allDirPaths = useMemo(() => {
87
- const paths: string[] = [''];
88
- function collect(node: FileNode) {
89
- node.children.forEach(child => {
90
- paths.push(child.path);
91
- collect(child);
92
- });
93
- }
94
- collect(tree);
95
- return paths;
96
- }, [tree]);
97
-
98
- // Selection & expand/collapse logic
99
- const allIds = filtered.map(f => f.id);
100
- const toggleAllSelection = () => selected.size < allIds.length ? setSelected(new Set(allIds)) : setSelected(new Set());
101
- const toggleDirOpen = (path: string) => setExpanded(prev => {
102
- const next = new Set(prev);
103
- next.has(path) ? next.delete(path) : next.add(path);
104
- return next;
105
- });
106
- const expandAll = () => setExpanded(new Set(allDirPaths));
107
- const collapseAll = () => setExpanded(new Set());
108
-
109
- // Recursive renderer: directory row with select-all checkbox, then its files, then subdirectories
110
- const renderNode = (node: FileNode, depth = 0): React.ReactNode[] => {
111
- const rows: React.ReactNode[] = [];
112
- if (node.path) {
113
- const isOpen = expanded.has(node.path);
114
- const nodeIds = collectNodeIds(node);
115
- const allSelected = nodeIds.every(id => selected.has(id));
116
- const someSelected = nodeIds.some(id => selected.has(id));
117
- rows.push(
118
- <tr key={node.path}>
119
- {/* Directory-level checkbox */}
120
- <td className="px-4 py-2 bg-gray-100">
121
- <input
122
- type="checkbox"
123
- checked={allSelected}
124
- ref={el => { if (el) el.indeterminate = !allSelected && someSelected; }}
125
- onChange={() => {
126
- setSelected(prev => {
127
- const next = new Set(prev);
128
- if (allSelected) {
129
- nodeIds.forEach(id => next.delete(id));
130
- } else {
131
- nodeIds.forEach(id => next.add(id));
132
- }
133
- return next;
134
- });
135
- }}
136
- />
137
- </td>
138
- {/* Directory label pushed left */}
139
- <td className="px-4 py-2 bg-gray-100 font-bold" colSpan={5} style={{ textAlign: 'left' }}>
140
- {node.path}
141
- </td>
142
- {/* Expand/collapse ticker on right */}
143
- <td className="px-4 py-2 bg-gray-100 text-right">
144
- <button onClick={() => toggleDirOpen(node.path)}>
145
- {isOpen ? '▾' : '▸'}
146
- </button>
147
- </td>
148
- </tr>
149
- );
150
- if (!isOpen) return rows;
151
- }
152
- // Render files in this directory
153
- node.files.sort((a, b) => a.filename.localeCompare(b.filename)).forEach(f => {
154
- const isOwner = f.uploader_id.toLowerCase() === (currentUsername() ?? '').toLowerCase();
155
- const canDownload = isOwner || f.shareable;
156
- rows.push(
157
- <tr key={f.id}>
158
- <td className="px-4 py-2">
159
- <input
160
- type="checkbox"
161
- checked={selected.has(f.id)}
162
- onChange={() => setSelected(prev => {
163
- const next = new Set(prev);
164
- next.has(f.id) ? next.delete(f.id) : next.add(f.id);
165
- return next;
166
- })}
167
- />
168
- </td>
169
- <td className="px-4 py-2" style={{ paddingLeft: (depth + 1) * 20 }}>
170
- {f.filename}
171
- </td>
172
- <td className="px-4 py-2">
173
- {canDownload ? <Button variant="secondary" onClick={() => downloadFile(f)}>Download</Button> : <span>🔒</span>}
174
- </td>
175
- <td className="px-4 py-2">
176
- {isOwner && <Button variant="icon" onClick={() => setModalFile(f)}>⚙️</Button>}
177
- </td>
178
- <td className="px-4 py-2">
179
- {isOwner && <Button variant={f.shareable ? 'primary' : 'secondary'} onClick={() => onToggleShare(f)}>{f.shareable ? 'Sharing' : 'Share'}</Button>}
180
- </td>
181
- <td className="px-4 py-2">
182
- {isOwner && <Button variant="icon" onClick={() => onDelete(f).then(load)}>🗑</Button>}
183
- </td>
184
- <td className="px-4 py-2">
185
- {f.download_count} / {f.download_limit ?? '∞'}
186
- </td>
187
- </tr>
188
- );
189
- });
190
- // Render subdirectories
191
- Array.from(node.children.values())
192
- .sort((a, b) => a.name.localeCompare(b.name))
193
- .forEach(child => rows.push(...renderNode(child, depth + 1)));
194
- return rows;
195
- };
196
-
197
- // Batch actions
198
- const handleDownloadAll = async () => {
199
- const inputs = filtered.filter(f => selected.has(f.id)).map(f => document.createElement('input'));
200
- inputs.forEach((cb, idx) => cb.value = filtered.filter(f => selected.has(f.id))[idx].filepath);
201
- await downloadSelected(inputs);
202
- };
203
- const handleDeleteAll = async () => { await onDelete(filtered.filter(f => selected.has(f.id))); setSelected(new Set()); await load(); };
204
- const handleShareAll = async () => { for (const f of filtered.filter(f => selected.has(f.id))) await onToggleShare(f); };
205
-
206
- if (loading) return <Spinner />;
207
- if (error) return <p className="text-red-600">{error.message}</p>;
208
-
209
- return (
210
- <>
211
-
212
-
213
- {/* Search & actions */}
214
- <div className="mb-4 flex flex-col md:flex-row md:justify-between gap-4">
215
- <Input label="Search files" type="text" value={search} onChange={e => setSearch(e.target.value)} placeholder="Enter filename…" className="form-input flex-1" />
216
- <div className="flex gap-2">
217
- <Button onClick={expandAll} disabled={!allDirPaths.length}>Expand All</Button>
218
- <Button onClick={collapseAll} disabled={!allDirPaths.length}>Collapse All</Button>
219
- <Button onClick={handleDownloadAll} disabled={!selected.size}>Download Selected</Button>
220
- <Button color="gray" onClick={handleDeleteAll} disabled={!selected.size}>Delete Selected</Button>
221
- <Button onClick={handleShareAll} disabled={!selected.size}>Share Selected</Button>
222
- </div>
223
- </div>
224
-
225
- {/* File tree table */}
226
- <div className="overflow-x-auto wm-container">
227
- <table className="file-table w-full">
228
- <thead className="wm-thead">
229
- <tr>
230
- <th className="px-4 py-2 w-12"><input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAllSelection} /></th>
231
- <th className="px-4 py-2">Filename</th>
232
- <th className="px-4 py-2">Download</th>
233
- <th className="px-4 py-2">Settings</th>
234
- <th className="px-4 py-2">Share</th>
235
- <th className="px-4 py-2">Delete</th>
236
- <th className="px-4 py-2">Downloads</th>
237
- </tr>
238
- </thead>
239
- <tbody>{renderNode(tree)}</tbody>
240
- </table>
241
- </div>
242
-
243
- <ShareModal file={modalFile} onClose={() => setModalFile(null)} onSave={async patch => {
244
- if (!modalFile) return;
245
- const updated: FileItem = { ...modalFile, ...patch };
246
- await onPatchShare(updated);
247
- setModalFile(null);
248
- }} />
249
- </>
250
- );
251
- }
@@ -1,2 +0,0 @@
1
- export {fetchSharePatch,Button, Checkbox, Input, ClipboardIcon, createPortal, useEffect, useRef, useState} from './../imports'
2
- export type {ShareModalProps} from './../imports'
@@ -1 +0,0 @@
1
- export {ShareModal} from './src';
@@ -1 +0,0 @@
1
- export {default as ShareModal} from './share_utils';