@duplicati/ngclient 0.0.1 → 0.0.6

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 (197) hide show
  1. package/chunk-22HCWJS5.js +1 -0
  2. package/chunk-24PLBY6C.js +1 -0
  3. package/chunk-3MM4GLBS.js +1 -0
  4. package/chunk-3MTW6FJP.js +1 -0
  5. package/chunk-4FK75Z4C.js +1 -0
  6. package/chunk-4MMHXTNF.js +1 -0
  7. package/chunk-57M4MADC.js +1 -0
  8. package/chunk-6XUWDRDE.js +1 -0
  9. package/chunk-77NTMJCT.js +1 -0
  10. package/chunk-7X6SBNMU.js +1 -0
  11. package/chunk-A66Z6362.js +1 -0
  12. package/chunk-AC6VDRLC.js +1 -0
  13. package/chunk-BNNZKRIC.js +1 -0
  14. package/chunk-CKPPU3GS.js +2 -0
  15. package/chunk-DYANEO5K.js +1 -0
  16. package/chunk-GJTW7UUU.js +1 -0
  17. package/chunk-GMANGOGH.js +1 -0
  18. package/chunk-I6QIKK6M.js +1 -0
  19. package/chunk-IOWSWUHM.js +1 -0
  20. package/chunk-IQSBPGVL.js +1 -0
  21. package/chunk-L47VTK2X.js +1 -0
  22. package/chunk-LVLU6MPQ.js +1 -0
  23. package/chunk-N5US3SKW.js +1 -0
  24. package/chunk-NIMPOFJV.js +1 -0
  25. package/chunk-ORDBF5MR.js +8 -0
  26. package/chunk-PH6AAOK4.js +1 -0
  27. package/chunk-PY5HJ5U2.js +1 -0
  28. package/chunk-QQDSFTZV.js +1 -0
  29. package/chunk-RANWFSNY.js +1 -0
  30. package/chunk-RLJJFBQ2.js +1 -0
  31. package/chunk-S76TN27U.js +1 -0
  32. package/chunk-UTPCUNNU.js +1 -0
  33. package/chunk-VPEVWKGB.js +1 -0
  34. package/chunk-VVUYO7E4.js +1 -0
  35. package/chunk-WLI4RZYL.js +1 -0
  36. package/chunk-X2NZ4CJ5.js +2 -0
  37. package/chunk-XU7PNEZO.js +1 -0
  38. package/chunk-XYJYUMYL.js +1 -0
  39. package/chunk-YRXI477O.js +1 -0
  40. package/chunk-ZD3JEKWI.js +1 -0
  41. package/index.html +15 -0
  42. package/main-5KJRELCN.js +1 -0
  43. package/package.json +3 -40
  44. package/sparkle-ui-assets/fonts/InterTight-VariableFont_wght.ttf +0 -0
  45. package/sparkle-ui-assets/fonts/InterTight-VariableFont_wght.woff2 +0 -0
  46. package/styles-6W7ZCKNM.css +1 -0
  47. package/.dockerignore +0 -13
  48. package/.github/workflows/npm-publish.yml +0 -59
  49. package/.prettierignore +0 -13
  50. package/.prettierrc +0 -12
  51. package/.vscode/extensions.json +0 -4
  52. package/.vscode/launch.json +0 -13
  53. package/.vscode/settings.json +0 -8
  54. package/.vscode/tasks.json +0 -24
  55. package/Dockerfile +0 -38
  56. package/LICENSE +0 -21
  57. package/README.md +0 -27
  58. package/angular.json +0 -98
  59. package/bun.lockb +0 -0
  60. package/openapi-ts.config.ts +0 -13
  61. package/scripts/generate-package-json.ts +0 -15
  62. package/src/app/about/about.component.html +0 -15
  63. package/src/app/about/about.component.scss +0 -19
  64. package/src/app/about/about.component.ts +0 -13
  65. package/src/app/about/changelog/changelog.component.html +0 -3
  66. package/src/app/about/changelog/changelog.component.scss +0 -7
  67. package/src/app/about/changelog/changelog.component.ts +0 -18
  68. package/src/app/about/general/general.component.html +0 -9
  69. package/src/app/about/general/general.component.scss +0 -23
  70. package/src/app/about/general/general.component.ts +0 -30
  71. package/src/app/about/libraries/libraries.component.html +0 -3
  72. package/src/app/about/libraries/libraries.component.scss +0 -7
  73. package/src/app/about/libraries/libraries.component.ts +0 -18
  74. package/src/app/about/logs/logs.component.html +0 -5
  75. package/src/app/about/logs/logs.component.scss +0 -7
  76. package/src/app/about/logs/logs.component.ts +0 -18
  77. package/src/app/about/system-info/system-info.component.html +0 -3
  78. package/src/app/about/system-info/system-info.component.scss +0 -7
  79. package/src/app/about/system-info/system-info.component.ts +0 -17
  80. package/src/app/add-backup/add-backup.component.html +0 -29
  81. package/src/app/add-backup/add-backup.component.scss +0 -38
  82. package/src/app/add-backup/add-backup.component.ts +0 -14
  83. package/src/app/app.component.ts +0 -35
  84. package/src/app/app.config.ts +0 -23
  85. package/src/app/app.routes.ts +0 -121
  86. package/src/app/core/components/file-tree/file-tree.component.html +0 -87
  87. package/src/app/core/components/file-tree/file-tree.component.scss +0 -80
  88. package/src/app/core/components/file-tree/file-tree.component.ts +0 -485
  89. package/src/app/core/components/logo/logo.component.html +0 -22
  90. package/src/app/core/components/logo/logo.component.scss +0 -12
  91. package/src/app/core/components/logo/logo.component.ts +0 -11
  92. package/src/app/core/components/status-bar/status-bar.component.html +0 -38
  93. package/src/app/core/components/status-bar/status-bar.component.scss +0 -27
  94. package/src/app/core/components/status-bar/status-bar.component.ts +0 -33
  95. package/src/app/core/components/status-bar/status-bar.state.ts +0 -182
  96. package/src/app/core/components/toggle-card/toggle-card.component.html +0 -11
  97. package/src/app/core/components/toggle-card/toggle-card.component.scss +0 -49
  98. package/src/app/core/components/toggle-card/toggle-card.component.ts +0 -28
  99. package/src/app/core/interceptors/http.interceptor.ts +0 -69
  100. package/src/app/core/interceptors/websocket.interceptor.ts +0 -66
  101. package/src/app/core/openapi/core/ApiError.ts +0 -21
  102. package/src/app/core/openapi/core/ApiRequestOptions.ts +0 -21
  103. package/src/app/core/openapi/core/ApiResult.ts +0 -7
  104. package/src/app/core/openapi/core/OpenAPI.ts +0 -55
  105. package/src/app/core/openapi/core/request.ts +0 -337
  106. package/src/app/core/openapi/index.ts +0 -6
  107. package/src/app/core/openapi/schemas.gen.ts +0 -3611
  108. package/src/app/core/openapi/services.gen.ts +0 -1460
  109. package/src/app/core/openapi/types.gen.ts +0 -1510
  110. package/src/app/core/pipes/duration.pipe.ts +0 -27
  111. package/src/app/core/pipes/relative-time.pipe.ts +0 -14
  112. package/src/app/core/providers/dayjs.ts +0 -16
  113. package/src/app/core/services/dict.en.ts +0 -0
  114. package/src/app/core/services/dictionary.service.ts +0 -12
  115. package/src/app/core/services/localstorage.token.ts +0 -82
  116. package/src/app/core/services/password-generator.service.ts +0 -39
  117. package/src/app/core/services/relay-websocket.service.ts +0 -268
  118. package/src/app/core/services/timespan-literals.service.ts +0 -25
  119. package/src/app/core/states/app-auth.state.ts +0 -87
  120. package/src/app/core/states/backups.state.ts +0 -71
  121. package/src/app/core/states/relayconfig.state.ts +0 -23
  122. package/src/app/core/states/sysinfo.state.ts +0 -31
  123. package/src/app/core/states/tasks.state.ts +0 -34
  124. package/src/app/core/types/subscribed.ts +0 -7
  125. package/src/app/core/validators/custom.validators.ts +0 -120
  126. package/src/app/create-edit-backup/create-edit-backup.component.html +0 -28
  127. package/src/app/create-edit-backup/create-edit-backup.component.scss +0 -15
  128. package/src/app/create-edit-backup/create-edit-backup.component.ts +0 -33
  129. package/src/app/create-edit-backup/create-edit-backup.state.ts +0 -582
  130. package/src/app/create-edit-backup/destination/destination.component.html +0 -367
  131. package/src/app/create-edit-backup/destination/destination.component.scss +0 -85
  132. package/src/app/create-edit-backup/destination/destination.component.ts +0 -249
  133. package/src/app/create-edit-backup/destination/destination.config.ts +0 -103
  134. package/src/app/create-edit-backup/destination/destination.mapper.ts +0 -177
  135. package/src/app/create-edit-backup/general/general.component.html +0 -108
  136. package/src/app/create-edit-backup/general/general.component.scss +0 -34
  137. package/src/app/create-edit-backup/general/general.component.ts +0 -136
  138. package/src/app/create-edit-backup/options/options.component.html +0 -95
  139. package/src/app/create-edit-backup/options/options.component.scss +0 -42
  140. package/src/app/create-edit-backup/options/options.component.ts +0 -113
  141. package/src/app/create-edit-backup/schedule/schedule.component.html +0 -102
  142. package/src/app/create-edit-backup/schedule/schedule.component.scss +0 -38
  143. package/src/app/create-edit-backup/schedule/schedule.component.ts +0 -137
  144. package/src/app/create-edit-backup/source-data/source-data.component.html +0 -93
  145. package/src/app/create-edit-backup/source-data/source-data.component.scss +0 -41
  146. package/src/app/create-edit-backup/source-data/source-data.component.ts +0 -114
  147. package/src/app/home/backup.const.ts +0 -167
  148. package/src/app/home/home.component.html +0 -98
  149. package/src/app/home/home.component.scss +0 -88
  150. package/src/app/home/home.component.ts +0 -54
  151. package/src/app/layout/layout.component.html +0 -64
  152. package/src/app/layout/layout.component.scss +0 -24
  153. package/src/app/layout/layout.component.ts +0 -51
  154. package/src/app/layout/layout.state.ts +0 -70
  155. package/src/app/login/login.component.html +0 -12
  156. package/src/app/login/login.component.scss +0 -25
  157. package/src/app/login/login.component.ts +0 -34
  158. package/src/app/logout/logout.component.html +0 -1
  159. package/src/app/logout/logout.component.scss +0 -3
  160. package/src/app/logout/logout.component.ts +0 -18
  161. package/src/app/restore/restore.component.html +0 -56
  162. package/src/app/restore/restore.component.scss +0 -37
  163. package/src/app/restore/restore.component.ts +0 -55
  164. package/src/app/restore-flow/options/options.component.html +0 -57
  165. package/src/app/restore-flow/options/options.component.scss +0 -16
  166. package/src/app/restore-flow/options/options.component.ts +0 -58
  167. package/src/app/restore-flow/restore-flow.component.html +0 -14
  168. package/src/app/restore-flow/restore-flow.component.scss +0 -15
  169. package/src/app/restore-flow/restore-flow.component.ts +0 -23
  170. package/src/app/restore-flow/restore-flow.state.ts +0 -120
  171. package/src/app/restore-flow/select-files/select-files.component.html +0 -42
  172. package/src/app/restore-flow/select-files/select-files.component.scss +0 -16
  173. package/src/app/restore-flow/select-files/select-files.component.ts +0 -129
  174. package/src/app/settings/settings.component.html +0 -256
  175. package/src/app/settings/settings.component.scss +0 -106
  176. package/src/app/settings/settings.component.ts +0 -475
  177. package/src/environments/environment-token.ts +0 -4
  178. package/src/environments/environment.prod.ts +0 -6
  179. package/src/environments/environment.ts +0 -6
  180. package/src/index.html +0 -15
  181. package/src/main.ts +0 -6
  182. package/src/proxy.conf.mjs +0 -6
  183. package/src/styles.scss +0 -41
  184. package/tsconfig.app.json +0 -15
  185. package/tsconfig.json +0 -30
  186. /package/{src/assets → assets}/duplicati-logo.png +0 -0
  187. /package/{src/assets → assets}/duplicati-logo.svg +0 -0
  188. /package/{src/assets → assets}/favicon.ico +0 -0
  189. /package/{src/assets → assets}/images/backup.png +0 -0
  190. /package/{src/assets → assets}/images/dark-theme.png +0 -0
  191. /package/{src/assets → assets}/images/folder.png +0 -0
  192. /package/{src/assets → assets}/images/light-theme.png +0 -0
  193. /package/{src/assets → assets}/images/new-backup.png +0 -0
  194. /package/{src/assets → assets}/images/restore.png +0 -0
  195. /package/{src/assets → assets}/images/system-theme.png +0 -0
  196. /package/{src/assets → assets}/spk.css +0 -0
  197. /package/{src/assets → assets}/spk.woff2 +0 -0
@@ -1,485 +0,0 @@
1
- import { JsonPipe, NgTemplateOutlet } from '@angular/common';
2
- import {
3
- ChangeDetectionStrategy,
4
- Component,
5
- computed,
6
- effect,
7
- ElementRef,
8
- inject,
9
- input,
10
- output,
11
- signal,
12
- viewChild,
13
- } from '@angular/core';
14
- import { FormsModule } from '@angular/forms';
15
- import {
16
- SparkleButtonGroupComponent,
17
- SparkleCheckboxComponent,
18
- SparkleFormFieldComponent,
19
- SparkleIconComponent,
20
- SparkleListComponent,
21
- SparkleToggleComponent,
22
- } from '@sparkle-ui/core';
23
- import { finalize, forkJoin, Observable } from 'rxjs';
24
- import { DuplicatiServerService, GetApiV1BackupByIdFilesData, TreeNodeDto } from '../../openapi';
25
-
26
- type TreeNode = TreeNodeDto & {
27
- isSelected: boolean;
28
- parentPath: string;
29
- };
30
-
31
- type FileTreeNode = TreeNode & {
32
- children: FileTreeNode[];
33
- };
34
-
35
- type InputValueChangedEvent = CustomEvent<{ value: string }>;
36
-
37
- interface CustomEventMap {
38
- inputValueChanged: InputValueChangedEvent;
39
- }
40
-
41
- declare global {
42
- interface HTMLInputElement {
43
- // Extend HTMLElement to cover input elements
44
- addEventListener<K extends keyof CustomEventMap>(
45
- type: K,
46
- listener: (this: HTMLElement, ev: CustomEventMap[K]) => any,
47
- options?: boolean | AddEventListenerOptions
48
- ): void;
49
- }
50
- }
51
-
52
- type BackupSettings = {
53
- id: string;
54
- time: string;
55
- };
56
-
57
- // TODO
58
- // - Scroll to newly selected node by path
59
- // - When rootPath get all the levels and batch them at the root level for better usability
60
-
61
- @Component({
62
- selector: 'app-file-tree',
63
- standalone: true,
64
- imports: [
65
- SparkleButtonGroupComponent,
66
- SparkleToggleComponent,
67
- SparkleIconComponent,
68
- SparkleFormFieldComponent,
69
- SparkleListComponent,
70
- SparkleCheckboxComponent,
71
- NgTemplateOutlet,
72
- JsonPipe,
73
- FormsModule,
74
- ],
75
- templateUrl: './file-tree.component.html',
76
- styleUrl: './file-tree.component.scss',
77
- changeDetection: ChangeDetectionStrategy.OnPush,
78
- host: {
79
- '[class.disabled]': 'disabled()',
80
- },
81
- })
82
- export default class FileTreeComponent {
83
- #dupServer = inject(DuplicatiServerService);
84
-
85
- multiSelect = input(false);
86
- disabled = input(false);
87
- showFiles = input(false);
88
- startingPath = input<string | null>(null);
89
- rootPath = input<string | undefined>(undefined);
90
- backupSettings = input<BackupSettings | null>(null);
91
- includes = output<string[]>();
92
- excludes = output<string[]>();
93
-
94
- treeContainerRef = viewChild<ElementRef<HTMLDivElement>>('treeContainer');
95
- formRef = viewChild<ElementRef<HTMLFormElement>>('formRef');
96
- pathDiscoveryMethod = signal<'browse' | 'path'>('browse');
97
- isLoading = signal(false);
98
- showHiddenFiles = signal(false);
99
- currentPath = signal<string>('/');
100
- #inputRef = signal<HTMLInputElement | null>(null);
101
- treeSearchQuery = signal<string>('');
102
- treeNodes = signal<TreeNode[]>([]);
103
-
104
- isByBackupSettings = computed(() => this.rootPath() && this.backupSettings()?.id && this.backupSettings()?.time);
105
- searchableTreeNodes = computed<TreeNode[]>(() => {
106
- const query = this.treeSearchQuery();
107
- return query
108
- ? this.treeNodes().filter((x) => x.text?.toLowerCase().includes(query.toLowerCase()))
109
- : this.treeNodes();
110
- });
111
- treeStructure = computed<FileTreeNode[]>(() => {
112
- const nodes = this.searchableTreeNodes();
113
- const nodeMap = new Map<string, FileTreeNode>();
114
- const rootPath = this.rootPath();
115
-
116
- const root: FileTreeNode = rootPath
117
- ? {
118
- id: rootPath,
119
- resolvedpath: rootPath,
120
- text: rootPath?.replaceAll('/', ''),
121
- parentPath: '',
122
- children: [],
123
- isSelected: false,
124
- cls: 'folder',
125
- }
126
- : {
127
- id: '/',
128
- resolvedpath: '/',
129
- text: 'Computer',
130
- parentPath: '',
131
- children: [],
132
- isSelected: false,
133
- };
134
-
135
- nodeMap.set('/', root);
136
-
137
- for (const node of nodes) {
138
- const itemPath = (node.id as string).replace(rootPath ?? '', '');
139
- const pathParts = itemPath.split('/').filter(Boolean);
140
-
141
- let currentPath = '';
142
- let parentNode = root;
143
-
144
- for (const part of pathParts) {
145
- currentPath += '/' + part;
146
-
147
- if (!nodeMap.has(currentPath)) {
148
- const newNode: FileTreeNode = {
149
- id: node.id,
150
- isSelected: node.isSelected,
151
- parentPath: currentPath,
152
- resolvedpath: node.id?.startsWith('%') ? node.resolvedpath + '/' : currentPath,
153
- hidden: node.hidden,
154
- text: node.text,
155
- cls: node.cls,
156
- children: [],
157
- };
158
- nodeMap.set(currentPath, newNode);
159
- parentNode.children.push(newNode);
160
- }
161
-
162
- parentNode = nodeMap.get(currentPath)!;
163
- }
164
- }
165
-
166
- return [root];
167
- });
168
-
169
- pathDiscoveryMethodEffect = effect(
170
- () => {
171
- const disvoeryMethod = this.pathDiscoveryMethod();
172
- const input = this.#inputRef();
173
-
174
- if (disvoeryMethod === 'browse' && input) {
175
- if (this.multiSelect()) {
176
- const arr = input.value.split('\0');
177
- this.treeNodes.update((y) =>
178
- y.map((z) => ({ ...z, isSelected: typeof z.id === 'string' && arr.includes(z.id) }))
179
- );
180
- } else {
181
- this.treeNodes.update((y) => y.map((z) => ({ ...z, isSelected: z.id === input.value })));
182
- }
183
- }
184
- },
185
- {
186
- allowSignalWrites: true,
187
- }
188
- );
189
-
190
- #scrollToFirstSelectedNode() {
191
- const selectedNodes = this.treeContainerRef()?.nativeElement.querySelectorAll('.active');
192
-
193
- if (selectedNodes && selectedNodes.length > 0) {
194
- selectedNodes[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
195
- }
196
- }
197
-
198
- currentPathEffect = effect(
199
- () => {
200
- const input = this.#inputRef();
201
-
202
- if (input) {
203
- input.value = this.currentPath();
204
- input.dispatchEvent(new Event('input'));
205
- }
206
- },
207
- {
208
- allowSignalWrites: true,
209
- }
210
- );
211
-
212
- selectedPathsEffect = effect(
213
- () => {
214
- if (this.multiSelect()) {
215
- const selectedNodes = this.treeNodes().filter((node) => node.isSelected);
216
- const excludedNodes = this.treeNodes().filter(
217
- (node) => !node.isSelected && selectedNodes.some((selected) => node.id?.startsWith(selected.id as string))
218
- );
219
-
220
- const selectedMapped = selectedNodes
221
- .filter(
222
- (node) =>
223
- !selectedNodes.some(
224
- (otherNode) => node.id !== otherNode.id && node.id?.startsWith(otherNode.id as string)
225
- )
226
- )
227
- .map((node) => node.id as string);
228
-
229
- const excludedMapped = excludedNodes
230
- .filter(
231
- (node) =>
232
- !excludedNodes.some(
233
- (otherNode) => node.id !== otherNode.id && node.id?.startsWith(otherNode.id as string)
234
- )
235
- )
236
- .map((node) => `-${node.id as string}`);
237
-
238
- this.excludes.emit(excludedMapped);
239
-
240
- const newPath = [...selectedMapped, ...excludedMapped] as string[];
241
-
242
- this.currentPath.set(newPath.join('\0'));
243
- } else {
244
- const selectedNode = this.treeNodes().find((node) => node.isSelected);
245
-
246
- const resolvedPath = selectedNode?.resolvedpath as string;
247
-
248
- this.currentPath.set(selectedNode?.id ?? '');
249
- }
250
- },
251
- {
252
- allowSignalWrites: true,
253
- }
254
- );
255
-
256
- inputValueChangeAbortController: AbortController | null = null;
257
- inputRefEffect = effect(
258
- () => {
259
- const input = this.formRef()?.nativeElement?.querySelector('input');
260
-
261
- if (!input) return;
262
-
263
- this.#createCustomInputEventListener(input);
264
-
265
- if (this.inputValueChangeAbortController) {
266
- this.inputValueChangeAbortController.abort();
267
- }
268
-
269
- this.inputValueChangeAbortController = new AbortController();
270
-
271
- input.addEventListener(
272
- 'inputValueChanged',
273
- (event: InputValueChangedEvent) => {
274
- this.currentPath.set(event.detail.value);
275
- },
276
- { signal: this.inputValueChangeAbortController.signal }
277
- );
278
-
279
- this.#inputRef.set(input);
280
- input.autocomplete = 'off';
281
- },
282
- { allowSignalWrites: true }
283
- );
284
-
285
- ngOnInit() {
286
- const startingPath = this.startingPath();
287
-
288
- if (startingPath) {
289
- this.currentPath.set(startingPath);
290
- this.#fetchPathSegmentsRecursively(startingPath);
291
- } else {
292
- this.#getPath(null, this.rootPath());
293
- }
294
- }
295
-
296
- toggleSelectedNode($event: Event, node: FileTreeNode) {
297
- $event.stopPropagation();
298
-
299
- if (this.multiSelect()) {
300
- this.treeNodes.update((y) =>
301
- y.map((z) => {
302
- if (z.id?.startsWith(node.id as string)) {
303
- return { ...z, isSelected: !node.isSelected };
304
- }
305
- return z;
306
- })
307
- );
308
- } else {
309
- this.treeNodes.update((y) =>
310
- y.map((z) => {
311
- if (z.id === (node.id as string)) {
312
- return { ...z, isSelected: !node.isSelected };
313
- } else {
314
- return { ...z, isSelected: false };
315
- }
316
- })
317
- );
318
- }
319
- }
320
-
321
- toggleNode($event: Event, path: string, node: FileTreeNode | null = null) {
322
- $event.stopPropagation();
323
-
324
- if (node?.children.length) {
325
- this.treeNodes.update((y) => y.filter((z) => !z.id?.startsWith(node.id as string) || z.id === node.id));
326
- } else {
327
- this.#getPath(node, path);
328
- }
329
- }
330
-
331
- #createCustomInputEventListener(input: HTMLInputElement) {
332
- Object.defineProperty(input, 'value', {
333
- configurable: true,
334
- get() {
335
- return Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.get!.call(this);
336
- },
337
- set(newVal) {
338
- Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set!.call(this, newVal);
339
-
340
- this.dispatchEvent(
341
- new CustomEvent('inputValueChanged', {
342
- bubbles: true,
343
- cancelable: true,
344
- detail: {
345
- value: newVal,
346
- },
347
- })
348
- );
349
-
350
- return newVal;
351
- },
352
- });
353
-
354
- return input;
355
- }
356
-
357
- #getFilesystemPath(path: string) {
358
- return this.#dupServer.postApiV1Filesystem({
359
- showHidden: true,
360
- requestBody: {
361
- path,
362
- },
363
- onlyFolders: !this.showFiles(),
364
- });
365
- }
366
-
367
- #getBackupFiles(path: string | null) {
368
- const backupSettings = this.backupSettings()!;
369
- const params: GetApiV1BackupByIdFilesData = {
370
- id: backupSettings.id,
371
- time: backupSettings.time,
372
- prefixOnly: false,
373
- folderContents: true,
374
- };
375
-
376
- if (path) {
377
- params.filter = '@' + path;
378
- }
379
-
380
- return this.#dupServer.getApiV1BackupByIdFiles(params);
381
- }
382
-
383
- #getFilePath(path: string) {
384
- return this.isByBackupSettings() ? this.#getBackupFiles(path) : this.#getFilesystemPath(path);
385
- }
386
-
387
- #fetchPathSegmentsRecursively(path: string) {
388
- const deselectedPaths = path
389
- .split('\0')
390
- .filter((x) => x.startsWith('-'))
391
- .map((x) => x.slice(1, -1));
392
-
393
- const pathArr = path
394
- .split('\0')
395
- .filter((x) => !x.startsWith('-'))
396
- .filter(Boolean);
397
- const segmentArr = pathArr.map((x) => x.split('/').filter(Boolean));
398
-
399
- let urlPieces: string[] = [this.rootPath() ?? '/'];
400
-
401
- segmentArr.forEach((segments) => {
402
- segments.forEach((_, index) => {
403
- const urlPiece = '/' + segments.slice(0, index + 1).join('/');
404
- if (!urlPieces.includes(urlPiece)) {
405
- urlPieces.push(urlPiece);
406
- }
407
- });
408
- });
409
-
410
- this.isLoading.set(true);
411
-
412
- forkJoin([...urlPieces.map((urlPiece) => this.#getFilePath(urlPiece === '/' ? urlPiece : urlPiece))])
413
- .pipe(finalize(() => this.isLoading.set(false)))
414
- .subscribe({
415
- next: (results) => {
416
- this.treeNodes.update((y) => {
417
- const allNewNodes = results.flatMap((x) => {
418
- return (x as any).map((z: any) => {
419
- const path = z.id;
420
- const parentPath = path && path.split('/').filter(Boolean).slice(0, -1).join('/');
421
- const _pathWithoutTrailingSlash = path && path.split('/').filter(Boolean).join('/');
422
- const pathWithoutTrailingSlash = '/' + _pathWithoutTrailingSlash;
423
- const found =
424
- pathArr.findIndex((x) => {
425
- return this.multiSelect() ? pathWithoutTrailingSlash.startsWith(x) : pathWithoutTrailingSlash === x;
426
- }) > -1;
427
-
428
- const hi = pathArr.findIndex((x) => x === path) > -1;
429
- const isDeselected = deselectedPaths.findIndex((x) => x === pathWithoutTrailingSlash) > -1;
430
-
431
- return {
432
- ...z,
433
- parentPath: parentPath.startsWith('%') ? parentPath : '/' + parentPath,
434
- isSelected: (found && !isDeselected) || hi, // TODO - Use deselected paths to disable
435
- };
436
- });
437
- });
438
-
439
- const arrayUniqueByKey = [
440
- ...new Map([...y, ...allNewNodes].map((item) => [item.resolvedpath ?? item.id, item])).values(),
441
- ];
442
-
443
- return arrayUniqueByKey as TreeNode[];
444
- });
445
- },
446
- });
447
- }
448
-
449
- #getPath(node: FileTreeNode | null = null, newPath = '/') {
450
- this.isLoading.set(true);
451
-
452
- (this.#getFilePath(newPath) as Observable<any>).pipe(finalize(() => this.isLoading.set(false))).subscribe({
453
- next: (x) => {
454
- const alignDataArray = this.isByBackupSettings()
455
- ? x['Files'].map((y: { Path: string; Size: any }) => {
456
- return {
457
- text: y.Path.split('/')
458
- .filter((part) => part !== '')
459
- .pop(),
460
- id: y.Path,
461
- cls: y.Path.endsWith('/') ? 'folder' : 'file',
462
- leaf: node !== null,
463
- resolvedpath: y.Path,
464
- hidden: false,
465
- };
466
- })
467
- : x;
468
-
469
- this.treeNodes.update((y) => {
470
- const newArray = alignDataArray.map((z: any) => ({
471
- ...z,
472
- parentPath: newPath,
473
- isSelected: (this.multiSelect() && node?.isSelected) ?? false,
474
- }));
475
-
476
- const arrayUniqueByKey = [
477
- ...new Map([...y, ...newArray].map((item) => [item.resolvedpath ?? item.id, item])).values(),
478
- ];
479
-
480
- return arrayUniqueByKey as TreeNode[];
481
- });
482
- },
483
- });
484
- }
485
- }