@plutonhq/core-frontend 0.1.23 → 0.1.25

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 (143) hide show
  1. package/dist-lib/@types/index.js +4 -1
  2. package/dist-lib/@types/index.js.map +1 -1
  3. package/dist-lib/@types/settings.d.ts +14 -0
  4. package/dist-lib/@types/settings.d.ts.map +1 -1
  5. package/dist-lib/@types/settings.js +34 -0
  6. package/dist-lib/@types/settings.js.map +1 -0
  7. package/dist-lib/components/Plan/Backups/Backups.d.ts.map +1 -1
  8. package/dist-lib/components/Plan/Backups/Backups.js +189 -159
  9. package/dist-lib/components/Plan/Backups/Backups.js.map +1 -1
  10. package/dist-lib/components/Plan/PlanSettings/PlanNotificationSettings.d.ts.map +1 -1
  11. package/dist-lib/components/Plan/PlanSettings/PlanNotificationSettings.js +148 -90
  12. package/dist-lib/components/Plan/PlanSettings/PlanNotificationSettings.js.map +1 -1
  13. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.d.ts +32 -0
  14. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.d.ts.map +1 -0
  15. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.js +252 -0
  16. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.js.map +1 -0
  17. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.d.ts +23 -0
  18. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.d.ts.map +1 -0
  19. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.js +72 -0
  20. package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.js.map +1 -0
  21. package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.d.ts.map +1 -1
  22. package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.js +188 -198
  23. package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.js.map +1 -1
  24. package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.module.scss.js +20 -64
  25. package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.module.scss.js.map +1 -1
  26. package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.d.ts.map +1 -1
  27. package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.js +125 -159
  28. package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.js.map +1 -1
  29. package/dist-lib/components/Settings/IntegrationSettings/IntegrationSettings.d.ts.map +1 -1
  30. package/dist-lib/components/Settings/IntegrationSettings/IntegrationSettings.js +52 -47
  31. package/dist-lib/components/Settings/IntegrationSettings/IntegrationSettings.js.map +1 -1
  32. package/dist-lib/components/Settings/IntegrationSettings/IntegrationSettings.module.scss.js +12 -6
  33. package/dist-lib/components/Settings/IntegrationSettings/IntegrationSettings.module.scss.js.map +1 -1
  34. package/dist-lib/components/Settings/IntegrationSettings/NtfySettings.d.ts +9 -0
  35. package/dist-lib/components/Settings/IntegrationSettings/NtfySettings.d.ts.map +1 -0
  36. package/dist-lib/components/Settings/IntegrationSettings/NtfySettings.js +79 -0
  37. package/dist-lib/components/Settings/IntegrationSettings/NtfySettings.js.map +1 -0
  38. package/dist-lib/components/Settings/IntegrationSettings/SMTPSettings.d.ts +4 -3
  39. package/dist-lib/components/Settings/IntegrationSettings/SMTPSettings.d.ts.map +1 -1
  40. package/dist-lib/components/Settings/IntegrationSettings/SMTPSettings.js +37 -35
  41. package/dist-lib/components/Settings/IntegrationSettings/SMTPSettings.js.map +1 -1
  42. package/dist-lib/components/Settings/IntegrationSettings/ValidateEmailIntegration.d.ts +10 -0
  43. package/dist-lib/components/Settings/IntegrationSettings/ValidateEmailIntegration.d.ts.map +1 -0
  44. package/dist-lib/components/Settings/IntegrationSettings/ValidateEmailIntegration.js +49 -0
  45. package/dist-lib/components/Settings/IntegrationSettings/ValidateEmailIntegration.js.map +1 -0
  46. package/dist-lib/components/Storage/EditStorage/EditStorage.js +10 -10
  47. package/dist-lib/components/Storage/EditStorage/EditStorage.js.map +1 -1
  48. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowser.module.scss.js +74 -0
  49. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowser.module.scss.js.map +1 -0
  50. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.d.ts +17 -0
  51. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.d.ts.map +1 -0
  52. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.js +57 -0
  53. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.js.map +1 -0
  54. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.d.ts +18 -0
  55. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.d.ts.map +1 -0
  56. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.js +24 -0
  57. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.js.map +1 -0
  58. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.d.ts +18 -0
  59. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.d.ts.map +1 -0
  60. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.js +37 -0
  61. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.js.map +1 -0
  62. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.d.ts +9 -0
  63. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.d.ts.map +1 -0
  64. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.js +15 -0
  65. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.js.map +1 -0
  66. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.d.ts +11 -0
  67. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.d.ts.map +1 -0
  68. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.js +18 -0
  69. package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.js.map +1 -0
  70. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.d.ts +12 -0
  71. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.d.ts.map +1 -0
  72. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.js +70 -0
  73. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.js.map +1 -0
  74. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.d.ts +22 -0
  75. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.d.ts.map +1 -0
  76. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.js +79 -0
  77. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.js.map +1 -0
  78. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.d.ts +6 -0
  79. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.d.ts.map +1 -0
  80. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.js +18 -0
  81. package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.js.map +1 -0
  82. package/dist-lib/components/common/SnapshotBrowser/index.d.ts +11 -0
  83. package/dist-lib/components/common/SnapshotBrowser/index.d.ts.map +1 -0
  84. package/dist-lib/components/index.d.ts +12 -0
  85. package/dist-lib/components/index.d.ts.map +1 -1
  86. package/dist-lib/components.js +152 -128
  87. package/dist-lib/components.js.map +1 -1
  88. package/dist-lib/hooks/usePlanSingleActions.d.ts.map +1 -1
  89. package/dist-lib/hooks/usePlanSingleActions.js +21 -21
  90. package/dist-lib/hooks/usePlanSingleActions.js.map +1 -1
  91. package/dist-lib/services/backups.d.ts +4 -0
  92. package/dist-lib/services/backups.d.ts.map +1 -1
  93. package/dist-lib/services/backups.js +34 -25
  94. package/dist-lib/services/backups.js.map +1 -1
  95. package/dist-lib/services/settings.d.ts +3 -2
  96. package/dist-lib/services/settings.d.ts.map +1 -1
  97. package/dist-lib/services/settings.js +0 -1
  98. package/dist-lib/services/settings.js.map +1 -1
  99. package/dist-lib/services.js +113 -112
  100. package/dist-lib/styles/core-frontend.css +1 -1
  101. package/dist-lib/utils/index.d.ts +1 -0
  102. package/dist-lib/utils/index.d.ts.map +1 -1
  103. package/dist-lib/utils/snapshotDatabase.d.ts +16 -0
  104. package/dist-lib/utils/snapshotDatabase.d.ts.map +1 -0
  105. package/dist-lib/utils/snapshotDatabase.js +105 -0
  106. package/dist-lib/utils/snapshotDatabase.js.map +1 -0
  107. package/dist-lib/utils.js +24 -22
  108. package/dist-lib/utils.js.map +1 -1
  109. package/package.json +1 -1
  110. package/src/@types/settings.ts +43 -0
  111. package/src/components/Plan/Backups/Backups.tsx +40 -1
  112. package/src/components/Plan/PlanSettings/PlanNotificationSettings.tsx +65 -0
  113. package/src/components/Plan/SnapshotViewer/SnapshotViewer.tsx +344 -0
  114. package/src/components/Plan/SnapshotViewer/SnapshotViewerFile.tsx +89 -0
  115. package/src/components/Restore/RestoreFileSelector/RestoreFileSelector.tsx +82 -145
  116. package/src/components/Restore/RestoredFileBrowser/RestoredFileBrowser.tsx +71 -156
  117. package/src/components/Settings/IntegrationSettings/IntegrationSettings.module.scss +16 -0
  118. package/src/components/Settings/IntegrationSettings/IntegrationSettings.tsx +45 -42
  119. package/src/components/Settings/IntegrationSettings/NtfySettings.tsx +106 -0
  120. package/src/components/Settings/IntegrationSettings/SMTPSettings.tsx +28 -19
  121. package/src/components/Settings/IntegrationSettings/ValidateEmailIntegration.tsx +58 -0
  122. package/src/components/Storage/EditStorage/EditStorage.tsx +1 -1
  123. package/src/components/common/SnapshotBrowser/SnapshotBrowser.module.scss +376 -0
  124. package/src/components/common/SnapshotBrowser/SnapshotBrowserDirectories.tsx +84 -0
  125. package/src/components/common/SnapshotBrowser/SnapshotBrowserFileList.tsx +52 -0
  126. package/src/components/common/SnapshotBrowser/SnapshotBrowserFileRow.tsx +44 -0
  127. package/src/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.tsx +22 -0
  128. package/src/components/common/SnapshotBrowser/SnapshotBrowserToolbar.tsx +29 -0
  129. package/src/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.ts +130 -0
  130. package/src/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.ts +154 -0
  131. package/src/components/common/SnapshotBrowser/hooks/useSnapshotSort.ts +24 -0
  132. package/src/components/common/SnapshotBrowser/index.ts +13 -0
  133. package/src/components/index.ts +15 -0
  134. package/src/hooks/usePlanSingleActions.tsx +5 -3
  135. package/src/services/backups.ts +12 -0
  136. package/src/services/settings.ts +2 -2
  137. package/src/utils/index.ts +1 -0
  138. package/src/utils/snapshotDatabase.ts +201 -0
  139. /package/dist-lib/providers/{azureBlob.png → azureblob.png} +0 -0
  140. /package/dist-lib/providers/{azureFiles.png → azurefiles.png} +0 -0
  141. /package/dist-lib/providers/{files.png → filescom.png} +0 -0
  142. /package/dist-lib/providers/{oracle.png → oracleobjectstorage.png} +0 -0
  143. /package/dist-lib/providers/{proton.png → protondrive.png} +0 -0
@@ -0,0 +1,376 @@
1
+ .snapshotBrowser {
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+ border: 1px solid var(--line-color);
6
+ border-radius: 8px;
7
+ overflow: hidden;
8
+ }
9
+
10
+ .storageSelect {
11
+ background-color: transparent;
12
+ :global([class*='_dropdown_']) {
13
+ min-width: 250px;
14
+ }
15
+ }
16
+
17
+ .toolbar {
18
+ display: flex;
19
+ padding: 10px;
20
+ border-bottom: 1px solid var(--line-color);
21
+ gap: 15px;
22
+ align-items: center;
23
+ justify-content: space-between;
24
+ .toolbarRight {
25
+ display: flex;
26
+ flex-direction: row;
27
+ gap: 15px;
28
+ justify-content: space-between;
29
+ align-items: center;
30
+
31
+ .search {
32
+ display: flex;
33
+ align-items: center;
34
+ gap: 8px;
35
+ padding: 6px 12px;
36
+ border: 1px solid var(--line-color);
37
+ border-radius: 4px;
38
+ margin-left: auto;
39
+
40
+ input {
41
+ border: none;
42
+ outline: none;
43
+ font-size: 0.75rem;
44
+ min-width: 200px;
45
+ background-color: var(--content-background-color);
46
+ }
47
+ }
48
+ }
49
+
50
+ .toolbarLeft {
51
+ .stats {
52
+ display: flex;
53
+ flex-direction: row;
54
+ gap: 8px;
55
+ color: var(--content-text-color-light);
56
+ strong {
57
+ color: var(--content-text-color);
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ .browserContent {
64
+ display: flex;
65
+ flex: 1;
66
+ overflow: hidden;
67
+
68
+ &.loadingState {
69
+ align-items: center;
70
+ justify-content: center;
71
+ }
72
+ }
73
+
74
+ .sidebar {
75
+ width: 300px;
76
+ border-right: 1px solid var(--line-color);
77
+ overflow-y: auto;
78
+
79
+ .sidebarHeader {
80
+ padding: 12px;
81
+ background: var(--background-color);
82
+ font-weight: 600;
83
+ position: sticky;
84
+ top: 0;
85
+ z-index: 2;
86
+ display: flex;
87
+ justify-content: space-between;
88
+ h4 {
89
+ margin: 0;
90
+ }
91
+ }
92
+ .noDirectories {
93
+ padding: 12px;
94
+ color: var(--content-text-color-light);
95
+ font-size: 0.85rem;
96
+ }
97
+ }
98
+
99
+ .directory {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 8px;
103
+ padding: 8px 16px;
104
+ cursor: pointer;
105
+ position: relative;
106
+ button {
107
+ width: 20px;
108
+ }
109
+ .toggleButton {
110
+ border: 1px solid var(--line-color);
111
+ width: auto;
112
+ padding: 0px 4px;
113
+ border-radius: 3px;
114
+ }
115
+ .togglePlaceholder {
116
+ width: 10px;
117
+ height: 10px;
118
+ }
119
+ .dirName {
120
+ position: relative;
121
+ .notification {
122
+ width: 7px;
123
+ height: 7px;
124
+ background: var(--primary-color);
125
+ border-radius: 50%;
126
+ margin-left: auto;
127
+ position: absolute;
128
+ left: -2px;
129
+ top: 8px;
130
+ }
131
+ }
132
+ &.directoryEmpty {
133
+ .dirName {
134
+ padding-left: 20px;
135
+ .notification {
136
+ left: 8px;
137
+ }
138
+ }
139
+ }
140
+
141
+ &:hover {
142
+ background: var(--background-color);
143
+ }
144
+ }
145
+
146
+ .selected {
147
+ background: var(--primary-color-light);
148
+ }
149
+
150
+ .content {
151
+ flex: 1;
152
+ overflow-y: auto;
153
+ }
154
+
155
+ .fileList {
156
+ .header {
157
+ display: grid;
158
+ padding: 12px;
159
+ background: var(--background-color);
160
+ font-weight: 600;
161
+ position: sticky;
162
+ z-index: 2;
163
+ top: 0;
164
+ div {
165
+ display: flex;
166
+ width: 100%;
167
+ justify-content: center;
168
+ cursor: pointer;
169
+ user-select: none;
170
+ &.activeSort {
171
+ font-weight: bold;
172
+ cursor: pointer;
173
+ }
174
+
175
+ &:nth-child(1) {
176
+ justify-content: left;
177
+ }
178
+
179
+ &.headerActions {
180
+ justify-content: right;
181
+ }
182
+ }
183
+ }
184
+ }
185
+
186
+ .fileListEmpty {
187
+ height: calc(100vh - 400px);
188
+ width: 100%;
189
+ display: flex;
190
+ align-items: center;
191
+ justify-content: center;
192
+ }
193
+
194
+ .virtualFileList {
195
+ flex: 1;
196
+ overflow: hidden;
197
+ }
198
+
199
+ .snapshotFile {
200
+ display: grid;
201
+ padding: 12px;
202
+ align-items: center;
203
+ box-sizing: border-box;
204
+ border-bottom: 1px solid var(--line-color);
205
+ & > div {
206
+ display: flex;
207
+ width: 100%;
208
+ justify-content: center;
209
+
210
+ &:nth-child(1) {
211
+ justify-content: left;
212
+ gap: 5px;
213
+ word-break: break-all;
214
+ }
215
+ }
216
+
217
+ &.fileIsDir {
218
+ .fileName {
219
+ cursor: pointer;
220
+ i {
221
+ width: 8px;
222
+ height: 8px;
223
+ display: inline-block;
224
+ margin-left: 8px;
225
+ background: var(--primary-color);
226
+ border-radius: 50%;
227
+ }
228
+ &:hover {
229
+ color: var(--primary-color);
230
+ }
231
+ }
232
+ }
233
+
234
+ .fileModifiedAt {
235
+ i {
236
+ font-style: normal;
237
+ }
238
+ }
239
+ .fileModifiedAt,
240
+ .fileSize {
241
+ color: var(--content-text-color-light);
242
+ }
243
+ .fileActions {
244
+ display: flex;
245
+ align-items: center;
246
+ width: 100%;
247
+ justify-content: right;
248
+ button {
249
+ color: var(--icon-color);
250
+ transition: all 0.12s linear;
251
+ &:hover {
252
+ color: var(--primary-color);
253
+ }
254
+ }
255
+ }
256
+
257
+ &:last-child {
258
+ border-bottom: none;
259
+ }
260
+ }
261
+
262
+ .goUpButton {
263
+ font-style: italic;
264
+ opacity: 0.8;
265
+ padding: 0px 12px;
266
+
267
+ &:hover {
268
+ background-color: var(--primary-color-light);
269
+ }
270
+
271
+ .fileName {
272
+ font-weight: normal;
273
+ }
274
+ }
275
+
276
+ .loadingState,
277
+ .errorState {
278
+ display: flex;
279
+ flex-direction: column;
280
+ align-items: center;
281
+ justify-content: center;
282
+ height: 400px;
283
+ gap: 16px;
284
+ color: var(--text-muted);
285
+
286
+ small {
287
+ color: var(--text-muted);
288
+ opacity: 0.8;
289
+ }
290
+ }
291
+
292
+ .errorState button {
293
+ padding: 8px 16px;
294
+ background: var(--primary);
295
+ color: white;
296
+ border: none;
297
+ border-radius: 4px;
298
+ cursor: pointer;
299
+ }
300
+
301
+ .restoreModalFile {
302
+ word-break: break-all;
303
+ background: var(--primary-color-light);
304
+ padding: 10px;
305
+ border-radius: 6px;
306
+ }
307
+
308
+ @media only screen and (max-width: 768px) {
309
+ .toolbar {
310
+ flex-direction: column;
311
+ align-items: flex-start;
312
+ gap: 10px;
313
+ .toolbarLeft {
314
+ width: 100%;
315
+ .stats {
316
+ font-size: 0.9em;
317
+ :global(.icon) {
318
+ display: none;
319
+ }
320
+ }
321
+ }
322
+ .toolbarRight {
323
+ width: 100%;
324
+ .search {
325
+ width: 100%;
326
+ }
327
+ }
328
+ }
329
+ .sidebar {
330
+ display: none;
331
+ }
332
+
333
+ .content {
334
+ padding: 0;
335
+ }
336
+
337
+ .fileList {
338
+ .header {
339
+ display: none;
340
+ }
341
+ .snapshotFile {
342
+ display: block;
343
+ padding: 10px;
344
+ font-size: 0.9em;
345
+ .fileName {
346
+ width: 100%;
347
+ margin-bottom: 4px;
348
+ white-space: nowrap;
349
+ overflow: hidden;
350
+ text-overflow: ellipsis;
351
+ }
352
+ & > div {
353
+ display: block;
354
+ width: auto;
355
+ float: left;
356
+ margin-right: 12px;
357
+ }
358
+ .fileActions {
359
+ display: block;
360
+ width: auto;
361
+ float: right;
362
+ margin-right: 0;
363
+ }
364
+ &.goUpButton {
365
+ display: flex;
366
+ align-items: center;
367
+ .fileName::after {
368
+ content: ' Go Up ↑';
369
+ font-size: 12px;
370
+ font-style: normal;
371
+ font-weight: 500;
372
+ }
373
+ }
374
+ }
375
+ }
376
+ }
@@ -0,0 +1,84 @@
1
+ import { ReactNode } from 'react';
2
+ import Icon from '../Icon/Icon';
3
+ import classes from './SnapshotBrowser.module.scss';
4
+
5
+ interface SnapshotBrowserDirectoriesProps {
6
+ directories: string[];
7
+ selectedFolder: string;
8
+ expandedFolders: Set<string>;
9
+ useProgressiveLoading?: boolean;
10
+ onDirectoryClick: (path: string) => void;
11
+ onToggleFolder: (dir: string) => void;
12
+ isVisible: (dir: string) => boolean;
13
+ hasSubdirectories: (dir: string) => boolean;
14
+ renderDirectoryExtra?: (dir: string) => ReactNode;
15
+ /** Custom function to split a path into parts. Defaults to splitting by / and \ */
16
+ splitPath?: (path: string) => string[];
17
+ }
18
+
19
+ const defaultSplitPath = (path: string) => path.split(/[/\\]/).filter(Boolean);
20
+
21
+ const SnapshotBrowserDirectories = ({
22
+ directories,
23
+ selectedFolder,
24
+ expandedFolders,
25
+ useProgressiveLoading,
26
+ onDirectoryClick,
27
+ onToggleFolder,
28
+ isVisible,
29
+ hasSubdirectories,
30
+ renderDirectoryExtra,
31
+ splitPath: splitPathFn = defaultSplitPath,
32
+ }: SnapshotBrowserDirectoriesProps) => {
33
+ return (
34
+ <div className={`${classes.sidebar} styled__scrollbar`}>
35
+ <div className={classes.sidebarHeader}>
36
+ <h4>
37
+ Directories ({directories.length}
38
+ {useProgressiveLoading && '+'})
39
+ </h4>
40
+ </div>
41
+ {directories.length === 0 && (
42
+ <div className={classes.noDirectories}>{useProgressiveLoading ? 'Loading directories...' : 'No directories found'}</div>
43
+ )}
44
+ {directories.map((dir) => {
45
+ const parts = splitPathFn(dir);
46
+ const dirName = parts[parts.length - 1] || dir;
47
+ const depth = parts.length - 1;
48
+ const isExpanded = expandedFolders.has(dir);
49
+ const hasChildren = hasSubdirectories(dir);
50
+
51
+ if (!isVisible(dir)) return null;
52
+
53
+ return (
54
+ <div
55
+ key={dir}
56
+ className={`${classes.directory} ${selectedFolder === dir ? classes.selected : ''} ${hasChildren ? '' : classes.directoryEmpty}`}
57
+ style={{ paddingLeft: `${depth * 20}px` }}
58
+ onClick={() => onDirectoryClick(dir)}
59
+ >
60
+ {hasChildren ? (
61
+ <button
62
+ className={classes.toggleButton}
63
+ onClick={(e) => {
64
+ e.stopPropagation();
65
+ onToggleFolder(dir);
66
+ }}
67
+ >
68
+ {isExpanded ? '-' : '+'}
69
+ </button>
70
+ ) : (
71
+ <span className={classes.togglePlaceholder} />
72
+ )}
73
+ <span className={classes.dirName}>
74
+ <Icon type={'fm-directory'} size={14} /> {dirName}
75
+ </span>
76
+ {renderDirectoryExtra?.(dir)}
77
+ </div>
78
+ );
79
+ })}
80
+ </div>
81
+ );
82
+ };
83
+
84
+ export default SnapshotBrowserDirectories;
@@ -0,0 +1,52 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { FixedSizeList as List } from 'react-window';
3
+ import classes from './SnapshotBrowser.module.scss';
4
+ import { isMobile } from '../../../utils';
5
+
6
+ const isMobileDevice = isMobile();
7
+ const DEFAULT_ITEM_HEIGHT = isMobileDevice ? 65 : 46;
8
+
9
+ interface SnapshotBrowserFileListProps {
10
+ files: any[];
11
+ height: number;
12
+ itemSize?: number;
13
+ headerContent: ReactNode;
14
+ renderRow: (props: { index: number; style: React.CSSProperties }) => React.ReactElement | null;
15
+ selectedFolder: string | null;
16
+ emptyMessage?: string;
17
+ isLoading?: boolean;
18
+ gridTemplateColumns?: string;
19
+ }
20
+
21
+ const SnapshotBrowserFileList = ({
22
+ files,
23
+ height,
24
+ itemSize = DEFAULT_ITEM_HEIGHT,
25
+ headerContent,
26
+ renderRow,
27
+ selectedFolder,
28
+ emptyMessage = 'Select a folder from the left to browse its content',
29
+ isLoading,
30
+ gridTemplateColumns,
31
+ }: SnapshotBrowserFileListProps) => {
32
+ return (
33
+ <div className={classes.fileList}>
34
+ <div className={classes.header} style={gridTemplateColumns ? { gridTemplateColumns } : undefined}>
35
+ {headerContent}
36
+ </div>
37
+
38
+ {selectedFolder !== null && files.length > 0 && (
39
+ <div className={classes.virtualFileList}>
40
+ <List height={height} itemCount={files.length} itemSize={itemSize} width="100%" overscanCount={5}>
41
+ {renderRow}
42
+ </List>
43
+ </div>
44
+ )}
45
+
46
+ {selectedFolder === null && <div className={classes.fileListEmpty}>{emptyMessage}</div>}
47
+ {selectedFolder !== null && !isLoading && files.length === 0 && <div className={classes.fileListEmpty}>This folder is empty</div>}
48
+ </div>
49
+ );
50
+ };
51
+
52
+ export default SnapshotBrowserFileList;
@@ -0,0 +1,44 @@
1
+ import React, { ReactNode } from 'react';
2
+ import Icon from '../Icon/Icon';
3
+ import FileIcon from '../FileIcon/FileIcon';
4
+ import classes from './SnapshotBrowser.module.scss';
5
+
6
+ interface SnapshotBrowserFileRowProps {
7
+ style: React.CSSProperties;
8
+ file: { path: string; name?: string; isDirectory?: boolean };
9
+ isDirectory: boolean;
10
+ onClick?: () => void;
11
+ namePrefix?: ReactNode;
12
+ children?: ReactNode;
13
+ gridTemplateColumns?: string;
14
+ className?: string;
15
+ }
16
+
17
+ const SnapshotBrowserFileRow = ({
18
+ style,
19
+ file,
20
+ isDirectory,
21
+ onClick,
22
+ namePrefix,
23
+ children,
24
+ gridTemplateColumns,
25
+ className,
26
+ }: SnapshotBrowserFileRowProps) => {
27
+ const fileName = file.name || file.path.split('/').pop() || '';
28
+
29
+ return (
30
+ <div
31
+ style={{ ...style, ...(gridTemplateColumns ? { gridTemplateColumns } : {}) }}
32
+ className={`${classes.snapshotFile} ${isDirectory ? classes.fileIsDir : ''} ${className || ''}`}
33
+ onClick={onClick}
34
+ >
35
+ <div className={classes.fileName}>
36
+ {namePrefix}
37
+ {isDirectory ? <Icon type={'fm-directory'} size={16} /> : <FileIcon filename={fileName} />} {fileName}
38
+ </div>
39
+ {children}
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export default SnapshotBrowserFileRow;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import classes from './SnapshotBrowser.module.scss';
3
+
4
+ interface SnapshotBrowserGoUpRowProps {
5
+ style: React.CSSProperties;
6
+ onGoUp: () => void;
7
+ gridTemplateColumns?: string;
8
+ }
9
+
10
+ const SnapshotBrowserGoUpRow = ({ style, onGoUp, gridTemplateColumns }: SnapshotBrowserGoUpRowProps) => {
11
+ return (
12
+ <div
13
+ style={{ ...style, ...(gridTemplateColumns ? { gridTemplateColumns } : {}) }}
14
+ className={`${classes.snapshotFile} ${classes.fileIsDir} ${classes.goUpButton}`}
15
+ onClick={onGoUp}
16
+ >
17
+ <div className={classes.fileName}>...</div>
18
+ </div>
19
+ );
20
+ };
21
+
22
+ export default SnapshotBrowserGoUpRow;
@@ -0,0 +1,29 @@
1
+ import { ReactNode } from 'react';
2
+ import Icon from '../Icon/Icon';
3
+ import classes from './SnapshotBrowser.module.scss';
4
+
5
+ interface SnapshotBrowserToolbarProps {
6
+ search: string;
7
+ onSearchChange: (value: string) => void;
8
+ isLoading?: boolean;
9
+ leftContent?: ReactNode;
10
+ rightContent?: ReactNode;
11
+ }
12
+
13
+ const SnapshotBrowserToolbar = ({ search, onSearchChange, isLoading, leftContent, rightContent }: SnapshotBrowserToolbarProps) => {
14
+ return (
15
+ <div className={classes.toolbar}>
16
+ <div className={classes.toolbarLeft}>{leftContent}</div>
17
+ <div className={classes.toolbarRight}>
18
+ {rightContent}
19
+ <div className={classes.search}>
20
+ <Icon type="search" size={16} />
21
+ <input type="text" placeholder="Search in current Directory..." value={search} onChange={(e) => onSearchChange(e.target.value)} />
22
+ {isLoading && <Icon type="loading" size={12} />}
23
+ </div>
24
+ </div>
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export default SnapshotBrowserToolbar;