@memberjunction/ng-file-storage 3.1.0 → 3.2.0

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 (34) hide show
  1. package/dist/lib/file-browser/file-browser-demo.component.d.ts +10 -0
  2. package/dist/lib/file-browser/file-browser-demo.component.d.ts.map +1 -0
  3. package/dist/lib/file-browser/file-browser-demo.component.js +39 -0
  4. package/dist/lib/file-browser/file-browser-demo.component.js.map +1 -0
  5. package/dist/lib/file-browser/file-browser-resource.component.d.ts +30 -0
  6. package/dist/lib/file-browser/file-browser-resource.component.d.ts.map +1 -0
  7. package/dist/lib/file-browser/file-browser-resource.component.js +82 -0
  8. package/dist/lib/file-browser/file-browser-resource.component.js.map +1 -0
  9. package/dist/lib/file-browser/file-browser.component.d.ts +69 -0
  10. package/dist/lib/file-browser/file-browser.component.d.ts.map +1 -0
  11. package/dist/lib/file-browser/file-browser.component.js +132 -0
  12. package/dist/lib/file-browser/file-browser.component.js.map +1 -0
  13. package/dist/lib/file-browser/file-grid.component.d.ts +429 -0
  14. package/dist/lib/file-browser/file-grid.component.d.ts.map +1 -0
  15. package/dist/lib/file-browser/file-grid.component.js +2394 -0
  16. package/dist/lib/file-browser/file-grid.component.js.map +1 -0
  17. package/dist/lib/file-browser/folder-tree.component.d.ts +115 -0
  18. package/dist/lib/file-browser/folder-tree.component.d.ts.map +1 -0
  19. package/dist/lib/file-browser/folder-tree.component.js +364 -0
  20. package/dist/lib/file-browser/folder-tree.component.js.map +1 -0
  21. package/dist/lib/file-browser/storage-providers-list.component.d.ts +59 -0
  22. package/dist/lib/file-browser/storage-providers-list.component.d.ts.map +1 -0
  23. package/dist/lib/file-browser/storage-providers-list.component.js +235 -0
  24. package/dist/lib/file-browser/storage-providers-list.component.js.map +1 -0
  25. package/dist/lib/file-upload/file-upload.d.ts +19 -19
  26. package/dist/lib/module.d.ts +25 -18
  27. package/dist/lib/module.d.ts.map +1 -1
  28. package/dist/lib/module.js +44 -4
  29. package/dist/lib/module.js.map +1 -1
  30. package/dist/public-api.d.ts +3 -0
  31. package/dist/public-api.d.ts.map +1 -1
  32. package/dist/public-api.js +6 -0
  33. package/dist/public-api.js.map +1 -1
  34. package/package.json +9 -8
@@ -0,0 +1,2394 @@
1
+ import { Component, Input, Output, EventEmitter } from '@angular/core';
2
+ import { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';
3
+ import { FileStorageEngine } from '@memberjunction/core-entities';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ import * as i2 from "@angular/forms";
7
+ import * as i3 from "@memberjunction/ng-shared-generic";
8
+ import * as i4 from "@progress/kendo-angular-label";
9
+ function FileGridComponent_div_1_button_12_Template(rf, ctx) { if (rf & 1) {
10
+ const _r3 = i0.ɵɵgetCurrentView();
11
+ i0.ɵɵelementStart(0, "button", 30);
12
+ i0.ɵɵlistener("click", function FileGridComponent_div_1_button_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.clearSearch()); });
13
+ i0.ɵɵelement(1, "i", 31);
14
+ i0.ɵɵelementEnd();
15
+ } }
16
+ function FileGridComponent_div_1_Template(rf, ctx) { if (rf & 1) {
17
+ const _r1 = i0.ɵɵgetCurrentView();
18
+ i0.ɵɵelementStart(0, "div", 12)(1, "div", 13)(2, "button", 14);
19
+ i0.ɵɵlistener("click", function FileGridComponent_div_1_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.navigateUp()); });
20
+ i0.ɵɵelement(3, "i", 15);
21
+ i0.ɵɵelementEnd();
22
+ i0.ɵɵelementStart(4, "button", 16);
23
+ i0.ɵɵlistener("click", function FileGridComponent_div_1_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.refresh()); });
24
+ i0.ɵɵelement(5, "i", 17);
25
+ i0.ɵɵelementEnd()();
26
+ i0.ɵɵelementStart(6, "div", 18);
27
+ i0.ɵɵelement(7, "i", 19);
28
+ i0.ɵɵelementStart(8, "span", 20);
29
+ i0.ɵɵtext(9);
30
+ i0.ɵɵelementEnd()();
31
+ i0.ɵɵelementStart(10, "div", 21)(11, "input", 22);
32
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_1_Template_input_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.searchQuery, $event) || (ctx_r1.searchQuery = $event); return i0.ɵɵresetView($event); });
33
+ i0.ɵɵlistener("ngModelChange", function FileGridComponent_div_1_Template_input_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSearchChange($event)); });
34
+ i0.ɵɵelementEnd();
35
+ i0.ɵɵtemplate(12, FileGridComponent_div_1_button_12_Template, 2, 0, "button", 23);
36
+ i0.ɵɵelementStart(13, "select", 24);
37
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_1_Template_select_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.fileTypeFilter, $event) || (ctx_r1.fileTypeFilter = $event); return i0.ɵɵresetView($event); });
38
+ i0.ɵɵlistener("ngModelChange", function FileGridComponent_div_1_Template_select_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onFileTypeFilterChange($event)); });
39
+ i0.ɵɵelementStart(14, "option", 25);
40
+ i0.ɵɵtext(15, "All");
41
+ i0.ɵɵelementEnd();
42
+ i0.ɵɵelementStart(16, "option", 26);
43
+ i0.ɵɵtext(17, "Files");
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(18, "option", 27);
46
+ i0.ɵɵtext(19, "Folders");
47
+ i0.ɵɵelementEnd()();
48
+ i0.ɵɵelementStart(20, "button", 28);
49
+ i0.ɵɵlistener("click", function FileGridComponent_div_1_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleMultiAccountSearchMode()); });
50
+ i0.ɵɵelement(21, "i", 29);
51
+ i0.ɵɵelementEnd()()();
52
+ } if (rf & 2) {
53
+ const ctx_r1 = i0.ɵɵnextContext();
54
+ i0.ɵɵadvance(2);
55
+ i0.ɵɵproperty("disabled", !ctx_r1.canNavigateUp());
56
+ i0.ɵɵadvance(7);
57
+ i0.ɵɵtextInterpolate1("", ctx_r1.folderPath || "Root", " /");
58
+ i0.ɵɵadvance(2);
59
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.searchQuery);
60
+ i0.ɵɵproperty("disabled", ctx_r1.isLoading || ctx_r1.isMultiProviderSearchMode);
61
+ i0.ɵɵadvance();
62
+ i0.ɵɵproperty("ngIf", ctx_r1.searchQuery && !ctx_r1.isMultiProviderSearchMode);
63
+ i0.ɵɵadvance();
64
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.fileTypeFilter);
65
+ i0.ɵɵproperty("disabled", ctx_r1.isLoading || ctx_r1.isMultiProviderSearchMode);
66
+ i0.ɵɵadvance(7);
67
+ i0.ɵɵclassProp("active", ctx_r1.isMultiProviderSearchMode);
68
+ } }
69
+ function FileGridComponent_div_2_i_11_Template(rf, ctx) { if (rf & 1) {
70
+ i0.ɵɵelement(0, "i", 48);
71
+ } }
72
+ function FileGridComponent_div_2_i_12_Template(rf, ctx) { if (rf & 1) {
73
+ i0.ɵɵelement(0, "i", 49);
74
+ } }
75
+ function FileGridComponent_div_2_label_18_span_6_Template(rf, ctx) { if (rf & 1) {
76
+ i0.ɵɵelementStart(0, "span", 55);
77
+ i0.ɵɵtext(1, "(no search)");
78
+ i0.ɵɵelementEnd();
79
+ } }
80
+ function FileGridComponent_div_2_label_18_Template(rf, ctx) { if (rf & 1) {
81
+ const _r5 = i0.ɵɵgetCurrentView();
82
+ i0.ɵɵelementStart(0, "label", 50)(1, "input", 51);
83
+ i0.ɵɵlistener("change", function FileGridComponent_div_2_label_18_Template_input_change_1_listener() { const a_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleSearchAccount(a_r6.account.ID)); });
84
+ i0.ɵɵelementEnd();
85
+ i0.ɵɵelementStart(2, "span", 52);
86
+ i0.ɵɵtext(3);
87
+ i0.ɵɵelementEnd();
88
+ i0.ɵɵelementStart(4, "span", 53);
89
+ i0.ɵɵtext(5);
90
+ i0.ɵɵelementEnd();
91
+ i0.ɵɵtemplate(6, FileGridComponent_div_2_label_18_span_6_Template, 2, 0, "span", 54);
92
+ i0.ɵɵelementEnd();
93
+ } if (rf & 2) {
94
+ const a_r6 = ctx.$implicit;
95
+ const ctx_r1 = i0.ɵɵnextContext(2);
96
+ i0.ɵɵclassProp("disabled", !ctx_r1.accountSupportsSearch(a_r6));
97
+ i0.ɵɵproperty("title", ctx_r1.accountSupportsSearch(a_r6) ? "" : "This account does not support search");
98
+ i0.ɵɵadvance();
99
+ i0.ɵɵproperty("checked", ctx_r1.isAccountSelectedForSearch(a_r6.account.ID))("disabled", !ctx_r1.accountSupportsSearch(a_r6));
100
+ i0.ɵɵadvance(2);
101
+ i0.ɵɵtextInterpolate(a_r6.account.Name);
102
+ i0.ɵɵadvance(2);
103
+ i0.ɵɵtextInterpolate1("(", a_r6.provider.Name, ")");
104
+ i0.ɵɵadvance();
105
+ i0.ɵɵproperty("ngIf", !ctx_r1.accountSupportsSearch(a_r6));
106
+ } }
107
+ function FileGridComponent_div_2_div_19_span_6_Template(rf, ctx) { if (rf & 1) {
108
+ i0.ɵɵelementStart(0, "span", 64);
109
+ i0.ɵɵtext(1);
110
+ i0.ɵɵelementEnd();
111
+ } if (rf & 2) {
112
+ const ctx_r1 = i0.ɵɵnextContext(3);
113
+ i0.ɵɵadvance();
114
+ i0.ɵɵtextInterpolate1(" , ", ctx_r1.multiProviderSearchResults.failedAccounts, " failed ");
115
+ } }
116
+ function FileGridComponent_div_2_div_19_div_12_span_5_Template(rf, ctx) { if (rf & 1) {
117
+ i0.ɵɵelementStart(0, "span", 58);
118
+ i0.ɵɵtext(1);
119
+ i0.ɵɵelementEnd();
120
+ } if (rf & 2) {
121
+ const accountResult_r8 = i0.ɵɵnextContext().$implicit;
122
+ i0.ɵɵadvance();
123
+ i0.ɵɵtextInterpolate1(" (", accountResult_r8.results.length, " result(s)) ");
124
+ } }
125
+ function FileGridComponent_div_2_div_19_div_12_span_6_Template(rf, ctx) { if (rf & 1) {
126
+ i0.ɵɵelementStart(0, "span", 72);
127
+ i0.ɵɵelement(1, "i", 73);
128
+ i0.ɵɵtext(2);
129
+ i0.ɵɵelementEnd();
130
+ } if (rf & 2) {
131
+ const accountResult_r8 = i0.ɵɵnextContext().$implicit;
132
+ i0.ɵɵadvance(2);
133
+ i0.ɵɵtextInterpolate1(" ", accountResult_r8.errorMessage, " ");
134
+ } }
135
+ function FileGridComponent_div_2_div_19_div_12_div_7_div_1_Template(rf, ctx) { if (rf & 1) {
136
+ i0.ɵɵelementStart(0, "div", 76);
137
+ i0.ɵɵelement(1, "i", 77);
138
+ i0.ɵɵelementStart(2, "div", 78)(3, "span", 79);
139
+ i0.ɵɵtext(4);
140
+ i0.ɵɵelementEnd();
141
+ i0.ɵɵelementStart(5, "span", 80);
142
+ i0.ɵɵtext(6);
143
+ i0.ɵɵelementEnd()();
144
+ i0.ɵɵelementStart(7, "span", 81);
145
+ i0.ɵɵtext(8);
146
+ i0.ɵɵelementEnd();
147
+ i0.ɵɵelementStart(9, "span", 82);
148
+ i0.ɵɵtext(10);
149
+ i0.ɵɵelementEnd()();
150
+ } if (rf & 2) {
151
+ const file_r9 = ctx.$implicit;
152
+ const ctx_r1 = i0.ɵɵnextContext(5);
153
+ i0.ɵɵadvance();
154
+ i0.ɵɵclassMap(ctx_r1.getSearchResultIcon(file_r9));
155
+ i0.ɵɵadvance(3);
156
+ i0.ɵɵtextInterpolate(file_r9.name);
157
+ i0.ɵɵadvance(2);
158
+ i0.ɵɵtextInterpolate(file_r9.path);
159
+ i0.ɵɵadvance(2);
160
+ i0.ɵɵtextInterpolate(ctx_r1.formatSearchResultSize(file_r9.size));
161
+ i0.ɵɵadvance(2);
162
+ i0.ɵɵtextInterpolate(ctx_r1.formatSearchResultDate(file_r9.lastModified));
163
+ } }
164
+ function FileGridComponent_div_2_div_19_div_12_div_7_Template(rf, ctx) { if (rf & 1) {
165
+ i0.ɵɵelementStart(0, "div", 74);
166
+ i0.ɵɵtemplate(1, FileGridComponent_div_2_div_19_div_12_div_7_div_1_Template, 11, 6, "div", 75);
167
+ i0.ɵɵelementEnd();
168
+ } if (rf & 2) {
169
+ const accountResult_r8 = i0.ɵɵnextContext().$implicit;
170
+ i0.ɵɵadvance();
171
+ i0.ɵɵproperty("ngForOf", accountResult_r8.results);
172
+ } }
173
+ function FileGridComponent_div_2_div_19_div_12_div_8_Template(rf, ctx) { if (rf & 1) {
174
+ i0.ɵɵelementStart(0, "div", 83);
175
+ i0.ɵɵtext(1, " No matching files found ");
176
+ i0.ɵɵelementEnd();
177
+ } }
178
+ function FileGridComponent_div_2_div_19_div_12_Template(rf, ctx) { if (rf & 1) {
179
+ i0.ɵɵelementStart(0, "div", 65)(1, "div", 66);
180
+ i0.ɵɵelement(2, "i", 67);
181
+ i0.ɵɵelementStart(3, "span", 52);
182
+ i0.ɵɵtext(4);
183
+ i0.ɵɵelementEnd();
184
+ i0.ɵɵtemplate(5, FileGridComponent_div_2_div_19_div_12_span_5_Template, 2, 1, "span", 68)(6, FileGridComponent_div_2_div_19_div_12_span_6_Template, 3, 1, "span", 69);
185
+ i0.ɵɵelementEnd();
186
+ i0.ɵɵtemplate(7, FileGridComponent_div_2_div_19_div_12_div_7_Template, 2, 1, "div", 70)(8, FileGridComponent_div_2_div_19_div_12_div_8_Template, 2, 0, "div", 71);
187
+ i0.ɵɵelementEnd();
188
+ } if (rf & 2) {
189
+ const accountResult_r8 = ctx.$implicit;
190
+ i0.ɵɵclassProp("failed", !accountResult_r8.success);
191
+ i0.ɵɵadvance(4);
192
+ i0.ɵɵtextInterpolate(accountResult_r8.accountName);
193
+ i0.ɵɵadvance();
194
+ i0.ɵɵproperty("ngIf", accountResult_r8.success);
195
+ i0.ɵɵadvance();
196
+ i0.ɵɵproperty("ngIf", !accountResult_r8.success);
197
+ i0.ɵɵadvance();
198
+ i0.ɵɵproperty("ngIf", accountResult_r8.success && accountResult_r8.results.length > 0);
199
+ i0.ɵɵadvance();
200
+ i0.ɵɵproperty("ngIf", accountResult_r8.success && accountResult_r8.results.length === 0);
201
+ } }
202
+ function FileGridComponent_div_2_div_19_Template(rf, ctx) { if (rf & 1) {
203
+ const _r7 = i0.ɵɵgetCurrentView();
204
+ i0.ɵɵelementStart(0, "div", 56)(1, "div", 57)(2, "span", 58);
205
+ i0.ɵɵtext(3);
206
+ i0.ɵɵelementEnd();
207
+ i0.ɵɵelementStart(4, "span", 59);
208
+ i0.ɵɵtext(5);
209
+ i0.ɵɵtemplate(6, FileGridComponent_div_2_div_19_span_6_Template, 2, 1, "span", 60);
210
+ i0.ɵɵtext(7, ") ");
211
+ i0.ɵɵelementEnd();
212
+ i0.ɵɵelementStart(8, "button", 61);
213
+ i0.ɵɵlistener("click", function FileGridComponent_div_2_div_19_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.clearMultiProviderSearch()); });
214
+ i0.ɵɵelement(9, "i", 31);
215
+ i0.ɵɵtext(10, " Clear ");
216
+ i0.ɵɵelementEnd()();
217
+ i0.ɵɵelementStart(11, "div", 62);
218
+ i0.ɵɵtemplate(12, FileGridComponent_div_2_div_19_div_12_Template, 9, 7, "div", 63);
219
+ i0.ɵɵelementEnd()();
220
+ } if (rf & 2) {
221
+ const ctx_r1 = i0.ɵɵnextContext(2);
222
+ i0.ɵɵadvance(3);
223
+ i0.ɵɵtextInterpolate1("", ctx_r1.multiProviderSearchResults.totalResultsReturned, " result(s) found");
224
+ i0.ɵɵadvance(2);
225
+ i0.ɵɵtextInterpolate1(" (", ctx_r1.multiProviderSearchResults.successfulAccounts, " account(s) searched ");
226
+ i0.ɵɵadvance();
227
+ i0.ɵɵproperty("ngIf", ctx_r1.multiProviderSearchResults.failedAccounts > 0);
228
+ i0.ɵɵadvance(6);
229
+ i0.ɵɵproperty("ngForOf", ctx_r1.multiProviderSearchResults.accountResults);
230
+ } }
231
+ function FileGridComponent_div_2_div_20_Template(rf, ctx) { if (rf & 1) {
232
+ i0.ɵɵelementStart(0, "div", 84);
233
+ i0.ɵɵelement(1, "mj-loading", 85);
234
+ i0.ɵɵelementEnd();
235
+ } }
236
+ function FileGridComponent_div_2_Template(rf, ctx) { if (rf & 1) {
237
+ const _r4 = i0.ɵɵgetCurrentView();
238
+ i0.ɵɵelementStart(0, "div", 32)(1, "div", 33)(2, "h3");
239
+ i0.ɵɵelement(3, "i", 34);
240
+ i0.ɵɵtext(4, " Search Across Providers");
241
+ i0.ɵɵelementEnd();
242
+ i0.ɵɵelementStart(5, "button", 35);
243
+ i0.ɵɵlistener("click", function FileGridComponent_div_2_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleMultiAccountSearchMode()); });
244
+ i0.ɵɵelement(6, "i", 31);
245
+ i0.ɵɵelementEnd()();
246
+ i0.ɵɵelementStart(7, "div", 36)(8, "div", 37)(9, "input", 38);
247
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_2_Template_input_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.multiProviderSearchQuery, $event) || (ctx_r1.multiProviderSearchQuery = $event); return i0.ɵɵresetView($event); });
248
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_2_Template_input_keydown_enter_9_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.executeMultiAccountSearch()); });
249
+ i0.ɵɵelementEnd();
250
+ i0.ɵɵelementStart(10, "button", 39);
251
+ i0.ɵɵlistener("click", function FileGridComponent_div_2_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.executeMultiAccountSearch()); });
252
+ i0.ɵɵtemplate(11, FileGridComponent_div_2_i_11_Template, 1, 0, "i", 40)(12, FileGridComponent_div_2_i_12_Template, 1, 0, "i", 41);
253
+ i0.ɵɵtext(13);
254
+ i0.ɵɵelementEnd()();
255
+ i0.ɵɵelementStart(14, "div", 42)(15, "label", 43);
256
+ i0.ɵɵtext(16, "Select accounts to search:");
257
+ i0.ɵɵelementEnd();
258
+ i0.ɵɵelementStart(17, "div", 44);
259
+ i0.ɵɵtemplate(18, FileGridComponent_div_2_label_18_Template, 7, 8, "label", 45);
260
+ i0.ɵɵelementEnd()()();
261
+ i0.ɵɵtemplate(19, FileGridComponent_div_2_div_19_Template, 13, 4, "div", 46)(20, FileGridComponent_div_2_div_20_Template, 2, 0, "div", 47);
262
+ i0.ɵɵelementEnd();
263
+ } if (rf & 2) {
264
+ const ctx_r1 = i0.ɵɵnextContext();
265
+ i0.ɵɵadvance(9);
266
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.multiProviderSearchQuery);
267
+ i0.ɵɵproperty("disabled", ctx_r1.isSearching);
268
+ i0.ɵɵadvance();
269
+ i0.ɵɵproperty("disabled", ctx_r1.isSearching || !ctx_r1.multiProviderSearchQuery.trim() || ctx_r1.selectedSearchProviders.size === 0);
270
+ i0.ɵɵadvance();
271
+ i0.ɵɵproperty("ngIf", ctx_r1.isSearching);
272
+ i0.ɵɵadvance();
273
+ i0.ɵɵproperty("ngIf", !ctx_r1.isSearching);
274
+ i0.ɵɵadvance();
275
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isSearching ? "Searching..." : "Search", " ");
276
+ i0.ɵɵadvance(5);
277
+ i0.ɵɵproperty("ngForOf", ctx_r1.availableAccounts);
278
+ i0.ɵɵadvance();
279
+ i0.ɵɵproperty("ngIf", ctx_r1.multiProviderSearchResults);
280
+ i0.ɵɵadvance();
281
+ i0.ɵɵproperty("ngIf", ctx_r1.isSearching);
282
+ } }
283
+ function FileGridComponent_div_3_Template(rf, ctx) { if (rf & 1) {
284
+ i0.ɵɵelementStart(0, "div", 86);
285
+ i0.ɵɵelement(1, "mj-loading", 87);
286
+ i0.ɵɵelementEnd();
287
+ } }
288
+ function FileGridComponent_div_4_Template(rf, ctx) { if (rf & 1) {
289
+ const _r10 = i0.ɵɵgetCurrentView();
290
+ i0.ɵɵelementStart(0, "div", 88)(1, "div", 89);
291
+ i0.ɵɵelement(2, "i", 90);
292
+ i0.ɵɵelementEnd();
293
+ i0.ɵɵelementStart(3, "p", 91);
294
+ i0.ɵɵtext(4);
295
+ i0.ɵɵelementEnd();
296
+ i0.ɵɵelementStart(5, "button", 92);
297
+ i0.ɵɵlistener("click", function FileGridComponent_div_4_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.refresh()); });
298
+ i0.ɵɵelement(6, "i", 17);
299
+ i0.ɵɵtext(7, " Retry ");
300
+ i0.ɵɵelementEnd()();
301
+ } if (rf & 2) {
302
+ const ctx_r1 = i0.ɵɵnextContext();
303
+ i0.ɵɵadvance(4);
304
+ i0.ɵɵtextInterpolate(ctx_r1.errorMessage);
305
+ } }
306
+ function FileGridComponent_div_5_tr_19_Template(rf, ctx) { if (rf & 1) {
307
+ const _r12 = i0.ɵɵgetCurrentView();
308
+ i0.ɵɵelementStart(0, "tr", 101);
309
+ i0.ɵɵlistener("click", function FileGridComponent_div_5_tr_19_Template_tr_click_0_listener($event) { const item_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onTileClick(item_r13, $event)); })("dblclick", function FileGridComponent_div_5_tr_19_Template_tr_dblclick_0_listener() { const item_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onItemDoubleClick(item_r13)); });
310
+ i0.ɵɵelementStart(1, "td", 102);
311
+ i0.ɵɵelement(2, "i", 103);
312
+ i0.ɵɵelementStart(3, "span", 104);
313
+ i0.ɵɵtext(4);
314
+ i0.ɵɵelementEnd()();
315
+ i0.ɵɵelementStart(5, "td", 97)(6, "span", 105);
316
+ i0.ɵɵtext(7);
317
+ i0.ɵɵelementEnd()();
318
+ i0.ɵɵelementStart(8, "td", 106)(9, "span", 107);
319
+ i0.ɵɵtext(10);
320
+ i0.ɵɵelementEnd()();
321
+ i0.ɵɵelementStart(11, "td", 108)(12, "span", 109);
322
+ i0.ɵɵtext(13);
323
+ i0.ɵɵelementEnd()()();
324
+ } if (rf & 2) {
325
+ const item_r13 = ctx.$implicit;
326
+ const ctx_r1 = i0.ɵɵnextContext(2);
327
+ i0.ɵɵclassProp("selected", ctx_r1.selectedItems.includes(item_r13.key));
328
+ i0.ɵɵadvance(2);
329
+ i0.ɵɵclassMap(ctx_r1.getItemIcon(item_r13));
330
+ i0.ɵɵadvance(2);
331
+ i0.ɵɵtextInterpolate(item_r13.name);
332
+ i0.ɵɵadvance(3);
333
+ i0.ɵɵtextInterpolate(ctx_r1.getFileType(item_r13));
334
+ i0.ɵɵadvance(3);
335
+ i0.ɵɵtextInterpolate(item_r13.type === "folder" ? "\u2014" : ctx_r1.formatFileSize(item_r13.size));
336
+ i0.ɵɵadvance(3);
337
+ i0.ɵɵtextInterpolate(ctx_r1.formatDate(item_r13.lastModified));
338
+ } }
339
+ function FileGridComponent_div_5_Template(rf, ctx) { if (rf & 1) {
340
+ const _r11 = i0.ɵɵgetCurrentView();
341
+ i0.ɵɵelementStart(0, "div", 93)(1, "table", 94)(2, "thead")(3, "tr")(4, "th", 95);
342
+ i0.ɵɵlistener("click", function FileGridComponent_div_5_Template_th_click_4_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSortChange([{ field: "name", dir: (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "name" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc" ? "desc" : "asc" }])); });
343
+ i0.ɵɵelementStart(5, "span");
344
+ i0.ɵɵtext(6, "Name");
345
+ i0.ɵɵelementEnd();
346
+ i0.ɵɵelement(7, "i", 96);
347
+ i0.ɵɵelementEnd();
348
+ i0.ɵɵelementStart(8, "th", 97);
349
+ i0.ɵɵtext(9, "Type");
350
+ i0.ɵɵelementEnd();
351
+ i0.ɵɵelementStart(10, "th", 98);
352
+ i0.ɵɵlistener("click", function FileGridComponent_div_5_Template_th_click_10_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSortChange([{ field: "size", dir: (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "size" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc" ? "desc" : "asc" }])); });
353
+ i0.ɵɵelementStart(11, "span");
354
+ i0.ɵɵtext(12, "Size");
355
+ i0.ɵɵelementEnd();
356
+ i0.ɵɵelement(13, "i", 96);
357
+ i0.ɵɵelementEnd();
358
+ i0.ɵɵelementStart(14, "th", 99);
359
+ i0.ɵɵlistener("click", function FileGridComponent_div_5_Template_th_click_14_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSortChange([{ field: "lastModified", dir: (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "lastModified" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc" ? "desc" : "asc" }])); });
360
+ i0.ɵɵelementStart(15, "span");
361
+ i0.ɵɵtext(16, "Modified");
362
+ i0.ɵɵelementEnd();
363
+ i0.ɵɵelement(17, "i", 96);
364
+ i0.ɵɵelementEnd()()();
365
+ i0.ɵɵelementStart(18, "tbody");
366
+ i0.ɵɵtemplate(19, FileGridComponent_div_5_tr_19_Template, 14, 8, "tr", 100);
367
+ i0.ɵɵelementEnd()()();
368
+ } if (rf & 2) {
369
+ const ctx_r1 = i0.ɵɵnextContext();
370
+ i0.ɵɵadvance(7);
371
+ i0.ɵɵclassProp("fa-caret-up", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "name" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc")("fa-caret-down", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "name" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "desc")("fa-sort", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) !== "name");
372
+ i0.ɵɵadvance(6);
373
+ i0.ɵɵclassProp("fa-caret-up", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "size" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc")("fa-caret-down", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "size" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "desc")("fa-sort", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) !== "size");
374
+ i0.ɵɵadvance(4);
375
+ i0.ɵɵclassProp("fa-caret-up", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "lastModified" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "asc")("fa-caret-down", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) === "lastModified" && (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].dir) === "desc")("fa-sort", (ctx_r1.sort[0] == null ? null : ctx_r1.sort[0].field) !== "lastModified");
376
+ i0.ɵɵadvance(2);
377
+ i0.ɵɵproperty("ngForOf", ctx_r1.filteredItems);
378
+ } }
379
+ function FileGridComponent_div_6_div_2_div_5_Template(rf, ctx) { if (rf & 1) {
380
+ i0.ɵɵelementStart(0, "div", 117);
381
+ i0.ɵɵtext(1);
382
+ i0.ɵɵelementEnd();
383
+ } if (rf & 2) {
384
+ const item_r15 = i0.ɵɵnextContext().$implicit;
385
+ const ctx_r1 = i0.ɵɵnextContext(2);
386
+ i0.ɵɵadvance();
387
+ i0.ɵɵtextInterpolate(ctx_r1.formatFileSize(item_r15.size));
388
+ } }
389
+ function FileGridComponent_div_6_div_2_div_6_Template(rf, ctx) { if (rf & 1) {
390
+ i0.ɵɵelementStart(0, "div", 117);
391
+ i0.ɵɵtext(1, "Folder");
392
+ i0.ɵɵelementEnd();
393
+ } }
394
+ function FileGridComponent_div_6_div_2_Template(rf, ctx) { if (rf & 1) {
395
+ const _r14 = i0.ɵɵgetCurrentView();
396
+ i0.ɵɵelementStart(0, "div", 113);
397
+ i0.ɵɵlistener("click", function FileGridComponent_div_6_div_2_Template_div_click_0_listener($event) { const item_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onTileClick(item_r15, $event)); })("dblclick", function FileGridComponent_div_6_div_2_Template_div_dblclick_0_listener() { const item_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onItemDoubleClick(item_r15)); });
398
+ i0.ɵɵelementStart(1, "div", 114);
399
+ i0.ɵɵelement(2, "i");
400
+ i0.ɵɵelementEnd();
401
+ i0.ɵɵelementStart(3, "div", 115);
402
+ i0.ɵɵtext(4);
403
+ i0.ɵɵelementEnd();
404
+ i0.ɵɵtemplate(5, FileGridComponent_div_6_div_2_div_5_Template, 2, 1, "div", 116)(6, FileGridComponent_div_6_div_2_div_6_Template, 2, 0, "div", 116);
405
+ i0.ɵɵelementEnd();
406
+ } if (rf & 2) {
407
+ const item_r15 = ctx.$implicit;
408
+ const ctx_r1 = i0.ɵɵnextContext(2);
409
+ i0.ɵɵclassProp("selected", ctx_r1.selectedItems.includes(item_r15.key));
410
+ i0.ɵɵadvance(2);
411
+ i0.ɵɵclassMap(ctx_r1.getItemIcon(item_r15));
412
+ i0.ɵɵadvance(2);
413
+ i0.ɵɵtextInterpolate(item_r15.name);
414
+ i0.ɵɵadvance();
415
+ i0.ɵɵproperty("ngIf", item_r15.type === "file");
416
+ i0.ɵɵadvance();
417
+ i0.ɵɵproperty("ngIf", item_r15.type === "folder");
418
+ } }
419
+ function FileGridComponent_div_6_Template(rf, ctx) { if (rf & 1) {
420
+ i0.ɵɵelementStart(0, "div", 110)(1, "div", 111);
421
+ i0.ɵɵtemplate(2, FileGridComponent_div_6_div_2_Template, 7, 7, "div", 112);
422
+ i0.ɵɵelementEnd()();
423
+ } if (rf & 2) {
424
+ const ctx_r1 = i0.ɵɵnextContext();
425
+ i0.ɵɵadvance(2);
426
+ i0.ɵɵproperty("ngForOf", ctx_r1.filteredItems);
427
+ } }
428
+ function FileGridComponent_div_7_Template(rf, ctx) { if (rf & 1) {
429
+ const _r16 = i0.ɵɵgetCurrentView();
430
+ i0.ɵɵelementStart(0, "div", 118)(1, "div", 119);
431
+ i0.ɵɵelement(2, "i", 120);
432
+ i0.ɵɵelementEnd();
433
+ i0.ɵɵelementStart(3, "p", 121);
434
+ i0.ɵɵtext(4, "This folder is empty");
435
+ i0.ɵɵelementEnd();
436
+ i0.ɵɵelementStart(5, "button", 122);
437
+ i0.ɵɵlistener("click", function FileGridComponent_div_7_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadClick()); });
438
+ i0.ɵɵelement(6, "i", 123);
439
+ i0.ɵɵtext(7, " Upload Files ");
440
+ i0.ɵɵelementEnd()();
441
+ } }
442
+ function FileGridComponent_div_8_Template(rf, ctx) { if (rf & 1) {
443
+ const _r17 = i0.ɵɵgetCurrentView();
444
+ i0.ɵɵelementStart(0, "div", 124)(1, "div", 125)(2, "button", 126);
445
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onUploadClick()); });
446
+ i0.ɵɵelement(3, "i", 123);
447
+ i0.ɵɵtext(4, " Upload ");
448
+ i0.ɵɵelementEnd();
449
+ i0.ɵɵelementStart(5, "button", 126);
450
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onNewFolderClick()); });
451
+ i0.ɵɵelement(6, "i", 127);
452
+ i0.ɵɵtext(7, " New Folder ");
453
+ i0.ɵɵelementEnd();
454
+ i0.ɵɵelementStart(8, "button", 128);
455
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDownloadClick()); });
456
+ i0.ɵɵelement(9, "i", 129);
457
+ i0.ɵɵtext(10, " Download ");
458
+ i0.ɵɵelementEnd();
459
+ i0.ɵɵelementStart(11, "button", 128);
460
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRenameClick()); });
461
+ i0.ɵɵelement(12, "i", 130);
462
+ i0.ɵɵtext(13, " Rename ");
463
+ i0.ɵɵelementEnd();
464
+ i0.ɵɵelementStart(14, "button", 128);
465
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCopyClick()); });
466
+ i0.ɵɵelement(15, "i", 131);
467
+ i0.ɵɵtext(16, " Copy ");
468
+ i0.ɵɵelementEnd();
469
+ i0.ɵɵelementStart(17, "button", 132);
470
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCopyToAccountClick()); });
471
+ i0.ɵɵelement(18, "i", 133);
472
+ i0.ɵɵtext(19, " Copy to... ");
473
+ i0.ɵɵelementEnd();
474
+ i0.ɵɵelementStart(20, "button", 128);
475
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onMoveClick()); });
476
+ i0.ɵɵelement(21, "i", 134);
477
+ i0.ɵɵtext(22, " Move ");
478
+ i0.ɵɵelementEnd();
479
+ i0.ɵɵelementStart(23, "button", 128);
480
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDeleteClick()); });
481
+ i0.ɵɵelement(24, "i", 135);
482
+ i0.ɵɵtext(25, " Delete ");
483
+ i0.ɵɵelementEnd()();
484
+ i0.ɵɵelementStart(26, "div", 136)(27, "div", 137)(28, "button", 138);
485
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.viewMode = "list"); });
486
+ i0.ɵɵelement(29, "i", 139);
487
+ i0.ɵɵelementEnd();
488
+ i0.ɵɵelementStart(30, "button", 140);
489
+ i0.ɵɵlistener("click", function FileGridComponent_div_8_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.viewMode = "grid"); });
490
+ i0.ɵɵelement(31, "i", 141);
491
+ i0.ɵɵelementEnd()();
492
+ i0.ɵɵelementStart(32, "span", 142);
493
+ i0.ɵɵtext(33);
494
+ i0.ɵɵelementEnd()()();
495
+ } if (rf & 2) {
496
+ let tmp_4_0;
497
+ const ctx_r1 = i0.ɵɵnextContext();
498
+ i0.ɵɵadvance(8);
499
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length !== 1);
500
+ i0.ɵɵadvance(3);
501
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length !== 1);
502
+ i0.ɵɵadvance(3);
503
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length !== 1);
504
+ i0.ɵɵadvance(3);
505
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length !== 1 || ((tmp_4_0 = ctx_r1.getSelectedItem()) == null ? null : tmp_4_0.type) === "folder");
506
+ i0.ɵɵadvance(3);
507
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length !== 1);
508
+ i0.ɵɵadvance(3);
509
+ i0.ɵɵproperty("disabled", ctx_r1.selectedItems.length === 0);
510
+ i0.ɵɵadvance(5);
511
+ i0.ɵɵclassProp("active", ctx_r1.viewMode === "list");
512
+ i0.ɵɵadvance(2);
513
+ i0.ɵɵclassProp("active", ctx_r1.viewMode === "grid");
514
+ i0.ɵɵadvance(3);
515
+ i0.ɵɵtextInterpolate2(" ", ctx_r1.filteredItems.length, " ", ctx_r1.filteredItems.length === 1 ? "item" : "filteredItems", " ");
516
+ } }
517
+ function FileGridComponent_div_9_Template(rf, ctx) { if (rf & 1) {
518
+ i0.ɵɵelementStart(0, "div", 143)(1, "div", 144)(2, "div", 145);
519
+ i0.ɵɵelement(3, "i", 133);
520
+ i0.ɵɵelementEnd();
521
+ i0.ɵɵelementStart(4, "h2", 146);
522
+ i0.ɵɵtext(5, "Drop files to upload");
523
+ i0.ɵɵelementEnd()()();
524
+ } }
525
+ function FileGridComponent_div_10_Template(rf, ctx) { if (rf & 1) {
526
+ i0.ɵɵelementStart(0, "div", 147)(1, "div", 148)(2, "div", 149);
527
+ i0.ɵɵelement(3, "i", 48);
528
+ i0.ɵɵelementStart(4, "span");
529
+ i0.ɵɵtext(5);
530
+ i0.ɵɵelementEnd()();
531
+ i0.ɵɵelementStart(6, "div", 150);
532
+ i0.ɵɵelement(7, "div", 151);
533
+ i0.ɵɵelementEnd();
534
+ i0.ɵɵelementStart(8, "span", 152);
535
+ i0.ɵɵtext(9);
536
+ i0.ɵɵelementEnd()()();
537
+ } if (rf & 2) {
538
+ const ctx_r1 = i0.ɵɵnextContext();
539
+ i0.ɵɵadvance(5);
540
+ i0.ɵɵtextInterpolate1("Uploading ", ctx_r1.uploadingFileName, "...");
541
+ i0.ɵɵadvance(2);
542
+ i0.ɵɵstyleProp("width", ctx_r1.uploadProgress, "%");
543
+ i0.ɵɵadvance(2);
544
+ i0.ɵɵtextInterpolate1("", ctx_r1.uploadProgress, "%");
545
+ } }
546
+ function FileGridComponent_div_11_i_15_Template(rf, ctx) { if (rf & 1) {
547
+ i0.ɵɵelement(0, "i", 48);
548
+ } }
549
+ function FileGridComponent_div_11_Template(rf, ctx) { if (rf & 1) {
550
+ const _r18 = i0.ɵɵgetCurrentView();
551
+ i0.ɵɵelementStart(0, "div", 153);
552
+ i0.ɵɵlistener("click", function FileGridComponent_div_11_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelNewFolder()); });
553
+ i0.ɵɵelementStart(1, "div", 154);
554
+ i0.ɵɵlistener("click", function FileGridComponent_div_11_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r18); return i0.ɵɵresetView($event.stopPropagation()); });
555
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
556
+ i0.ɵɵtext(4, "Create New Folder");
557
+ i0.ɵɵelementEnd();
558
+ i0.ɵɵelementStart(5, "button", 156);
559
+ i0.ɵɵlistener("click", function FileGridComponent_div_11_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelNewFolder()); });
560
+ i0.ɵɵelement(6, "i", 31);
561
+ i0.ɵɵelementEnd()();
562
+ i0.ɵɵelementStart(7, "div", 157)(8, "label");
563
+ i0.ɵɵtext(9, "Folder name:");
564
+ i0.ɵɵelementEnd();
565
+ i0.ɵɵelementStart(10, "input", 158);
566
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_11_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newFolderName, $event) || (ctx_r1.newFolderName = $event); return i0.ɵɵresetView($event); });
567
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_11_Template_input_keydown_enter_10_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCreateFolder()); });
568
+ i0.ɵɵelementEnd()();
569
+ i0.ɵɵelementStart(11, "div", 159)(12, "button", 160);
570
+ i0.ɵɵlistener("click", function FileGridComponent_div_11_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelNewFolder()); });
571
+ i0.ɵɵtext(13, "Cancel");
572
+ i0.ɵɵelementEnd();
573
+ i0.ɵɵelementStart(14, "button", 160);
574
+ i0.ɵɵlistener("click", function FileGridComponent_div_11_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCreateFolder()); });
575
+ i0.ɵɵtemplate(15, FileGridComponent_div_11_i_15_Template, 1, 0, "i", 40);
576
+ i0.ɵɵtext(16);
577
+ i0.ɵɵelementEnd()()()();
578
+ } if (rf & 2) {
579
+ const ctx_r1 = i0.ɵɵnextContext();
580
+ i0.ɵɵadvance(10);
581
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newFolderName);
582
+ i0.ɵɵproperty("disabled", ctx_r1.isCreatingFolder);
583
+ i0.ɵɵadvance(2);
584
+ i0.ɵɵproperty("disabled", ctx_r1.isCreatingFolder);
585
+ i0.ɵɵadvance(2);
586
+ i0.ɵɵproperty("disabled", !ctx_r1.newFolderName.trim() || ctx_r1.isCreatingFolder);
587
+ i0.ɵɵadvance();
588
+ i0.ɵɵproperty("ngIf", ctx_r1.isCreatingFolder);
589
+ i0.ɵɵadvance();
590
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isCreatingFolder ? "Creating..." : "Create", " ");
591
+ } }
592
+ function FileGridComponent_div_12_p_13_Template(rf, ctx) { if (rf & 1) {
593
+ i0.ɵɵelementStart(0, "p", 163);
594
+ i0.ɵɵtext(1, "This will delete the folder and all its contents.");
595
+ i0.ɵɵelementEnd();
596
+ } }
597
+ function FileGridComponent_div_12_i_18_Template(rf, ctx) { if (rf & 1) {
598
+ i0.ɵɵelement(0, "i", 48);
599
+ } }
600
+ function FileGridComponent_div_12_Template(rf, ctx) { if (rf & 1) {
601
+ const _r19 = i0.ɵɵgetCurrentView();
602
+ i0.ɵɵelementStart(0, "div", 153);
603
+ i0.ɵɵlistener("click", function FileGridComponent_div_12_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelDelete()); });
604
+ i0.ɵɵelementStart(1, "div", 154);
605
+ i0.ɵɵlistener("click", function FileGridComponent_div_12_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
606
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
607
+ i0.ɵɵtext(4);
608
+ i0.ɵɵelementEnd();
609
+ i0.ɵɵelementStart(5, "button", 156);
610
+ i0.ɵɵlistener("click", function FileGridComponent_div_12_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelDelete()); });
611
+ i0.ɵɵelement(6, "i", 31);
612
+ i0.ɵɵelementEnd()();
613
+ i0.ɵɵelementStart(7, "div", 157)(8, "p");
614
+ i0.ɵɵtext(9, "Are you sure you want to delete ");
615
+ i0.ɵɵelementStart(10, "strong");
616
+ i0.ɵɵtext(11);
617
+ i0.ɵɵelementEnd();
618
+ i0.ɵɵtext(12, "?");
619
+ i0.ɵɵelementEnd();
620
+ i0.ɵɵtemplate(13, FileGridComponent_div_12_p_13_Template, 2, 0, "p", 161);
621
+ i0.ɵɵelementEnd();
622
+ i0.ɵɵelementStart(14, "div", 159)(15, "button", 160);
623
+ i0.ɵɵlistener("click", function FileGridComponent_div_12_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelDelete()); });
624
+ i0.ɵɵtext(16, "Cancel");
625
+ i0.ɵɵelementEnd();
626
+ i0.ɵɵelementStart(17, "button", 162);
627
+ i0.ɵɵlistener("click", function FileGridComponent_div_12_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmDelete()); });
628
+ i0.ɵɵtemplate(18, FileGridComponent_div_12_i_18_Template, 1, 0, "i", 40);
629
+ i0.ɵɵtext(19);
630
+ i0.ɵɵelementEnd()()()();
631
+ } if (rf & 2) {
632
+ const ctx_r1 = i0.ɵɵnextContext();
633
+ i0.ɵɵadvance(4);
634
+ i0.ɵɵtextInterpolate1("Delete ", ctx_r1.itemToDelete.type === "folder" ? "Folder" : "File", "?");
635
+ i0.ɵɵadvance(7);
636
+ i0.ɵɵtextInterpolate(ctx_r1.itemToDelete.name);
637
+ i0.ɵɵadvance(2);
638
+ i0.ɵɵproperty("ngIf", ctx_r1.itemToDelete.type === "folder");
639
+ i0.ɵɵadvance(2);
640
+ i0.ɵɵproperty("disabled", ctx_r1.isDeleting);
641
+ i0.ɵɵadvance(2);
642
+ i0.ɵɵproperty("disabled", ctx_r1.isDeleting);
643
+ i0.ɵɵadvance();
644
+ i0.ɵɵproperty("ngIf", ctx_r1.isDeleting);
645
+ i0.ɵɵadvance();
646
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isDeleting ? "Deleting..." : "Delete", " ");
647
+ } }
648
+ function FileGridComponent_div_13_i_15_Template(rf, ctx) { if (rf & 1) {
649
+ i0.ɵɵelement(0, "i", 48);
650
+ } }
651
+ function FileGridComponent_div_13_Template(rf, ctx) { if (rf & 1) {
652
+ const _r20 = i0.ɵɵgetCurrentView();
653
+ i0.ɵɵelementStart(0, "div", 153);
654
+ i0.ɵɵlistener("click", function FileGridComponent_div_13_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelRename()); });
655
+ i0.ɵɵelementStart(1, "div", 154);
656
+ i0.ɵɵlistener("click", function FileGridComponent_div_13_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r20); return i0.ɵɵresetView($event.stopPropagation()); });
657
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
658
+ i0.ɵɵtext(4);
659
+ i0.ɵɵelementEnd();
660
+ i0.ɵɵelementStart(5, "button", 156);
661
+ i0.ɵɵlistener("click", function FileGridComponent_div_13_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelRename()); });
662
+ i0.ɵɵelement(6, "i", 31);
663
+ i0.ɵɵelementEnd()();
664
+ i0.ɵɵelementStart(7, "div", 157)(8, "label");
665
+ i0.ɵɵtext(9, "New name:");
666
+ i0.ɵɵelementEnd();
667
+ i0.ɵɵelementStart(10, "input", 164);
668
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_13_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newItemName, $event) || (ctx_r1.newItemName = $event); return i0.ɵɵresetView($event); });
669
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_13_Template_input_keydown_enter_10_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmRename()); });
670
+ i0.ɵɵelementEnd()();
671
+ i0.ɵɵelementStart(11, "div", 159)(12, "button", 160);
672
+ i0.ɵɵlistener("click", function FileGridComponent_div_13_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelRename()); });
673
+ i0.ɵɵtext(13, "Cancel");
674
+ i0.ɵɵelementEnd();
675
+ i0.ɵɵelementStart(14, "button", 160);
676
+ i0.ɵɵlistener("click", function FileGridComponent_div_13_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmRename()); });
677
+ i0.ɵɵtemplate(15, FileGridComponent_div_13_i_15_Template, 1, 0, "i", 40);
678
+ i0.ɵɵtext(16);
679
+ i0.ɵɵelementEnd()()()();
680
+ } if (rf & 2) {
681
+ const ctx_r1 = i0.ɵɵnextContext();
682
+ i0.ɵɵadvance(4);
683
+ i0.ɵɵtextInterpolate1("Rename ", ctx_r1.itemToRename.type === "folder" ? "Folder" : "File", "");
684
+ i0.ɵɵadvance(6);
685
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newItemName);
686
+ i0.ɵɵproperty("disabled", ctx_r1.isRenaming);
687
+ i0.ɵɵadvance(2);
688
+ i0.ɵɵproperty("disabled", ctx_r1.isRenaming);
689
+ i0.ɵɵadvance(2);
690
+ i0.ɵɵproperty("disabled", ctx_r1.isRenaming || !ctx_r1.newItemName.trim());
691
+ i0.ɵɵadvance();
692
+ i0.ɵɵproperty("ngIf", ctx_r1.isRenaming);
693
+ i0.ɵɵadvance();
694
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isRenaming ? "Renaming..." : "Rename", " ");
695
+ } }
696
+ function FileGridComponent_div_14_i_19_Template(rf, ctx) { if (rf & 1) {
697
+ i0.ɵɵelement(0, "i", 48);
698
+ } }
699
+ function FileGridComponent_div_14_Template(rf, ctx) { if (rf & 1) {
700
+ const _r21 = i0.ɵɵgetCurrentView();
701
+ i0.ɵɵelementStart(0, "div", 153);
702
+ i0.ɵɵlistener("click", function FileGridComponent_div_14_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopy()); });
703
+ i0.ɵɵelementStart(1, "div", 154);
704
+ i0.ɵɵlistener("click", function FileGridComponent_div_14_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r21); return i0.ɵɵresetView($event.stopPropagation()); });
705
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
706
+ i0.ɵɵtext(4);
707
+ i0.ɵɵelementEnd();
708
+ i0.ɵɵelementStart(5, "button", 156);
709
+ i0.ɵɵlistener("click", function FileGridComponent_div_14_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopy()); });
710
+ i0.ɵɵelement(6, "i", 31);
711
+ i0.ɵɵelementEnd()();
712
+ i0.ɵɵelementStart(7, "div", 157)(8, "p");
713
+ i0.ɵɵtext(9, "Copying: ");
714
+ i0.ɵɵelementStart(10, "strong");
715
+ i0.ɵɵtext(11);
716
+ i0.ɵɵelementEnd()();
717
+ i0.ɵɵelementStart(12, "label");
718
+ i0.ɵɵtext(13, "Destination path:");
719
+ i0.ɵɵelementEnd();
720
+ i0.ɵɵelementStart(14, "input", 165);
721
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_14_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.copyDestinationPath, $event) || (ctx_r1.copyDestinationPath = $event); return i0.ɵɵresetView($event); });
722
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_14_Template_input_keydown_enter_14_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmCopy()); });
723
+ i0.ɵɵelementEnd()();
724
+ i0.ɵɵelementStart(15, "div", 159)(16, "button", 160);
725
+ i0.ɵɵlistener("click", function FileGridComponent_div_14_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopy()); });
726
+ i0.ɵɵtext(17, "Cancel");
727
+ i0.ɵɵelementEnd();
728
+ i0.ɵɵelementStart(18, "button", 160);
729
+ i0.ɵɵlistener("click", function FileGridComponent_div_14_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmCopy()); });
730
+ i0.ɵɵtemplate(19, FileGridComponent_div_14_i_19_Template, 1, 0, "i", 40);
731
+ i0.ɵɵtext(20);
732
+ i0.ɵɵelementEnd()()()();
733
+ } if (rf & 2) {
734
+ const ctx_r1 = i0.ɵɵnextContext();
735
+ i0.ɵɵadvance(4);
736
+ i0.ɵɵtextInterpolate1("Copy ", ctx_r1.itemToCopy.type === "folder" ? "Folder" : "File", "");
737
+ i0.ɵɵadvance(7);
738
+ i0.ɵɵtextInterpolate(ctx_r1.itemToCopy.name);
739
+ i0.ɵɵadvance(3);
740
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.copyDestinationPath);
741
+ i0.ɵɵproperty("disabled", ctx_r1.isCopying);
742
+ i0.ɵɵadvance(2);
743
+ i0.ɵɵproperty("disabled", ctx_r1.isCopying);
744
+ i0.ɵɵadvance(2);
745
+ i0.ɵɵproperty("disabled", ctx_r1.isCopying || !ctx_r1.copyDestinationPath.trim());
746
+ i0.ɵɵadvance();
747
+ i0.ɵɵproperty("ngIf", ctx_r1.isCopying);
748
+ i0.ɵɵadvance();
749
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isCopying ? "Copying..." : "Copy", " ");
750
+ } }
751
+ function FileGridComponent_div_15_i_21_Template(rf, ctx) { if (rf & 1) {
752
+ i0.ɵɵelement(0, "i", 48);
753
+ } }
754
+ function FileGridComponent_div_15_Template(rf, ctx) { if (rf & 1) {
755
+ const _r22 = i0.ɵɵgetCurrentView();
756
+ i0.ɵɵelementStart(0, "div", 153);
757
+ i0.ɵɵlistener("click", function FileGridComponent_div_15_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelMove()); });
758
+ i0.ɵɵelementStart(1, "div", 154);
759
+ i0.ɵɵlistener("click", function FileGridComponent_div_15_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r22); return i0.ɵɵresetView($event.stopPropagation()); });
760
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
761
+ i0.ɵɵtext(4);
762
+ i0.ɵɵelementEnd();
763
+ i0.ɵɵelementStart(5, "button", 156);
764
+ i0.ɵɵlistener("click", function FileGridComponent_div_15_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelMove()); });
765
+ i0.ɵɵelement(6, "i", 31);
766
+ i0.ɵɵelementEnd()();
767
+ i0.ɵɵelementStart(7, "div", 157)(8, "p");
768
+ i0.ɵɵtext(9, "Moving: ");
769
+ i0.ɵɵelementStart(10, "strong");
770
+ i0.ɵɵtext(11);
771
+ i0.ɵɵelementEnd()();
772
+ i0.ɵɵelementStart(12, "label");
773
+ i0.ɵɵtext(13, "Destination folder path:");
774
+ i0.ɵɵelementEnd();
775
+ i0.ɵɵelementStart(14, "input", 166);
776
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_15_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.moveDestinationPath, $event) || (ctx_r1.moveDestinationPath = $event); return i0.ɵɵresetView($event); });
777
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_15_Template_input_keydown_enter_14_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmMove()); });
778
+ i0.ɵɵelementEnd();
779
+ i0.ɵɵelementStart(15, "p", 167);
780
+ i0.ɵɵtext(16);
781
+ i0.ɵɵelementEnd()();
782
+ i0.ɵɵelementStart(17, "div", 159)(18, "button", 160);
783
+ i0.ɵɵlistener("click", function FileGridComponent_div_15_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelMove()); });
784
+ i0.ɵɵtext(19, "Cancel");
785
+ i0.ɵɵelementEnd();
786
+ i0.ɵɵelementStart(20, "button", 160);
787
+ i0.ɵɵlistener("click", function FileGridComponent_div_15_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmMove()); });
788
+ i0.ɵɵtemplate(21, FileGridComponent_div_15_i_21_Template, 1, 0, "i", 40);
789
+ i0.ɵɵtext(22);
790
+ i0.ɵɵelementEnd()()()();
791
+ } if (rf & 2) {
792
+ const ctx_r1 = i0.ɵɵnextContext();
793
+ i0.ɵɵadvance(4);
794
+ i0.ɵɵtextInterpolate1("Move ", ctx_r1.itemToMove.type === "folder" ? "Folder" : "File", "");
795
+ i0.ɵɵadvance(7);
796
+ i0.ɵɵtextInterpolate(ctx_r1.itemToMove.name);
797
+ i0.ɵɵadvance(3);
798
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.moveDestinationPath);
799
+ i0.ɵɵproperty("disabled", ctx_r1.isMoving);
800
+ i0.ɵɵadvance(2);
801
+ i0.ɵɵtextInterpolate2(" File will be moved to: ", ctx_r1.moveDestinationPath, "", ctx_r1.itemToMove.name, " ");
802
+ i0.ɵɵadvance(2);
803
+ i0.ɵɵproperty("disabled", ctx_r1.isMoving);
804
+ i0.ɵɵadvance(2);
805
+ i0.ɵɵproperty("disabled", ctx_r1.isMoving || !ctx_r1.moveDestinationPath.trim());
806
+ i0.ɵɵadvance();
807
+ i0.ɵɵproperty("ngIf", ctx_r1.isMoving);
808
+ i0.ɵɵadvance();
809
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isMoving ? "Moving..." : "Move", " ");
810
+ } }
811
+ function FileGridComponent_div_16_div_19_Template(rf, ctx) { if (rf & 1) {
812
+ const _r24 = i0.ɵɵgetCurrentView();
813
+ i0.ɵɵelementStart(0, "div", 174)(1, "input", 175);
814
+ i0.ɵɵlistener("change", function FileGridComponent_div_16_div_19_Template_input_change_1_listener() { const a_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleDestinationAccount(a_r25.account.ID)); });
815
+ i0.ɵɵelementEnd();
816
+ i0.ɵɵelementStart(2, "label", 176);
817
+ i0.ɵɵtext(3);
818
+ i0.ɵɵelementStart(4, "span", 177);
819
+ i0.ɵɵtext(5);
820
+ i0.ɵɵelementEnd()()();
821
+ } if (rf & 2) {
822
+ const a_r25 = ctx.$implicit;
823
+ const ctx_r1 = i0.ɵɵnextContext(2);
824
+ i0.ɵɵadvance();
825
+ i0.ɵɵproperty("id", "dest-account-" + a_r25.account.ID)("checked", ctx_r1.isDestinationAccountSelected(a_r25.account.ID))("disabled", ctx_r1.isCopyingToAccount);
826
+ i0.ɵɵadvance();
827
+ i0.ɵɵproperty("for", "dest-account-" + a_r25.account.ID);
828
+ i0.ɵɵadvance();
829
+ i0.ɵɵtextInterpolate1(" ", a_r25.account.Name, " ");
830
+ i0.ɵɵadvance(2);
831
+ i0.ɵɵtextInterpolate(a_r25.provider.Name);
832
+ } }
833
+ function FileGridComponent_div_16_div_23_Template(rf, ctx) { if (rf & 1) {
834
+ i0.ɵɵelementStart(0, "div", 178);
835
+ i0.ɵɵelement(1, "i", 48);
836
+ i0.ɵɵtext(2);
837
+ i0.ɵɵelementEnd();
838
+ } if (rf & 2) {
839
+ const ctx_r1 = i0.ɵɵnextContext(2);
840
+ i0.ɵɵadvance(2);
841
+ i0.ɵɵtextInterpolate3(" Copying to ", ctx_r1.copyToAccountProgress.currentAccount, " (", ctx_r1.copyToAccountProgress.current, "/", ctx_r1.copyToAccountProgress.total, ")... ");
842
+ } }
843
+ function FileGridComponent_div_16_i_28_Template(rf, ctx) { if (rf & 1) {
844
+ i0.ɵɵelement(0, "i", 48);
845
+ } }
846
+ function FileGridComponent_div_16_Template(rf, ctx) { if (rf & 1) {
847
+ const _r23 = i0.ɵɵgetCurrentView();
848
+ i0.ɵɵelementStart(0, "div", 153);
849
+ i0.ɵɵlistener("click", function FileGridComponent_div_16_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopyToAccount()); });
850
+ i0.ɵɵelementStart(1, "div", 154);
851
+ i0.ɵɵlistener("click", function FileGridComponent_div_16_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r23); return i0.ɵɵresetView($event.stopPropagation()); });
852
+ i0.ɵɵelementStart(2, "div", 155)(3, "h3");
853
+ i0.ɵɵtext(4, "Copy to Another Account");
854
+ i0.ɵɵelementEnd();
855
+ i0.ɵɵelementStart(5, "button", 156);
856
+ i0.ɵɵlistener("click", function FileGridComponent_div_16_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopyToAccount()); });
857
+ i0.ɵɵelement(6, "i", 31);
858
+ i0.ɵɵelementEnd()();
859
+ i0.ɵɵelementStart(7, "div", 157)(8, "p");
860
+ i0.ɵɵtext(9, "Copying: ");
861
+ i0.ɵɵelementStart(10, "strong");
862
+ i0.ɵɵtext(11);
863
+ i0.ɵɵelementEnd()();
864
+ i0.ɵɵelementStart(12, "p", 168);
865
+ i0.ɵɵtext(13, " From: ");
866
+ i0.ɵɵelementStart(14, "strong");
867
+ i0.ɵɵtext(15);
868
+ i0.ɵɵelementEnd()();
869
+ i0.ɵɵelementStart(16, "label");
870
+ i0.ɵɵtext(17, "Select destination account(s):");
871
+ i0.ɵɵelementEnd();
872
+ i0.ɵɵelementStart(18, "div", 169);
873
+ i0.ɵɵtemplate(19, FileGridComponent_div_16_div_19_Template, 6, 6, "div", 170);
874
+ i0.ɵɵelementEnd();
875
+ i0.ɵɵelementStart(20, "label", 171);
876
+ i0.ɵɵtext(21, "Destination filename:");
877
+ i0.ɵɵelementEnd();
878
+ i0.ɵɵelementStart(22, "input", 172);
879
+ i0.ɵɵtwoWayListener("ngModelChange", function FileGridComponent_div_16_Template_input_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.copyToAccountDestinationPath, $event) || (ctx_r1.copyToAccountDestinationPath = $event); return i0.ɵɵresetView($event); });
880
+ i0.ɵɵlistener("keydown.enter", function FileGridComponent_div_16_Template_input_keydown_enter_22_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmCopyToAccount()); });
881
+ i0.ɵɵelementEnd();
882
+ i0.ɵɵtemplate(23, FileGridComponent_div_16_div_23_Template, 3, 3, "div", 173);
883
+ i0.ɵɵelementEnd();
884
+ i0.ɵɵelementStart(24, "div", 159)(25, "button", 160);
885
+ i0.ɵɵlistener("click", function FileGridComponent_div_16_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCancelCopyToAccount()); });
886
+ i0.ɵɵtext(26, "Cancel");
887
+ i0.ɵɵelementEnd();
888
+ i0.ɵɵelementStart(27, "button", 160);
889
+ i0.ɵɵlistener("click", function FileGridComponent_div_16_Template_button_click_27_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onConfirmCopyToAccount()); });
890
+ i0.ɵɵtemplate(28, FileGridComponent_div_16_i_28_Template, 1, 0, "i", 40);
891
+ i0.ɵɵtext(29);
892
+ i0.ɵɵelementEnd()()()();
893
+ } if (rf & 2) {
894
+ const ctx_r1 = i0.ɵɵnextContext();
895
+ i0.ɵɵadvance(11);
896
+ i0.ɵɵtextInterpolate(ctx_r1.itemToCopyToProvider.name);
897
+ i0.ɵɵadvance(4);
898
+ i0.ɵɵtextInterpolate(ctx_r1.account == null ? null : ctx_r1.account.account == null ? null : ctx_r1.account.account.Name);
899
+ i0.ɵɵadvance(4);
900
+ i0.ɵɵproperty("ngForOf", ctx_r1.availableAccounts);
901
+ i0.ɵɵadvance(3);
902
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.copyToAccountDestinationPath);
903
+ i0.ɵɵproperty("disabled", ctx_r1.isCopyingToAccount);
904
+ i0.ɵɵadvance();
905
+ i0.ɵɵproperty("ngIf", ctx_r1.copyToAccountProgress);
906
+ i0.ɵɵadvance(2);
907
+ i0.ɵɵproperty("disabled", ctx_r1.isCopyingToAccount);
908
+ i0.ɵɵadvance(2);
909
+ i0.ɵɵproperty("disabled", ctx_r1.isCopyingToAccount || ctx_r1.selectedDestinationAccounts.size === 0 || !ctx_r1.copyToAccountDestinationPath.trim());
910
+ i0.ɵɵadvance();
911
+ i0.ɵɵproperty("ngIf", ctx_r1.isCopyingToAccount);
912
+ i0.ɵɵadvance();
913
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.isCopyingToAccount ? "Copying..." : "Copy to " + ctx_r1.selectedDestinationAccounts.size + " account" + (ctx_r1.selectedDestinationAccounts.size !== 1 ? "s" : ""), " ");
914
+ } }
915
+ /**
916
+ * Displays files and folders in a grid/list view.
917
+ * Shows file metadata like name, size, type, and last modified date.
918
+ * Supports file selection and navigation to folders.
919
+ */
920
+ export class FileGridComponent {
921
+ /**
922
+ * The storage account to list files from (includes provider details)
923
+ */
924
+ account = null;
925
+ /**
926
+ * The current folder path to display
927
+ */
928
+ folderPath = '';
929
+ /**
930
+ * Emits when a folder is double-clicked for navigation
931
+ */
932
+ folderNavigate = new EventEmitter();
933
+ /**
934
+ * Emits when the folder structure has changed (e.g., new folder created)
935
+ * This signals that the folder tree should refresh
936
+ */
937
+ folderStructureChanged = new EventEmitter();
938
+ /**
939
+ * List of files and folders in the current directory
940
+ */
941
+ items = [];
942
+ /**
943
+ * Currently selected item keys in the grid (Kendo stores keys, not full objects)
944
+ */
945
+ selectedItems = [];
946
+ /**
947
+ * Loading state indicator
948
+ */
949
+ isLoading = false;
950
+ /**
951
+ * Error message if loading fails
952
+ */
953
+ errorMessage = null;
954
+ /**
955
+ * View mode: 'grid' or 'list'
956
+ */
957
+ viewMode = 'list';
958
+ /**
959
+ * Sort configuration for the grid
960
+ */
961
+ sort = [
962
+ { field: 'name', dir: 'asc' }
963
+ ];
964
+ /**
965
+ * Search query for filtering files/folders
966
+ */
967
+ searchQuery = '';
968
+ /**
969
+ * File type filter ('all', 'files', 'folders')
970
+ */
971
+ fileTypeFilter = 'all';
972
+ /**
973
+ * Filtered list of items based on search and filter criteria
974
+ */
975
+ filteredItems = [];
976
+ /**
977
+ * Drag-and-drop state
978
+ */
979
+ isDragging = false;
980
+ /**
981
+ * Upload progress state
982
+ */
983
+ isUploading = false;
984
+ uploadProgress = 0;
985
+ uploadingFileName = '';
986
+ /**
987
+ * New folder dialog state
988
+ */
989
+ showNewFolderDialog = false;
990
+ newFolderName = '';
991
+ isCreatingFolder = false;
992
+ /**
993
+ * Delete confirmation dialog state
994
+ */
995
+ showDeleteDialog = false;
996
+ itemToDelete = null;
997
+ isDeleting = false;
998
+ /**
999
+ * Rename dialog state
1000
+ */
1001
+ showRenameDialog = false;
1002
+ itemToRename = null;
1003
+ newItemName = '';
1004
+ isRenaming = false;
1005
+ /**
1006
+ * Copy dialog state
1007
+ */
1008
+ showCopyDialog = false;
1009
+ itemToCopy = null;
1010
+ copyDestinationPath = '';
1011
+ isCopying = false;
1012
+ /**
1013
+ * Move dialog state
1014
+ */
1015
+ showMoveDialog = false;
1016
+ itemToMove = null;
1017
+ moveDestinationPath = '';
1018
+ isMoving = false;
1019
+ /**
1020
+ * Copy to provider dialog state
1021
+ */
1022
+ showCopyToProviderDialog = false;
1023
+ itemToCopyToProvider = null;
1024
+ availableAccounts = [];
1025
+ selectedDestinationAccounts = new Set();
1026
+ copyToAccountDestinationPath = '';
1027
+ isCopyingToAccount = false;
1028
+ copyToAccountProgress = null;
1029
+ /**
1030
+ * Multi-provider search state
1031
+ */
1032
+ isMultiProviderSearchMode = false;
1033
+ multiProviderSearchQuery = '';
1034
+ selectedSearchProviders = new Set();
1035
+ isSearching = false;
1036
+ multiProviderSearchResults = null;
1037
+ /**
1038
+ * GraphQL client for file storage operations
1039
+ */
1040
+ storageClient;
1041
+ constructor() {
1042
+ this.storageClient = new GraphQLFileStorageClient(GraphQLDataProvider.Instance);
1043
+ }
1044
+ ngOnInit() {
1045
+ // Don't load items here - wait for ngOnChanges when inputs are set
1046
+ }
1047
+ ngOnChanges(changes) {
1048
+ // Reload items when provider or folder path changes
1049
+ if (changes['account'] || changes['folderPath']) {
1050
+ this.loadItems();
1051
+ }
1052
+ }
1053
+ /**
1054
+ * Loads files and folders from the current path
1055
+ */
1056
+ async loadItems() {
1057
+ if (!this.account) {
1058
+ this.items = [];
1059
+ return;
1060
+ }
1061
+ const previousItemCount = this.items.length;
1062
+ const previousItemNames = this.items.map(i => i.name);
1063
+ this.isLoading = true;
1064
+ this.errorMessage = null;
1065
+ try {
1066
+ console.log('[FileGrid] Loading items for account:', this.account.account.ID, 'path:', this.folderPath);
1067
+ console.log('[FileGrid] Previous items:', { count: previousItemCount, names: previousItemNames });
1068
+ const listResult = await this.storageClient.ListObjects(this.account.account.ID, this.folderPath || '', '/');
1069
+ console.log('[FileGrid] ListObjects result:', listResult);
1070
+ this.items = [];
1071
+ // Add folders from prefixes first (so they appear before files)
1072
+ if (listResult.prefixes) {
1073
+ for (const prefix of listResult.prefixes) {
1074
+ // Extract the folder name from the prefix path
1075
+ // Prefix comes as "path/to/folder/" so we need to get just "folder"
1076
+ const folderName = prefix.endsWith('/')
1077
+ ? prefix.slice(0, -1).split('/').pop()
1078
+ : prefix.split('/').pop();
1079
+ if (folderName) {
1080
+ this.items.push({
1081
+ key: prefix,
1082
+ name: folderName,
1083
+ type: 'folder',
1084
+ size: 0,
1085
+ lastModified: new Date(),
1086
+ contentType: 'application/x-directory'
1087
+ });
1088
+ }
1089
+ }
1090
+ }
1091
+ // Add files from objects
1092
+ if (listResult.objects) {
1093
+ for (const obj of listResult.objects) {
1094
+ // Skip directories from objects - we already added them from prefixes
1095
+ if (obj.isDirectory) {
1096
+ continue;
1097
+ }
1098
+ this.items.push({
1099
+ key: obj.fullPath,
1100
+ name: obj.name,
1101
+ type: 'file',
1102
+ size: obj.size,
1103
+ lastModified: obj.lastModified,
1104
+ contentType: obj.contentType,
1105
+ etag: obj.etag
1106
+ });
1107
+ }
1108
+ }
1109
+ }
1110
+ catch (error) {
1111
+ this.errorMessage = 'Failed to load files';
1112
+ console.error('[FileGrid] Error loading files:', error);
1113
+ }
1114
+ finally {
1115
+ this.isLoading = false;
1116
+ }
1117
+ // Apply filters after loading
1118
+ this.applyFilters();
1119
+ }
1120
+ /**
1121
+ * Applies search and filter criteria to the items list
1122
+ */
1123
+ applyFilters() {
1124
+ let filtered = [...this.items];
1125
+ // Apply file type filter
1126
+ if (this.fileTypeFilter === 'files') {
1127
+ filtered = filtered.filter(item => item.type === 'file');
1128
+ }
1129
+ else if (this.fileTypeFilter === 'folders') {
1130
+ filtered = filtered.filter(item => item.type === 'folder');
1131
+ }
1132
+ // Apply search query
1133
+ if (this.searchQuery.trim()) {
1134
+ const query = this.searchQuery.toLowerCase();
1135
+ filtered = filtered.filter(item => item.name.toLowerCase().includes(query));
1136
+ }
1137
+ this.filteredItems = filtered;
1138
+ }
1139
+ /**
1140
+ * Handles search query changes
1141
+ */
1142
+ onSearchChange(query) {
1143
+ this.searchQuery = query;
1144
+ this.applyFilters();
1145
+ }
1146
+ /**
1147
+ * Clears the search query
1148
+ */
1149
+ clearSearch() {
1150
+ this.searchQuery = '';
1151
+ this.applyFilters();
1152
+ }
1153
+ /**
1154
+ * Handles file type filter changes
1155
+ */
1156
+ onFileTypeFilterChange(filterType) {
1157
+ this.fileTypeFilter = filterType;
1158
+ this.applyFilters();
1159
+ }
1160
+ /**
1161
+ * Formats a file size in bytes to a human-readable string
1162
+ */
1163
+ formatFileSize(bytes) {
1164
+ if (bytes === 0)
1165
+ return '0 B';
1166
+ const k = 1024;
1167
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
1168
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1169
+ return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
1170
+ }
1171
+ /**
1172
+ * Formats a date to a readable string
1173
+ */
1174
+ formatDate(date) {
1175
+ return date.toLocaleString();
1176
+ }
1177
+ /**
1178
+ * Gets the icon class for a file or folder
1179
+ */
1180
+ getItemIcon(item) {
1181
+ if (!item || !item.name) {
1182
+ return 'fa-solid fa-file';
1183
+ }
1184
+ if (item.type === 'folder') {
1185
+ return 'fa-solid fa-folder';
1186
+ }
1187
+ // Determine file icon based on content type or extension
1188
+ const extension = item.name.split('.').pop()?.toLowerCase() || '';
1189
+ if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'].includes(extension)) {
1190
+ return 'fa-solid fa-file-image';
1191
+ }
1192
+ else if (['pdf'].includes(extension)) {
1193
+ return 'fa-solid fa-file-pdf';
1194
+ }
1195
+ else if (['doc', 'docx'].includes(extension)) {
1196
+ return 'fa-solid fa-file-word';
1197
+ }
1198
+ else if (['xls', 'xlsx'].includes(extension)) {
1199
+ return 'fa-solid fa-file-excel';
1200
+ }
1201
+ else if (['ppt', 'pptx'].includes(extension)) {
1202
+ return 'fa-solid fa-file-powerpoint';
1203
+ }
1204
+ else if (['zip', 'rar', '7z', 'tar', 'gz'].includes(extension)) {
1205
+ return 'fa-solid fa-file-zipper';
1206
+ }
1207
+ else if (['mp4', 'avi', 'mov', 'wmv'].includes(extension)) {
1208
+ return 'fa-solid fa-file-video';
1209
+ }
1210
+ else if (['mp3', 'wav', 'ogg', 'flac'].includes(extension)) {
1211
+ return 'fa-solid fa-file-audio';
1212
+ }
1213
+ else if (['txt', 'log'].includes(extension)) {
1214
+ return 'fa-solid fa-file-lines';
1215
+ }
1216
+ else if (['js', 'ts', 'html', 'css', 'json', 'xml', 'py', 'java', 'cpp'].includes(extension)) {
1217
+ return 'fa-solid fa-file-code';
1218
+ }
1219
+ else {
1220
+ return 'fa-solid fa-file';
1221
+ }
1222
+ }
1223
+ /**
1224
+ * Handles item selection change (not used - Kendo handles selection internally)
1225
+ */
1226
+ onSelectionChange(selectedKeys) {
1227
+ this.selectedItems = selectedKeys;
1228
+ }
1229
+ /**
1230
+ * Handles tile click in grid view for selection
1231
+ */
1232
+ onTileClick(item, event) {
1233
+ if (event.ctrlKey || event.metaKey) {
1234
+ // Multi-select: toggle item key
1235
+ const index = this.selectedItems.indexOf(item.key);
1236
+ if (index >= 0) {
1237
+ this.selectedItems.splice(index, 1);
1238
+ }
1239
+ else {
1240
+ this.selectedItems.push(item.key);
1241
+ }
1242
+ }
1243
+ else if (event.shiftKey && this.selectedItems.length > 0) {
1244
+ // Range select: select from last selected to current
1245
+ const lastSelectedKey = this.selectedItems[this.selectedItems.length - 1];
1246
+ const lastSelected = this.items.find(i => i.key === lastSelectedKey);
1247
+ if (lastSelected) {
1248
+ const lastIndex = this.items.indexOf(lastSelected);
1249
+ const currentIndex = this.items.indexOf(item);
1250
+ const start = Math.min(lastIndex, currentIndex);
1251
+ const end = Math.max(lastIndex, currentIndex);
1252
+ this.selectedItems = this.items.slice(start, end + 1).map(i => i.key);
1253
+ }
1254
+ }
1255
+ else {
1256
+ // Single select: replace selection
1257
+ this.selectedItems = [item.key];
1258
+ }
1259
+ }
1260
+ /**
1261
+ * Handles double-click on an item
1262
+ * For folders, navigate into them. For files, open/download them.
1263
+ */
1264
+ onItemDoubleClick(item) {
1265
+ if (item.type === 'folder') {
1266
+ // Navigate into folder by emitting the folder path
1267
+ console.log('[FileGrid] Navigating to folder:', item.key);
1268
+ this.folderNavigate.emit(item.key);
1269
+ }
1270
+ else {
1271
+ // Download file
1272
+ this.downloadFile(item);
1273
+ }
1274
+ }
1275
+ /**
1276
+ * Downloads a file by creating a pre-authenticated download URL
1277
+ */
1278
+ async downloadFile(item) {
1279
+ if (!this.account) {
1280
+ return;
1281
+ }
1282
+ try {
1283
+ console.log('[FileGrid] Downloading file:', item.key);
1284
+ const downloadUrl = await this.storageClient.CreatePreAuthDownloadUrl(this.account.account.ID, item.key);
1285
+ console.log('[FileGrid] Download URL created:', downloadUrl ? 'success' : 'failed');
1286
+ if (downloadUrl) {
1287
+ // Trigger browser download
1288
+ const link = document.createElement('a');
1289
+ link.href = downloadUrl;
1290
+ link.download = item.name;
1291
+ link.target = '_blank'; // Open in new tab as fallback
1292
+ document.body.appendChild(link);
1293
+ link.click();
1294
+ document.body.removeChild(link);
1295
+ console.log('[FileGrid] File download initiated:', item.name);
1296
+ }
1297
+ else {
1298
+ console.error('[FileGrid] Failed to get download URL');
1299
+ this.errorMessage = 'Failed to generate download URL';
1300
+ }
1301
+ }
1302
+ catch (error) {
1303
+ console.error('[FileGrid] Error downloading file:', error);
1304
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1305
+ this.errorMessage = `Failed to download file: ${errorMessage}`;
1306
+ // Clear error after 5 seconds
1307
+ setTimeout(() => {
1308
+ if (this.errorMessage?.startsWith('Failed to download')) {
1309
+ this.errorMessage = null;
1310
+ }
1311
+ }, 5000);
1312
+ }
1313
+ }
1314
+ /**
1315
+ * Toggles between grid and list view
1316
+ */
1317
+ toggleViewMode() {
1318
+ this.viewMode = this.viewMode === 'grid' ? 'list' : 'grid';
1319
+ }
1320
+ /**
1321
+ * Refreshes the current directory
1322
+ */
1323
+ refresh() {
1324
+ this.loadItems();
1325
+ }
1326
+ /**
1327
+ * Navigates up to the parent directory
1328
+ */
1329
+ navigateUp() {
1330
+ if (!this.folderPath) {
1331
+ // Already at root
1332
+ return;
1333
+ }
1334
+ // Remove trailing slash if present
1335
+ const cleanPath = this.folderPath.endsWith('/')
1336
+ ? this.folderPath.slice(0, -1)
1337
+ : this.folderPath;
1338
+ // Get parent path by removing last segment
1339
+ const segments = cleanPath.split('/').filter(s => s.length > 0);
1340
+ segments.pop(); // Remove last segment
1341
+ const parentPath = segments.length > 0 ? segments.join('/') + '/' : '';
1342
+ // Emit navigation event to update the folder tree and path
1343
+ this.folderNavigate.emit(parentPath);
1344
+ }
1345
+ /**
1346
+ * Checks if we can navigate up (not at root)
1347
+ */
1348
+ canNavigateUp() {
1349
+ return this.folderPath !== '' && this.folderPath !== '/';
1350
+ }
1351
+ /**
1352
+ * Handles sort change event from the grid
1353
+ */
1354
+ onSortChange(sort) {
1355
+ this.sort = sort;
1356
+ }
1357
+ /**
1358
+ * Gets a human-readable file type based on extension
1359
+ */
1360
+ getFileType(item) {
1361
+ if (item.type === 'folder') {
1362
+ return 'Folder';
1363
+ }
1364
+ const extension = item.name.split('.').pop()?.toLowerCase() || '';
1365
+ const typeMap = {
1366
+ // Documents
1367
+ pdf: 'PDF Document',
1368
+ doc: 'Word Document',
1369
+ docx: 'Word Document',
1370
+ xls: 'Excel Spreadsheet',
1371
+ xlsx: 'Excel Spreadsheet',
1372
+ ppt: 'PowerPoint',
1373
+ pptx: 'PowerPoint',
1374
+ txt: 'Text File',
1375
+ // Images
1376
+ jpg: 'JPEG Image',
1377
+ jpeg: 'JPEG Image',
1378
+ png: 'PNG Image',
1379
+ gif: 'GIF Image',
1380
+ bmp: 'Bitmap Image',
1381
+ svg: 'SVG Image',
1382
+ // Archives
1383
+ zip: 'ZIP Archive',
1384
+ rar: 'RAR Archive',
1385
+ '7z': '7-Zip Archive',
1386
+ tar: 'TAR Archive',
1387
+ gz: 'GZIP Archive',
1388
+ // Media
1389
+ mp4: 'MP4 Video',
1390
+ avi: 'AVI Video',
1391
+ mov: 'QuickTime Video',
1392
+ mp3: 'MP3 Audio',
1393
+ wav: 'WAV Audio',
1394
+ // Code
1395
+ js: 'JavaScript',
1396
+ ts: 'TypeScript',
1397
+ html: 'HTML',
1398
+ css: 'CSS',
1399
+ json: 'JSON',
1400
+ xml: 'XML',
1401
+ py: 'Python',
1402
+ java: 'Java',
1403
+ cpp: 'C++'
1404
+ };
1405
+ return typeMap[extension] || `${extension.toUpperCase()} File`;
1406
+ }
1407
+ /**
1408
+ * Handles upload button click - triggers file input
1409
+ */
1410
+ onUploadClick() {
1411
+ const fileInput = document.createElement('input');
1412
+ fileInput.type = 'file';
1413
+ fileInput.multiple = true;
1414
+ fileInput.onchange = (event) => {
1415
+ const target = event.target;
1416
+ if (target.files && target.files.length > 0) {
1417
+ this.uploadFiles(Array.from(target.files));
1418
+ }
1419
+ };
1420
+ fileInput.click();
1421
+ }
1422
+ /**
1423
+ * Handles drag enter event
1424
+ */
1425
+ onDragEnter(event) {
1426
+ event.preventDefault();
1427
+ event.stopPropagation();
1428
+ this.isDragging = true;
1429
+ }
1430
+ /**
1431
+ * Handles drag over event
1432
+ */
1433
+ onDragOver(event) {
1434
+ event.preventDefault();
1435
+ event.stopPropagation();
1436
+ }
1437
+ /**
1438
+ * Handles drag leave event
1439
+ */
1440
+ onDragLeave(event) {
1441
+ event.preventDefault();
1442
+ event.stopPropagation();
1443
+ // Only hide if leaving the container itself, not child elements
1444
+ if (event.currentTarget === event.target) {
1445
+ this.isDragging = false;
1446
+ }
1447
+ }
1448
+ /**
1449
+ * Handles drop event
1450
+ */
1451
+ onDrop(event) {
1452
+ event.preventDefault();
1453
+ event.stopPropagation();
1454
+ this.isDragging = false;
1455
+ const files = event.dataTransfer?.files;
1456
+ if (files && files.length > 0) {
1457
+ this.uploadFiles(Array.from(files));
1458
+ }
1459
+ }
1460
+ /**
1461
+ * Uploads multiple files to the current folder
1462
+ */
1463
+ async uploadFiles(files) {
1464
+ if (!this.account) {
1465
+ return;
1466
+ }
1467
+ console.log('[FileGrid] Uploading files:', files.map(f => f.name));
1468
+ for (let i = 0; i < files.length; i++) {
1469
+ const file = files[i];
1470
+ await this.uploadSingleFile(file, i + 1, files.length);
1471
+ }
1472
+ // Refresh the file list after all uploads complete
1473
+ this.loadItems();
1474
+ }
1475
+ /**
1476
+ * Uploads a single file
1477
+ */
1478
+ async uploadSingleFile(file, current, total) {
1479
+ if (!this.account) {
1480
+ return;
1481
+ }
1482
+ this.isUploading = true;
1483
+ this.uploadingFileName = `${file.name} (${current}/${total})`;
1484
+ this.uploadProgress = 0;
1485
+ try {
1486
+ // Construct the full object name with folder path
1487
+ // Remove trailing slash from folderPath to avoid double slashes
1488
+ let objectName;
1489
+ if (this.folderPath) {
1490
+ const cleanPath = this.folderPath.endsWith('/')
1491
+ ? this.folderPath.slice(0, -1)
1492
+ : this.folderPath;
1493
+ objectName = `${cleanPath}/${file.name}`;
1494
+ }
1495
+ else {
1496
+ objectName = file.name;
1497
+ }
1498
+ console.log('[FileGrid] Getting upload URL for:', objectName);
1499
+ // Get pre-authenticated upload URL
1500
+ const uploadData = await this.storageClient.CreatePreAuthUploadUrl(this.account.account.ID, objectName, file.type || 'application/octet-stream');
1501
+ console.log('[FileGrid] Got upload URL:', uploadData.uploadUrl);
1502
+ // Upload the file using XMLHttpRequest to track progress
1503
+ await this.uploadFileToUrl(file, uploadData.uploadUrl);
1504
+ console.log('[FileGrid] File uploaded successfully:', file.name);
1505
+ }
1506
+ catch (error) {
1507
+ console.error('[FileGrid] Error uploading file:', error);
1508
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1509
+ // Check if this is an unsupported operation error (e.g., Google Drive doesn't support pre-auth uploads)
1510
+ if (errorMessage.includes('not supported')) {
1511
+ this.errorMessage = `Upload not supported for ${this.account?.account.Name || 'this account'}. Try using a different storage account.`;
1512
+ }
1513
+ else {
1514
+ this.errorMessage = `Failed to upload ${file.name}: ${errorMessage}`;
1515
+ }
1516
+ // Clear error after 5 seconds
1517
+ setTimeout(() => {
1518
+ if (this.errorMessage?.startsWith('Failed to upload') || this.errorMessage?.startsWith('Upload not supported')) {
1519
+ this.errorMessage = null;
1520
+ }
1521
+ }, 5000);
1522
+ }
1523
+ finally {
1524
+ this.isUploading = false;
1525
+ this.uploadProgress = 0;
1526
+ this.uploadingFileName = '';
1527
+ }
1528
+ }
1529
+ /**
1530
+ * Uploads file to the pre-authenticated URL with progress tracking
1531
+ */
1532
+ uploadFileToUrl(file, url) {
1533
+ return new Promise((resolve, reject) => {
1534
+ const xhr = new XMLHttpRequest();
1535
+ xhr.upload.addEventListener('progress', (event) => {
1536
+ if (event.lengthComputable) {
1537
+ this.uploadProgress = Math.round((event.loaded / event.total) * 100);
1538
+ }
1539
+ });
1540
+ xhr.addEventListener('load', () => {
1541
+ if (xhr.status >= 200 && xhr.status < 300) {
1542
+ resolve();
1543
+ }
1544
+ else {
1545
+ reject(new Error(`Upload failed with status ${xhr.status}`));
1546
+ }
1547
+ });
1548
+ xhr.addEventListener('error', () => {
1549
+ reject(new Error('Network error during upload'));
1550
+ });
1551
+ xhr.addEventListener('abort', () => {
1552
+ reject(new Error('Upload cancelled'));
1553
+ });
1554
+ // Use POST for Dropbox temporary upload links (required by Dropbox API)
1555
+ // Use PUT for other providers like S3
1556
+ // Dropbox requires POST with application/octet-stream
1557
+ xhr.open('POST', url, true);
1558
+ xhr.setRequestHeader('Content-Type', 'application/octet-stream');
1559
+ xhr.send(file);
1560
+ });
1561
+ }
1562
+ /**
1563
+ * Opens the new folder dialog
1564
+ */
1565
+ onNewFolderClick() {
1566
+ this.newFolderName = '';
1567
+ this.showNewFolderDialog = true;
1568
+ }
1569
+ /**
1570
+ * Closes the new folder dialog
1571
+ */
1572
+ onCancelNewFolder() {
1573
+ this.showNewFolderDialog = false;
1574
+ this.newFolderName = '';
1575
+ }
1576
+ /**
1577
+ * Creates a new folder in the current directory
1578
+ */
1579
+ async onCreateFolder() {
1580
+ if (!this.account || !this.newFolderName.trim()) {
1581
+ return;
1582
+ }
1583
+ this.isCreatingFolder = true;
1584
+ try {
1585
+ // Construct the full folder path
1586
+ // Remove trailing slash from folderPath to avoid double slashes
1587
+ let folderPath;
1588
+ if (this.folderPath) {
1589
+ const cleanPath = this.folderPath.endsWith('/')
1590
+ ? this.folderPath.slice(0, -1)
1591
+ : this.folderPath;
1592
+ folderPath = `${cleanPath}/${this.newFolderName.trim()}`;
1593
+ }
1594
+ else {
1595
+ folderPath = this.newFolderName.trim();
1596
+ }
1597
+ console.log('[FileGrid] Creating folder:', folderPath);
1598
+ const success = await this.storageClient.CreateDirectory(this.account.account.ID, folderPath);
1599
+ if (success) {
1600
+ console.log('[FileGrid] Folder created successfully:', folderPath);
1601
+ // Close dialog and refresh
1602
+ this.showNewFolderDialog = false;
1603
+ this.newFolderName = '';
1604
+ // Notify parent that folder structure changed
1605
+ this.folderStructureChanged.emit();
1606
+ // Refresh the file grid
1607
+ this.loadItems();
1608
+ }
1609
+ else {
1610
+ this.errorMessage = 'Failed to create folder';
1611
+ }
1612
+ }
1613
+ catch (error) {
1614
+ console.error('[FileGrid] Error creating folder:', error);
1615
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1616
+ this.errorMessage = `Failed to create folder: ${errorMessage}`;
1617
+ // Clear error after 5 seconds
1618
+ setTimeout(() => {
1619
+ if (this.errorMessage?.startsWith('Failed to create')) {
1620
+ this.errorMessage = null;
1621
+ }
1622
+ }, 5000);
1623
+ }
1624
+ finally {
1625
+ this.isCreatingFolder = false;
1626
+ }
1627
+ }
1628
+ /**
1629
+ * Opens the delete confirmation dialog for the selected items
1630
+ */
1631
+ onDeleteClick() {
1632
+ if (this.selectedItems.length === 0) {
1633
+ return;
1634
+ }
1635
+ // selectedItems contains keys (strings), not full objects
1636
+ // Find the actual item object from the items array
1637
+ const selectedKey = this.selectedItems[0];
1638
+ const item = this.items.find(i => i.key === selectedKey);
1639
+ if (!item) {
1640
+ console.error('[FileGrid] Could not find selected item with key:', selectedKey);
1641
+ return;
1642
+ }
1643
+ this.itemToDelete = item;
1644
+ this.showDeleteDialog = true;
1645
+ }
1646
+ /**
1647
+ * Closes the delete confirmation dialog
1648
+ */
1649
+ onCancelDelete() {
1650
+ this.showDeleteDialog = false;
1651
+ this.itemToDelete = null;
1652
+ }
1653
+ /**
1654
+ * Deletes the selected item after confirmation
1655
+ */
1656
+ async onConfirmDelete() {
1657
+ if (!this.account || !this.itemToDelete) {
1658
+ return;
1659
+ }
1660
+ this.isDeleting = true;
1661
+ try {
1662
+ // Construct the full path to the item
1663
+ const itemPath = this.constructItemPath(this.itemToDelete);
1664
+ console.log('[FileGrid] Deleting item:', itemPath);
1665
+ const success = await this.storageClient.DeleteObject(this.account.account.ID, itemPath);
1666
+ console.log('[FileGrid] Delete result:', { success });
1667
+ if (success) {
1668
+ console.log('[FileGrid] Item deleted successfully:', itemPath);
1669
+ // Check if we deleted a folder (before clearing itemToDelete)
1670
+ const wasFolder = this.itemToDelete.type === 'folder';
1671
+ console.log('[FileGrid] Item details:', {
1672
+ type: this.itemToDelete.type,
1673
+ name: this.itemToDelete.name,
1674
+ key: this.itemToDelete.key,
1675
+ wasFolder
1676
+ });
1677
+ // Close dialog
1678
+ this.showDeleteDialog = false;
1679
+ this.itemToDelete = null;
1680
+ // Clear selection
1681
+ this.selectedItems = [];
1682
+ // If we deleted a folder, notify parent that folder structure changed
1683
+ if (wasFolder) {
1684
+ console.log('[FileGrid] Emitting folderStructureChanged event');
1685
+ this.folderStructureChanged.emit();
1686
+ }
1687
+ // Refresh the file grid
1688
+ console.log('[FileGrid] Calling loadItems() to refresh grid');
1689
+ this.loadItems();
1690
+ }
1691
+ else {
1692
+ console.error('[FileGrid] Delete operation returned false');
1693
+ this.errorMessage = `Failed to delete ${this.itemToDelete.type}`;
1694
+ }
1695
+ }
1696
+ catch (error) {
1697
+ console.error('[FileGrid] Error deleting item:', error);
1698
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1699
+ this.errorMessage = `Failed to delete: ${errorMessage}`;
1700
+ // Clear error after 5 seconds
1701
+ setTimeout(() => {
1702
+ if (this.errorMessage?.startsWith('Failed to delete')) {
1703
+ this.errorMessage = null;
1704
+ }
1705
+ }, 5000);
1706
+ }
1707
+ finally {
1708
+ this.isDeleting = false;
1709
+ }
1710
+ }
1711
+ /**
1712
+ * Opens the rename dialog for the selected item
1713
+ */
1714
+ onRenameClick() {
1715
+ if (this.selectedItems.length !== 1) {
1716
+ return;
1717
+ }
1718
+ // selectedItems contains keys (strings), not full objects
1719
+ // Find the actual item object from the items array
1720
+ const selectedKey = this.selectedItems[0];
1721
+ const item = this.items.find(i => i.key === selectedKey);
1722
+ if (!item) {
1723
+ console.error('[FileGrid] Could not find selected item with key:', selectedKey);
1724
+ return;
1725
+ }
1726
+ this.itemToRename = item;
1727
+ this.newItemName = item.name;
1728
+ this.showRenameDialog = true;
1729
+ }
1730
+ /**
1731
+ * Closes the rename dialog
1732
+ */
1733
+ onCancelRename() {
1734
+ this.showRenameDialog = false;
1735
+ this.itemToRename = null;
1736
+ this.newItemName = '';
1737
+ }
1738
+ /**
1739
+ * Renames the selected item after confirmation
1740
+ */
1741
+ async onConfirmRename() {
1742
+ if (!this.account || !this.itemToRename || !this.newItemName.trim()) {
1743
+ return;
1744
+ }
1745
+ // Check if name actually changed
1746
+ if (this.newItemName.trim() === this.itemToRename.name) {
1747
+ this.onCancelRename();
1748
+ return;
1749
+ }
1750
+ this.isRenaming = true;
1751
+ try {
1752
+ // Construct the old and new paths
1753
+ const oldPath = this.constructItemPath(this.itemToRename);
1754
+ // Build the new path by replacing the old name with the new name
1755
+ const pathParts = oldPath.split('/');
1756
+ pathParts[pathParts.length - 1] = this.newItemName.trim();
1757
+ const newPath = pathParts.join('/');
1758
+ console.log('[FileGrid] Renaming item:', { oldPath, newPath });
1759
+ const success = await this.storageClient.MoveObject(this.account.account.ID, oldPath, newPath);
1760
+ console.log('[FileGrid] Rename result:', { success });
1761
+ if (success) {
1762
+ console.log('[FileGrid] Item renamed successfully:', { oldPath, newPath });
1763
+ // Check if we renamed a folder (before clearing itemToRename)
1764
+ const wasFolder = this.itemToRename.type === 'folder';
1765
+ // Close dialog
1766
+ this.showRenameDialog = false;
1767
+ this.itemToRename = null;
1768
+ this.newItemName = '';
1769
+ // Clear selection
1770
+ this.selectedItems = [];
1771
+ // If we renamed a folder, notify parent that folder structure changed
1772
+ if (wasFolder) {
1773
+ console.log('[FileGrid] Emitting folderStructureChanged event');
1774
+ this.folderStructureChanged.emit();
1775
+ }
1776
+ // Refresh the file grid
1777
+ console.log('[FileGrid] Calling loadItems() to refresh grid');
1778
+ this.loadItems();
1779
+ }
1780
+ else {
1781
+ console.error('[FileGrid] Rename operation returned false');
1782
+ this.errorMessage = `Failed to rename ${this.itemToRename.type}`;
1783
+ }
1784
+ }
1785
+ catch (error) {
1786
+ console.error('[FileGrid] Error renaming item:', error);
1787
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1788
+ this.errorMessage = `Failed to rename: ${errorMessage}`;
1789
+ // Clear error after 5 seconds
1790
+ setTimeout(() => {
1791
+ if (this.errorMessage?.startsWith('Failed to rename')) {
1792
+ this.errorMessage = null;
1793
+ }
1794
+ }, 5000);
1795
+ }
1796
+ finally {
1797
+ this.isRenaming = false;
1798
+ }
1799
+ }
1800
+ /**
1801
+ * Downloads the selected file
1802
+ */
1803
+ async onDownloadClick() {
1804
+ if (this.selectedItems.length !== 1) {
1805
+ return;
1806
+ }
1807
+ // Find the selected item
1808
+ const selectedKey = this.selectedItems[0];
1809
+ const item = this.items.find(i => i.key === selectedKey);
1810
+ if (!item) {
1811
+ console.error('[FileGrid] Could not find selected item with key:', selectedKey);
1812
+ return;
1813
+ }
1814
+ // Can only download files, not folders
1815
+ if (item.type === 'folder') {
1816
+ this.errorMessage = 'Cannot download folders. Please select a file.';
1817
+ setTimeout(() => {
1818
+ if (this.errorMessage?.includes('Cannot download folders')) {
1819
+ this.errorMessage = null;
1820
+ }
1821
+ }, 3000);
1822
+ return;
1823
+ }
1824
+ if (!this.account) {
1825
+ return;
1826
+ }
1827
+ try {
1828
+ const itemPath = this.constructItemPath(item);
1829
+ console.log('[FileGrid] Creating download URL for:', itemPath);
1830
+ const downloadUrl = await this.storageClient.CreatePreAuthDownloadUrl(this.account.account.ID, itemPath);
1831
+ if (downloadUrl) {
1832
+ console.log('[FileGrid] Download URL created, initiating download');
1833
+ // Create a temporary anchor element to trigger download
1834
+ const link = document.createElement('a');
1835
+ link.href = downloadUrl;
1836
+ link.download = item.name;
1837
+ link.style.display = 'none';
1838
+ document.body.appendChild(link);
1839
+ link.click();
1840
+ document.body.removeChild(link);
1841
+ }
1842
+ else {
1843
+ this.errorMessage = 'Failed to create download URL';
1844
+ }
1845
+ }
1846
+ catch (error) {
1847
+ console.error('[FileGrid] Error downloading file:', error);
1848
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1849
+ this.errorMessage = `Failed to download: ${errorMessage}`;
1850
+ // Clear error after 5 seconds
1851
+ setTimeout(() => {
1852
+ if (this.errorMessage?.startsWith('Failed to download')) {
1853
+ this.errorMessage = null;
1854
+ }
1855
+ }, 5000);
1856
+ }
1857
+ }
1858
+ /**
1859
+ * Opens the copy dialog for the selected item
1860
+ */
1861
+ onCopyClick() {
1862
+ if (this.selectedItems.length !== 1) {
1863
+ return;
1864
+ }
1865
+ const selectedKey = this.selectedItems[0];
1866
+ const item = this.items.find(i => i.key === selectedKey);
1867
+ if (!item) {
1868
+ console.error('[FileGrid] Could not find selected item with key:', selectedKey);
1869
+ return;
1870
+ }
1871
+ this.itemToCopy = item;
1872
+ this.copyDestinationPath = this.folderPath + item.name + '-copy';
1873
+ this.showCopyDialog = true;
1874
+ }
1875
+ /**
1876
+ * Cancels the copy operation
1877
+ */
1878
+ onCancelCopy() {
1879
+ this.showCopyDialog = false;
1880
+ this.itemToCopy = null;
1881
+ this.copyDestinationPath = '';
1882
+ }
1883
+ /**
1884
+ * Confirms and executes the copy operation
1885
+ */
1886
+ async onConfirmCopy() {
1887
+ if (!this.account || !this.itemToCopy || !this.copyDestinationPath.trim()) {
1888
+ return;
1889
+ }
1890
+ this.isCopying = true;
1891
+ try {
1892
+ const sourcePath = this.constructItemPath(this.itemToCopy);
1893
+ const success = await this.storageClient.CopyObject(this.account.account.ID, sourcePath, this.copyDestinationPath.trim());
1894
+ if (success) {
1895
+ // Close dialog
1896
+ this.showCopyDialog = false;
1897
+ this.itemToCopy = null;
1898
+ this.copyDestinationPath = '';
1899
+ // Clear selection
1900
+ this.selectedItems = [];
1901
+ // Refresh the file grid
1902
+ this.loadItems();
1903
+ }
1904
+ else {
1905
+ this.errorMessage = 'Failed to copy item';
1906
+ }
1907
+ }
1908
+ catch (error) {
1909
+ console.error('[FileGrid] Error copying item:', error);
1910
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1911
+ this.errorMessage = `Failed to copy: ${errorMessage}`;
1912
+ setTimeout(() => {
1913
+ if (this.errorMessage?.startsWith('Failed to copy')) {
1914
+ this.errorMessage = null;
1915
+ }
1916
+ }, 5000);
1917
+ }
1918
+ finally {
1919
+ this.isCopying = false;
1920
+ }
1921
+ }
1922
+ /**
1923
+ * Opens the move dialog for the selected item
1924
+ */
1925
+ onMoveClick() {
1926
+ if (this.selectedItems.length !== 1) {
1927
+ return;
1928
+ }
1929
+ const selectedKey = this.selectedItems[0];
1930
+ const item = this.items.find(i => i.key === selectedKey);
1931
+ if (!item) {
1932
+ console.error('[FileGrid] Could not find selected item with key:', selectedKey);
1933
+ return;
1934
+ }
1935
+ this.itemToMove = item;
1936
+ // Suggest a different folder path
1937
+ this.moveDestinationPath = this.folderPath;
1938
+ this.showMoveDialog = true;
1939
+ }
1940
+ /**
1941
+ * Cancels the move operation
1942
+ */
1943
+ onCancelMove() {
1944
+ this.showMoveDialog = false;
1945
+ this.itemToMove = null;
1946
+ this.moveDestinationPath = '';
1947
+ }
1948
+ /**
1949
+ * Confirms and executes the move operation
1950
+ */
1951
+ async onConfirmMove() {
1952
+ if (!this.account || !this.itemToMove || !this.moveDestinationPath.trim()) {
1953
+ return;
1954
+ }
1955
+ this.isMoving = true;
1956
+ try {
1957
+ const sourcePath = this.constructItemPath(this.itemToMove);
1958
+ const destPath = this.moveDestinationPath.trim().endsWith('/')
1959
+ ? this.moveDestinationPath.trim() + this.itemToMove.name
1960
+ : this.moveDestinationPath.trim();
1961
+ const success = await this.storageClient.MoveObject(this.account.account.ID, sourcePath, destPath);
1962
+ if (success) {
1963
+ const wasFolder = this.itemToMove.type === 'folder';
1964
+ // Close dialog
1965
+ this.showMoveDialog = false;
1966
+ this.itemToMove = null;
1967
+ this.moveDestinationPath = '';
1968
+ // Clear selection
1969
+ this.selectedItems = [];
1970
+ // If we moved a folder, notify parent that folder structure changed
1971
+ if (wasFolder) {
1972
+ this.folderStructureChanged.emit();
1973
+ }
1974
+ // Refresh the file grid
1975
+ this.loadItems();
1976
+ }
1977
+ else {
1978
+ this.errorMessage = 'Failed to move item';
1979
+ }
1980
+ }
1981
+ catch (error) {
1982
+ console.error('[FileGrid] Error moving item:', error);
1983
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1984
+ this.errorMessage = `Failed to move: ${errorMessage}`;
1985
+ setTimeout(() => {
1986
+ if (this.errorMessage?.startsWith('Failed to move')) {
1987
+ this.errorMessage = null;
1988
+ }
1989
+ }, 5000);
1990
+ }
1991
+ finally {
1992
+ this.isMoving = false;
1993
+ }
1994
+ }
1995
+ /**
1996
+ * Constructs the full path for an item
1997
+ */
1998
+ constructItemPath(item) {
1999
+ // Validate that we have either key or name
2000
+ if (!item.key && !item.name) {
2001
+ console.error('[FileGrid] Cannot construct path - item has no key or name:', item);
2002
+ throw new Error('Cannot construct path for item without key or name');
2003
+ }
2004
+ // If item.key exists and is at root level, use it directly
2005
+ if (!this.folderPath || this.folderPath === '/') {
2006
+ return item.key || item.name;
2007
+ }
2008
+ // If the item key already includes the folder path, use it as is
2009
+ if (item.key && item.key.startsWith(this.folderPath)) {
2010
+ return item.key;
2011
+ }
2012
+ // Otherwise, combine folder path with item name
2013
+ const normalizedFolderPath = this.folderPath.endsWith('/')
2014
+ ? this.folderPath.slice(0, -1)
2015
+ : this.folderPath;
2016
+ // Make sure we have a name to use
2017
+ const itemName = item.name || item.key;
2018
+ if (!itemName) {
2019
+ console.error('[FileGrid] Cannot construct path - item has no usable name:', item);
2020
+ throw new Error('Cannot construct path for item without name');
2021
+ }
2022
+ return `${normalizedFolderPath}/${itemName}`;
2023
+ }
2024
+ /**
2025
+ * Gets the currently selected item (if exactly one is selected)
2026
+ */
2027
+ getSelectedItem() {
2028
+ if (this.selectedItems.length !== 1) {
2029
+ return null;
2030
+ }
2031
+ return this.items.find(item => item.key === this.selectedItems[0]) || null;
2032
+ }
2033
+ /**
2034
+ * Opens the copy to account dialog
2035
+ */
2036
+ async onCopyToAccountClick() {
2037
+ const item = this.getSelectedItem();
2038
+ if (!item || item.type === 'folder') {
2039
+ return;
2040
+ }
2041
+ try {
2042
+ const engine = FileStorageEngine.Instance;
2043
+ await engine.Config(false); // Use cached data if available
2044
+ // Build available accounts (excluding current account)
2045
+ this.availableAccounts = engine.AccountsWithProviders
2046
+ .filter(a => a.account.ID !== this.account?.account.ID);
2047
+ if (this.availableAccounts.length === 0) {
2048
+ this.errorMessage = 'No other storage accounts available';
2049
+ setTimeout(() => {
2050
+ if (this.errorMessage?.includes('No other storage accounts')) {
2051
+ this.errorMessage = null;
2052
+ }
2053
+ }, 3000);
2054
+ return;
2055
+ }
2056
+ this.itemToCopyToProvider = item;
2057
+ this.copyToAccountDestinationPath = item.name; // Default to same filename
2058
+ this.selectedDestinationAccounts.clear();
2059
+ this.copyToAccountProgress = null;
2060
+ this.showCopyToProviderDialog = true;
2061
+ }
2062
+ catch (error) {
2063
+ console.error('[FileGrid] Error loading accounts:', error);
2064
+ this.errorMessage = 'Failed to load storage accounts';
2065
+ }
2066
+ }
2067
+ /**
2068
+ * Cancels the copy to account dialog
2069
+ */
2070
+ onCancelCopyToAccount() {
2071
+ this.showCopyToProviderDialog = false;
2072
+ this.itemToCopyToProvider = null;
2073
+ this.selectedDestinationAccounts.clear();
2074
+ this.copyToAccountDestinationPath = '';
2075
+ this.copyToAccountProgress = null;
2076
+ }
2077
+ /**
2078
+ * Toggles selection of a destination account for copying
2079
+ */
2080
+ toggleDestinationAccount(accountId) {
2081
+ if (this.selectedDestinationAccounts.has(accountId)) {
2082
+ this.selectedDestinationAccounts.delete(accountId);
2083
+ }
2084
+ else {
2085
+ this.selectedDestinationAccounts.add(accountId);
2086
+ }
2087
+ }
2088
+ /**
2089
+ * Checks if an account is selected as a destination
2090
+ */
2091
+ isDestinationAccountSelected(accountId) {
2092
+ return this.selectedDestinationAccounts.has(accountId);
2093
+ }
2094
+ /**
2095
+ * Executes the cross-account copy to multiple selected accounts
2096
+ */
2097
+ async onConfirmCopyToAccount() {
2098
+ if (!this.itemToCopyToProvider || this.selectedDestinationAccounts.size === 0 || !this.account) {
2099
+ return;
2100
+ }
2101
+ this.isCopyingToAccount = true;
2102
+ // Get selected accounts
2103
+ const selectedAccounts = this.availableAccounts.filter(a => this.selectedDestinationAccounts.has(a.account.ID));
2104
+ const successfulCopies = [];
2105
+ const failedCopies = [];
2106
+ try {
2107
+ // Construct source path and normalize it
2108
+ const rawSourcePath = this.constructItemPath(this.itemToCopyToProvider);
2109
+ const sourcePath = rawSourcePath.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/');
2110
+ console.log('[FileGrid] Cross-account copy sourcePath:', { raw: rawSourcePath, normalized: sourcePath });
2111
+ // Copy to each selected account
2112
+ for (let i = 0; i < selectedAccounts.length; i++) {
2113
+ const destAccount = selectedAccounts[i];
2114
+ this.copyToAccountProgress = {
2115
+ current: i + 1,
2116
+ total: selectedAccounts.length,
2117
+ currentAccount: destAccount.account.Name
2118
+ };
2119
+ try {
2120
+ console.log('[FileGrid] Copying to account:', destAccount.account.Name);
2121
+ const copyResult = await this.storageClient.CopyObjectBetweenAccounts(this.account.account.ID, destAccount.account.ID, sourcePath, this.copyToAccountDestinationPath);
2122
+ if (copyResult.success) {
2123
+ successfulCopies.push(destAccount.account.Name);
2124
+ }
2125
+ else {
2126
+ failedCopies.push({ account: destAccount.account.Name, error: copyResult.message });
2127
+ }
2128
+ }
2129
+ catch (error) {
2130
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
2131
+ failedCopies.push({ account: destAccount.account.Name, error: errorMessage });
2132
+ }
2133
+ }
2134
+ // Show results
2135
+ if (failedCopies.length === 0) {
2136
+ this.errorMessage = `Successfully copied to ${successfulCopies.length} account${successfulCopies.length > 1 ? 's' : ''}: ${successfulCopies.join(', ')}`;
2137
+ }
2138
+ else if (successfulCopies.length === 0) {
2139
+ this.errorMessage = `Copy failed for all accounts: ${failedCopies.map(f => `${f.account} (${f.error})`).join(', ')}`;
2140
+ }
2141
+ else {
2142
+ this.errorMessage = `Copied to ${successfulCopies.length} account(s). Failed: ${failedCopies.map(f => f.account).join(', ')}`;
2143
+ }
2144
+ setTimeout(() => {
2145
+ if (this.errorMessage?.includes('copied') || this.errorMessage?.includes('Copy failed')) {
2146
+ this.errorMessage = null;
2147
+ }
2148
+ }, 5000);
2149
+ // Close dialog
2150
+ this.showCopyToProviderDialog = false;
2151
+ this.itemToCopyToProvider = null;
2152
+ this.selectedDestinationAccounts.clear();
2153
+ this.copyToAccountDestinationPath = '';
2154
+ this.copyToAccountProgress = null;
2155
+ }
2156
+ catch (error) {
2157
+ console.error('[FileGrid] Error copying to accounts:', error);
2158
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
2159
+ this.errorMessage = `Copy failed: ${errorMessage}`;
2160
+ setTimeout(() => {
2161
+ if (this.errorMessage?.startsWith('Copy failed')) {
2162
+ this.errorMessage = null;
2163
+ }
2164
+ }, 5000);
2165
+ }
2166
+ finally {
2167
+ this.isCopyingToAccount = false;
2168
+ this.copyToAccountProgress = null;
2169
+ }
2170
+ }
2171
+ // ==========================================
2172
+ // Multi-Account Search Methods
2173
+ // ==========================================
2174
+ /**
2175
+ * Toggles multi-account search mode
2176
+ */
2177
+ toggleMultiAccountSearchMode() {
2178
+ this.isMultiProviderSearchMode = !this.isMultiProviderSearchMode;
2179
+ if (this.isMultiProviderSearchMode) {
2180
+ // Load available accounts if not already loaded
2181
+ if (this.availableAccounts.length === 0) {
2182
+ this.loadAvailableAccountsForSearch();
2183
+ }
2184
+ // Pre-select current account if available
2185
+ if (this.account) {
2186
+ this.selectedSearchProviders.add(this.account.account.ID);
2187
+ }
2188
+ }
2189
+ else {
2190
+ // Clear search results when exiting search mode
2191
+ this.multiProviderSearchResults = null;
2192
+ this.multiProviderSearchQuery = '';
2193
+ }
2194
+ }
2195
+ /**
2196
+ * Loads available accounts for search selection
2197
+ */
2198
+ async loadAvailableAccountsForSearch() {
2199
+ try {
2200
+ const engine = FileStorageEngine.Instance;
2201
+ await engine.Config(false); // Use cached data if available
2202
+ this.availableAccounts = engine.AccountsWithProviders;
2203
+ }
2204
+ catch (error) {
2205
+ console.error('[FileGrid] Error loading accounts for search:', error);
2206
+ }
2207
+ }
2208
+ /**
2209
+ * Toggles account selection for search
2210
+ */
2211
+ toggleSearchAccount(accountID) {
2212
+ if (this.selectedSearchProviders.has(accountID)) {
2213
+ this.selectedSearchProviders.delete(accountID);
2214
+ }
2215
+ else {
2216
+ this.selectedSearchProviders.add(accountID);
2217
+ }
2218
+ }
2219
+ /**
2220
+ * Checks if an account is selected for search
2221
+ */
2222
+ isAccountSelectedForSearch(accountID) {
2223
+ return this.selectedSearchProviders.has(accountID);
2224
+ }
2225
+ /**
2226
+ * Checks if an account's provider supports search
2227
+ */
2228
+ accountSupportsSearch(accountWithProvider) {
2229
+ return accountWithProvider.provider.SupportsSearch === true;
2230
+ }
2231
+ /**
2232
+ * Executes multi-account search
2233
+ */
2234
+ async executeMultiAccountSearch() {
2235
+ if (!this.multiProviderSearchQuery.trim() || this.selectedSearchProviders.size === 0) {
2236
+ return;
2237
+ }
2238
+ this.isSearching = true;
2239
+ this.multiProviderSearchResults = null;
2240
+ try {
2241
+ console.log('[FileGrid] Executing multi-account search:', {
2242
+ accountIds: Array.from(this.selectedSearchProviders),
2243
+ query: this.multiProviderSearchQuery
2244
+ });
2245
+ const searchResult = await this.storageClient.SearchFiles(Array.from(this.selectedSearchProviders), this.multiProviderSearchQuery, { maxResultsPerAccount: 50 });
2246
+ console.log('[FileGrid] Multi-account search result:', searchResult);
2247
+ // Map the client result to the component's expected format
2248
+ this.multiProviderSearchResults = {
2249
+ accountResults: searchResult.accountResults.map((ar) => ({
2250
+ accountID: ar.accountId,
2251
+ accountName: ar.accountName,
2252
+ success: ar.success,
2253
+ errorMessage: ar.errorMessage,
2254
+ results: ar.results.map((r) => ({
2255
+ path: r.path,
2256
+ name: r.name,
2257
+ size: r.size,
2258
+ contentType: r.contentType,
2259
+ lastModified: r.lastModified.toISOString(),
2260
+ relevance: r.relevance,
2261
+ excerpt: r.excerpt,
2262
+ matchInFilename: r.matchInFilename,
2263
+ objectId: r.objectId
2264
+ })),
2265
+ totalMatches: ar.totalMatches,
2266
+ hasMore: ar.hasMore,
2267
+ nextPageToken: ar.nextPageToken
2268
+ })),
2269
+ totalResultsReturned: searchResult.totalResultsReturned,
2270
+ successfulAccounts: searchResult.successfulAccounts,
2271
+ failedAccounts: searchResult.failedAccounts
2272
+ };
2273
+ }
2274
+ catch (error) {
2275
+ console.error('[FileGrid] Error executing multi-provider search:', error);
2276
+ this.errorMessage = 'Search failed. Please try again.';
2277
+ setTimeout(() => {
2278
+ if (this.errorMessage === 'Search failed. Please try again.') {
2279
+ this.errorMessage = null;
2280
+ }
2281
+ }, 5000);
2282
+ }
2283
+ finally {
2284
+ this.isSearching = false;
2285
+ }
2286
+ }
2287
+ /**
2288
+ * Clears multi-provider search results
2289
+ */
2290
+ clearMultiProviderSearch() {
2291
+ this.multiProviderSearchQuery = '';
2292
+ this.multiProviderSearchResults = null;
2293
+ }
2294
+ /**
2295
+ * Gets icon for a search result based on content type
2296
+ */
2297
+ getSearchResultIcon(result) {
2298
+ const extension = result.name.split('.').pop()?.toLowerCase() || '';
2299
+ if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'].includes(extension)) {
2300
+ return 'fa-solid fa-file-image';
2301
+ }
2302
+ else if (['pdf'].includes(extension)) {
2303
+ return 'fa-solid fa-file-pdf';
2304
+ }
2305
+ else if (['doc', 'docx'].includes(extension)) {
2306
+ return 'fa-solid fa-file-word';
2307
+ }
2308
+ else if (['xls', 'xlsx'].includes(extension)) {
2309
+ return 'fa-solid fa-file-excel';
2310
+ }
2311
+ else if (['ppt', 'pptx'].includes(extension)) {
2312
+ return 'fa-solid fa-file-powerpoint';
2313
+ }
2314
+ else if (['zip', 'rar', '7z', 'tar', 'gz'].includes(extension)) {
2315
+ return 'fa-solid fa-file-zipper';
2316
+ }
2317
+ else if (['mp4', 'avi', 'mov', 'wmv'].includes(extension)) {
2318
+ return 'fa-solid fa-file-video';
2319
+ }
2320
+ else if (['mp3', 'wav', 'ogg', 'flac'].includes(extension)) {
2321
+ return 'fa-solid fa-file-audio';
2322
+ }
2323
+ else {
2324
+ return 'fa-solid fa-file';
2325
+ }
2326
+ }
2327
+ /**
2328
+ * Formats file size for search results
2329
+ */
2330
+ formatSearchResultSize(bytes) {
2331
+ return this.formatFileSize(bytes);
2332
+ }
2333
+ /**
2334
+ * Formats date for search results
2335
+ */
2336
+ formatSearchResultDate(dateStr) {
2337
+ return new Date(dateStr).toLocaleString();
2338
+ }
2339
+ static ɵfac = function FileGridComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FileGridComponent)(); };
2340
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileGridComponent, selectors: [["mj-file-grid"]], inputs: { account: "account", folderPath: "folderPath" }, outputs: { folderNavigate: "folderNavigate", folderStructureChanged: "folderStructureChanged" }, features: [i0.ɵɵNgOnChangesFeature], decls: 17, vars: 16, consts: [[1, "file-grid-container", 3, "dragenter", "dragover", "dragleave", "drop"], ["class", "breadcrumb-bar", 4, "ngIf"], ["class", "multi-provider-search-panel", 4, "ngIf"], ["class", "loading-state", 4, "ngIf"], ["class", "error-state", 4, "ngIf"], ["class", "file-table-wrapper", 4, "ngIf"], ["class", "file-grid-wrapper", 4, "ngIf"], ["class", "empty-state", 4, "ngIf"], ["class", "bottom-toolbar", 4, "ngIf"], ["class", "drag-overlay", 4, "ngIf"], ["class", "upload-progress", 4, "ngIf"], ["class", "modal-overlay", 3, "click", 4, "ngIf"], [1, "breadcrumb-bar"], [1, "nav-buttons"], ["title", "Go up to parent folder", 1, "nav-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-arrow-up"], ["title", "Refresh", 1, "nav-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "breadcrumb-path"], [1, "fa-solid", "fa-folder"], [1, "path-text"], [1, "search-bar"], ["type", "text", "placeholder", "Search files and folders...", 1, "search-input", 3, "ngModelChange", "ngModel", "disabled"], ["class", "search-clear-btn", "title", "Clear search", 3, "click", 4, "ngIf"], [1, "file-type-filter", 3, "ngModelChange", "ngModel", "disabled"], ["value", "all"], ["value", "files"], ["value", "folders"], ["title", "Search across all storage providers", 1, "multi-search-btn", 3, "click"], [1, "fa-solid", "fa-magnifying-glass-plus"], ["title", "Clear search", 1, "search-clear-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "multi-provider-search-panel"], [1, "search-panel-header"], [1, "fa-solid", "fa-magnifying-glass"], [1, "close-panel-btn", 3, "click"], [1, "search-panel-body"], [1, "search-input-row"], ["type", "text", "placeholder", "Enter search term...", 1, "multi-search-input", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], [1, "search-execute-btn", 3, "click", "disabled"], ["class", "fa-solid fa-spinner fa-spin", 4, "ngIf"], ["class", "fa-solid fa-search", 4, "ngIf"], [1, "provider-selection"], [1, "provider-selection-label"], [1, "provider-checkboxes"], ["class", "provider-checkbox", 3, "disabled", "title", 4, "ngFor", "ngForOf"], ["class", "search-results-container", 4, "ngIf"], ["class", "searching-state", 4, "ngIf"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-search"], [1, "provider-checkbox", 3, "title"], ["type", "checkbox", 3, "change", "checked", "disabled"], [1, "provider-name"], [1, "provider-type"], ["class", "no-search-badge", 4, "ngIf"], [1, "no-search-badge"], [1, "search-results-container"], [1, "search-results-summary"], [1, "result-count"], [1, "provider-stats"], ["class", "failed-count", 4, "ngIf"], [1, "clear-results-btn", 3, "click"], [1, "provider-results-list"], ["class", "provider-result-group", 3, "failed", 4, "ngFor", "ngForOf"], [1, "failed-count"], [1, "provider-result-group"], [1, "provider-result-header"], [1, "fa-solid", "fa-cloud"], ["class", "result-count", 4, "ngIf"], ["class", "error-badge", 4, "ngIf"], ["class", "provider-result-files", 4, "ngIf"], ["class", "no-results-message", 4, "ngIf"], [1, "error-badge"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "provider-result-files"], ["class", "search-result-item", 4, "ngFor", "ngForOf"], [1, "search-result-item"], [1, "file-icon"], [1, "file-info"], [1, "file-name"], [1, "file-path"], [1, "file-size"], [1, "file-date"], [1, "no-results-message"], [1, "searching-state"], ["text", "Searching across providers..."], [1, "loading-state"], ["text", "Loading files..."], [1, "error-state"], [1, "error-icon"], [1, "fa-solid", "fa-circle-exclamation"], [1, "error-message"], [1, "retry-btn", 3, "click"], [1, "file-table-wrapper"], [1, "file-table"], [1, "col-name", 3, "click"], [1, "fa-solid", "sort-icon"], [1, "col-type"], [1, "col-size", 3, "click"], [1, "col-modified", 3, "click"], ["class", "file-row", 3, "selected", "click", "dblclick", 4, "ngFor", "ngForOf"], [1, "file-row", 3, "click", "dblclick"], [1, "col-name"], [1, "item-icon"], [1, "item-name"], [1, "item-type"], [1, "col-size"], [1, "item-size"], [1, "col-modified"], [1, "item-date"], [1, "file-grid-wrapper"], [1, "file-grid"], ["class", "grid-item", 3, "selected", "click", "dblclick", 4, "ngFor", "ngForOf"], [1, "grid-item", 3, "click", "dblclick"], [1, "grid-icon"], [1, "grid-name"], ["class", "grid-meta", 4, "ngIf"], [1, "grid-meta"], [1, "empty-state"], [1, "empty-icon"], [1, "fa-solid", "fa-folder-open"], [1, "empty-message"], [1, "upload-btn", 3, "click"], [1, "fa-solid", "fa-upload"], [1, "bottom-toolbar"], [1, "toolbar-left"], [1, "toolbar-btn", 3, "click"], [1, "fa-solid", "fa-folder-plus"], [1, "toolbar-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-download"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-copy"], ["title", "Copy file to another storage account", 1, "toolbar-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-cloud-arrow-up"], [1, "fa-solid", "fa-arrows-up-down-left-right"], [1, "fa-solid", "fa-trash"], [1, "toolbar-right"], [1, "view-toggle"], ["title", "List View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Grid View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-th"], [1, "item-count"], [1, "drag-overlay"], [1, "drag-content"], [1, "drag-icon"], [1, "drag-title"], [1, "upload-progress"], [1, "progress-content"], [1, "progress-info"], [1, "progress-bar-wrap"], [1, "progress-bar"], [1, "progress-percent"], [1, "modal-overlay", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "modal-close", 3, "click"], [1, "modal-body"], ["type", "text", "placeholder", "Enter folder name", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], [1, "modal-footer"], [3, "click", "disabled"], ["class", "warning", 4, "ngIf"], [1, "danger", 3, "click", "disabled"], [1, "warning"], ["type", "text", "placeholder", "Enter new name", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], ["type", "text", "placeholder", "Enter destination path", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], ["type", "text", "placeholder", "Enter destination folder (e.g., folder1/folder2/)", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], [2, "font-size", "11px", "color", "#666", "margin-top", "8px"], [2, "font-size", "12px", "color", "#666", "margin-bottom", "16px"], [1, "account-checkbox-list"], ["class", "account-checkbox-item", 4, "ngFor", "ngForOf"], [2, "margin-top", "16px"], ["type", "text", "placeholder", "Enter destination filename", 3, "ngModelChange", "keydown.enter", "ngModel", "disabled"], ["class", "copy-progress", 4, "ngIf"], [1, "account-checkbox-item"], ["type", "checkbox", 3, "change", "id", "checked", "disabled"], [3, "for"], [1, "provider-badge"], [1, "copy-progress"]], template: function FileGridComponent_Template(rf, ctx) { if (rf & 1) {
2341
+ i0.ɵɵelementStart(0, "div", 0);
2342
+ i0.ɵɵlistener("dragenter", function FileGridComponent_Template_div_dragenter_0_listener($event) { return ctx.onDragEnter($event); })("dragover", function FileGridComponent_Template_div_dragover_0_listener($event) { return ctx.onDragOver($event); })("dragleave", function FileGridComponent_Template_div_dragleave_0_listener($event) { return ctx.onDragLeave($event); })("drop", function FileGridComponent_Template_div_drop_0_listener($event) { return ctx.onDrop($event); });
2343
+ i0.ɵɵtemplate(1, FileGridComponent_div_1_Template, 22, 9, "div", 1)(2, FileGridComponent_div_2_Template, 21, 9, "div", 2)(3, FileGridComponent_div_3_Template, 2, 0, "div", 3)(4, FileGridComponent_div_4_Template, 8, 1, "div", 4)(5, FileGridComponent_div_5_Template, 20, 19, "div", 5)(6, FileGridComponent_div_6_Template, 3, 1, "div", 6)(7, FileGridComponent_div_7_Template, 8, 0, "div", 7)(8, FileGridComponent_div_8_Template, 34, 12, "div", 8)(9, FileGridComponent_div_9_Template, 6, 0, "div", 9)(10, FileGridComponent_div_10_Template, 10, 4, "div", 10);
2344
+ i0.ɵɵelementEnd();
2345
+ i0.ɵɵtemplate(11, FileGridComponent_div_11_Template, 17, 6, "div", 11)(12, FileGridComponent_div_12_Template, 20, 7, "div", 11)(13, FileGridComponent_div_13_Template, 17, 7, "div", 11)(14, FileGridComponent_div_14_Template, 21, 8, "div", 11)(15, FileGridComponent_div_15_Template, 23, 10, "div", 11)(16, FileGridComponent_div_16_Template, 30, 10, "div", 11);
2346
+ } if (rf & 2) {
2347
+ i0.ɵɵadvance();
2348
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.errorMessage);
2349
+ i0.ɵɵadvance();
2350
+ i0.ɵɵproperty("ngIf", ctx.isMultiProviderSearchMode);
2351
+ i0.ɵɵadvance();
2352
+ i0.ɵɵproperty("ngIf", ctx.isLoading && !ctx.isMultiProviderSearchMode);
2353
+ i0.ɵɵadvance();
2354
+ i0.ɵɵproperty("ngIf", ctx.errorMessage && !ctx.isLoading);
2355
+ i0.ɵɵadvance();
2356
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.errorMessage && ctx.filteredItems.length > 0 && ctx.viewMode === "list");
2357
+ i0.ɵɵadvance();
2358
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.errorMessage && ctx.filteredItems.length > 0 && ctx.viewMode === "grid");
2359
+ i0.ɵɵadvance();
2360
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.errorMessage && ctx.filteredItems.length === 0);
2361
+ i0.ɵɵadvance();
2362
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.errorMessage);
2363
+ i0.ɵɵadvance();
2364
+ i0.ɵɵproperty("ngIf", ctx.isDragging);
2365
+ i0.ɵɵadvance();
2366
+ i0.ɵɵproperty("ngIf", ctx.isUploading);
2367
+ i0.ɵɵadvance();
2368
+ i0.ɵɵproperty("ngIf", ctx.showNewFolderDialog);
2369
+ i0.ɵɵadvance();
2370
+ i0.ɵɵproperty("ngIf", ctx.showDeleteDialog && ctx.itemToDelete);
2371
+ i0.ɵɵadvance();
2372
+ i0.ɵɵproperty("ngIf", ctx.showRenameDialog && ctx.itemToRename);
2373
+ i0.ɵɵadvance();
2374
+ i0.ɵɵproperty("ngIf", ctx.showCopyDialog && ctx.itemToCopy);
2375
+ i0.ɵɵadvance();
2376
+ i0.ɵɵproperty("ngIf", ctx.showMoveDialog && ctx.itemToMove);
2377
+ i0.ɵɵadvance();
2378
+ i0.ɵɵproperty("ngIf", ctx.showCopyToProviderDialog && ctx.itemToCopyToProvider);
2379
+ } }, dependencies: [i1.NgForOf, i1.NgIf, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.LoadingComponent, i4.LabelDirective], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.file-grid-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n position: relative;\n}\n\n\n\n\n\n\n.breadcrumb-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 6px 10px;\n background-color: #f8f8f8;\n border-bottom: 1px solid #ccc;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.nav-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.nav-btn[_ngcontent-%COMP%] {\n background: #fff;\n border: 1px solid #ccc;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.nav-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #e8e8e8;\n}\n\n.nav-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.breadcrumb-path[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: #333;\n}\n\n.breadcrumb-path[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #666;\n}\n\n.path-text[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.search-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-left: auto;\n position: relative;\n}\n\n.search-input[_ngcontent-%COMP%] {\n padding: 4px 30px 4px 8px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 12px;\n font-family: inherit;\n min-width: 200px;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.search-clear-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 142px;\n background: none;\n border: none;\n cursor: pointer;\n color: #999;\n padding: 4px;\n font-size: 12px;\n}\n\n.search-clear-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.file-type-filter[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 12px;\n font-family: inherit;\n background: #fff;\n cursor: pointer;\n}\n\n.file-type-filter[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n\n\n\n\n\n.file-table-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border-bottom: 1px solid #ccc;\n}\n\n.file-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 12px;\n}\n\n.file-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n background-color: #f0f0f0;\n z-index: 10;\n}\n\n.file-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid #ccc;\n font-weight: 600;\n color: #333;\n cursor: pointer;\n user-select: none;\n}\n\n.file-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:hover {\n background-color: #e8e8e8;\n}\n\n.file-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n margin-right: 4px;\n}\n\n.sort-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #666;\n}\n\n.file-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n border-bottom: 1px solid #e8e8e8;\n cursor: pointer;\n transition: background-color 0.1s;\n}\n\n.file-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: #f8f8f8;\n}\n\n.file-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.selected[_ngcontent-%COMP%] {\n background-color: #cce8ff;\n}\n\n.file-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.selected[_ngcontent-%COMP%]:hover {\n background-color: #b3d9ff;\n}\n\n.file-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 6px 10px;\n color: #333;\n}\n\n\n\n.col-name[_ngcontent-%COMP%] {\n width: 50%;\n}\n\n.col-type[_ngcontent-%COMP%] {\n width: 15%;\n}\n\n.col-size[_ngcontent-%COMP%] {\n width: 15%;\n}\n\n.col-modified[_ngcontent-%COMP%] {\n width: 20%;\n}\n\n\n\n.col-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.item-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #666;\n flex-shrink: 0;\n}\n\n.item-name[_ngcontent-%COMP%] {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.fa-folder[_ngcontent-%COMP%] {\n color: #FFB84D;\n}\n\n\n\n.fa-file-pdf[_ngcontent-%COMP%] {\n color: #D32F2F;\n}\n\n.fa-file-word[_ngcontent-%COMP%] {\n color: #2B579A;\n}\n\n.fa-file-excel[_ngcontent-%COMP%] {\n color: #217346;\n}\n\n.fa-file-image[_ngcontent-%COMP%] {\n color: #673AB7;\n}\n\n.fa-file-video[_ngcontent-%COMP%] {\n color: #F57C00;\n}\n\n.fa-file-audio[_ngcontent-%COMP%] {\n color: #D32F2F;\n}\n\n.fa-file-archive[_ngcontent-%COMP%] {\n color: #795548;\n}\n\n.fa-file-code[_ngcontent-%COMP%] {\n color: #388E3C;\n}\n\n\n\n\n\n\n.file-grid-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 10px;\n border-bottom: 1px solid #ccc;\n}\n\n.file-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.grid-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 12px 8px;\n border: 1px solid #e8e8e8;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n background: #fff;\n}\n\n.grid-item[_ngcontent-%COMP%]:hover {\n background-color: #f8f8f8;\n border-color: #ccc;\n}\n\n.grid-item.selected[_ngcontent-%COMP%] {\n background-color: #cce8ff;\n border-color: #007AFF;\n}\n\n.grid-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 8px;\n color: #666;\n}\n\n.grid-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n display: block;\n}\n\n.grid-name[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #333;\n text-align: center;\n word-break: break-word;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n max-width: 100%;\n}\n\n.grid-meta[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n margin-top: 4px;\n}\n\n\n\n\n\n\n.bottom-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n background-color: #f8f8f8;\n border-top: 1px solid #ccc;\n min-height: 36px;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n}\n\n.toolbar-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #fff;\n border: 1px solid #ccc;\n padding: 5px 12px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.toolbar-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #e8e8e8;\n}\n\n.toolbar-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.toolbar-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n border: 1px solid #ccc;\n border-radius: 3px;\n overflow: hidden;\n}\n\n.view-btn[_ngcontent-%COMP%] {\n background: #fff;\n border: none;\n border-right: 1px solid #ccc;\n padding: 4px 10px;\n cursor: pointer;\n font-size: 12px;\n color: #666;\n transition: all 0.15s;\n}\n\n.view-btn[_ngcontent-%COMP%]:last-child {\n border-right: none;\n}\n\n.view-btn[_ngcontent-%COMP%]:hover {\n background-color: #f0f0f0;\n color: #333;\n}\n\n.view-btn.active[_ngcontent-%COMP%] {\n background-color: #007AFF;\n color: #fff;\n}\n\n.item-count[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n}\n\n\n\n\n\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%], \n.empty-state[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.error-icon[_ngcontent-%COMP%], \n.empty-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: #999;\n margin-bottom: 16px;\n}\n\n.error-message[_ngcontent-%COMP%], \n.empty-message[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #666;\n margin-bottom: 16px;\n}\n\n.retry-btn[_ngcontent-%COMP%], \n.upload-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: #fff;\n border: 1px solid #ccc;\n padding: 8px 16px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 13px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.retry-btn[_ngcontent-%COMP%]:hover, \n.upload-btn[_ngcontent-%COMP%]:hover {\n background-color: #f0f0f0;\n}\n\n\n\n\n\n\n.drag-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.95);\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 3px dashed #007AFF;\n}\n\n.drag-content[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.drag-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n color: #007AFF;\n margin-bottom: 16px;\n}\n\n.drag-title[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 600;\n color: #007AFF;\n margin: 0;\n}\n\n\n\n\n\n\n.upload-progress[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 40px;\n right: 20px;\n background: #fff;\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 12px 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n min-width: 300px;\n z-index: 100;\n}\n\n.progress-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.progress-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #333;\n}\n\n.progress-bar-wrap[_ngcontent-%COMP%] {\n width: 100%;\n height: 6px;\n background-color: #e0e0e0;\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-bar[_ngcontent-%COMP%] {\n height: 100%;\n background-color: #007AFF;\n transition: width 0.3s ease;\n}\n\n.progress-percent[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n text-align: right;\n}\n\n\n\n\n\n\n.modal-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 2000;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: #fff;\n border: 1px solid #999;\n border-radius: 4px;\n min-width: 400px;\n max-width: 90%;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: #f8f8f8;\n border-bottom: 1px solid #ccc;\n}\n\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n}\n\n.modal-close[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 16px;\n color: #666;\n padding: 4px;\n}\n\n.modal-close[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.modal-body[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 12px;\n font-weight: 600;\n color: #333;\n}\n\n.modal-body[_ngcontent-%COMP%] input[type=\"text\"][_ngcontent-%COMP%] {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 13px;\n font-family: inherit;\n}\n\n.modal-body[_ngcontent-%COMP%] input[type=\"text\"][_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.modal-body[_ngcontent-%COMP%] select[_ngcontent-%COMP%], \n.modal-body[_ngcontent-%COMP%] .provider-select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 13px;\n font-family: inherit;\n background-color: #fff;\n cursor: pointer;\n}\n\n.modal-body[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:focus, \n.modal-body[_ngcontent-%COMP%] .provider-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.modal-body[_ngcontent-%COMP%] select[_ngcontent-%COMP%]:disabled, \n.modal-body[_ngcontent-%COMP%] .provider-select[_ngcontent-%COMP%]:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n}\n\n.modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 13px;\n color: #333;\n}\n\n.modal-body[_ngcontent-%COMP%] .warning[_ngcontent-%COMP%] {\n color: #D32F2F;\n font-size: 12px;\n}\n\n\n\n.account-checkbox-list[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 8px;\n background: #fafafa;\n}\n\n.account-checkbox-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border-radius: 3px;\n cursor: pointer;\n}\n\n.account-checkbox-item[_ngcontent-%COMP%]:hover {\n background-color: #e8f4fd;\n}\n\n.account-checkbox-item[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: #007AFF;\n}\n\n.account-checkbox-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n font-weight: normal;\n margin: 0;\n}\n\n.provider-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n background: #e0e0e0;\n padding: 2px 6px;\n border-radius: 10px;\n}\n\n.copy-progress[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 8px 12px;\n background: #e8f4fd;\n border-radius: 4px;\n font-size: 12px;\n color: #0066cc;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n background-color: #f8f8f8;\n border-top: 1px solid #ccc;\n}\n\n.modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n padding: 6px 16px;\n border: 1px solid #ccc;\n background: #fff;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n font-weight: 500;\n transition: background-color 0.15s;\n}\n\n.modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #f0f0f0;\n}\n\n.modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.modal-footer[_ngcontent-%COMP%] button.danger[_ngcontent-%COMP%] {\n background-color: #D32F2F;\n color: #fff;\n border-color: #D32F2F;\n}\n\n.modal-footer[_ngcontent-%COMP%] button.danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #B71C1C;\n}\n\n\n\n\n\n\n.file-table-wrapper[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 12px;\n height: 12px;\n}\n\n.file-table-wrapper[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: #f0f0f0;\n}\n\n.file-table-wrapper[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: #c0c0c0;\n border: 2px solid #f0f0f0;\n}\n\n.file-table-wrapper[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: #a0a0a0;\n}\n\n\n\n\n\n\n@media screen and (max-width: 768px) {\n .file-table[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .file-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .file-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 4px 6px;\n }\n\n .col-type[_ngcontent-%COMP%], \n .col-size[_ngcontent-%COMP%] {\n display: none;\n }\n\n .col-name[_ngcontent-%COMP%] {\n width: 60%;\n }\n\n .col-modified[_ngcontent-%COMP%] {\n width: 40%;\n }\n\n .toolbar-btn[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .modal-dialog[_ngcontent-%COMP%] {\n min-width: 90%;\n }\n}\n\n\n\n\n\n\n.multi-search-btn[_ngcontent-%COMP%] {\n background: #fff;\n border: 1px solid #ccc;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #666;\n transition: all 0.15s;\n}\n\n.multi-search-btn[_ngcontent-%COMP%]:hover {\n background-color: #e8e8e8;\n color: #333;\n}\n\n.multi-search-btn.active[_ngcontent-%COMP%] {\n background-color: #007AFF;\n color: #fff;\n border-color: #007AFF;\n}\n\n.multi-provider-search-panel[_ngcontent-%COMP%] {\n background: #fff;\n border-bottom: 1px solid #ccc;\n display: flex;\n flex-direction: column;\n max-height: 70vh;\n overflow: hidden;\n}\n\n.search-panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 16px;\n background-color: #f0f7ff;\n border-bottom: 1px solid #cce8ff;\n}\n\n.search-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #007AFF;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.close-panel-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 16px;\n color: #666;\n padding: 4px;\n}\n\n.close-panel-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.search-panel-body[_ngcontent-%COMP%] {\n padding: 16px;\n}\n\n.search-input-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.multi-search-input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #ccc;\n border-radius: 4px;\n font-size: 13px;\n font-family: inherit;\n}\n\n.multi-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.search-execute-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #007AFF;\n color: #fff;\n border: none;\n padding: 8px 16px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n transition: background-color 0.15s;\n}\n\n.search-execute-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: #0056b3;\n}\n\n.search-execute-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.provider-selection[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.provider-selection-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #333;\n margin-bottom: 8px;\n}\n\n.provider-checkboxes[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.provider-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #333;\n cursor: pointer;\n padding: 4px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: #fafafa;\n transition: all 0.15s;\n}\n\n.provider-checkbox[_ngcontent-%COMP%]:hover:not(.disabled) {\n border-color: #007AFF;\n background: #f0f7ff;\n}\n\n.provider-checkbox.disabled[_ngcontent-%COMP%] {\n opacity: 0.6;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.provider-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.provider-checkbox[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.no-search-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #999;\n font-style: italic;\n}\n\n\n\n.search-results-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border-top: 1px solid #e0e0e0;\n}\n\n.search-results-summary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 16px;\n background: #f8f8f8;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.search-results-summary[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n}\n\n.search-results-summary[_ngcontent-%COMP%] .provider-stats[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n}\n\n.search-results-summary[_ngcontent-%COMP%] .failed-count[_ngcontent-%COMP%] {\n color: #D32F2F;\n}\n\n.clear-results-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: 1px solid #ccc;\n padding: 4px 10px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 11px;\n color: #666;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.clear-results-btn[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n color: #333;\n}\n\n.provider-results-list[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.provider-result-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.provider-result-group[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.provider-result-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f5f5f5;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n}\n\n.provider-result-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #007AFF;\n}\n\n.provider-result-header[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n font-weight: normal;\n color: #666;\n}\n\n.provider-result-group.failed[_ngcontent-%COMP%] .provider-result-header[_ngcontent-%COMP%] {\n background: #fff5f5;\n}\n\n.provider-result-group.failed[_ngcontent-%COMP%] .provider-result-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #D32F2F;\n}\n\n.error-badge[_ngcontent-%COMP%] {\n color: #D32F2F;\n font-weight: normal;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.provider-result-files[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n.search-result-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 16px 8px 40px;\n border-bottom: 1px solid #f0f0f0;\n cursor: pointer;\n transition: background-color 0.1s;\n}\n\n.search-result-item[_ngcontent-%COMP%]:hover {\n background-color: #f8f8f8;\n}\n\n.search-result-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: #666;\n flex-shrink: 0;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-path[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #999;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-size[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n flex-shrink: 0;\n min-width: 60px;\n text-align: right;\n}\n\n.search-result-item[_ngcontent-%COMP%] .file-date[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n flex-shrink: 0;\n min-width: 140px;\n text-align: right;\n}\n\n.no-results-message[_ngcontent-%COMP%] {\n padding: 16px 40px;\n font-size: 12px;\n color: #999;\n font-style: italic;\n}\n\n.searching-state[_ngcontent-%COMP%] {\n padding: 40px 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}"] });
2380
+ }
2381
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FileGridComponent, [{
2382
+ type: Component,
2383
+ args: [{ selector: 'mj-file-grid', template: "<div class=\"file-grid-container\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <!-- Breadcrumb Navigation Bar -->\n <div class=\"breadcrumb-bar\" *ngIf=\"!isLoading && !errorMessage\">\n <div class=\"nav-buttons\">\n <button class=\"nav-btn\"\n [disabled]=\"!canNavigateUp()\"\n (click)=\"navigateUp()\"\n title=\"Go up to parent folder\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </button>\n <button class=\"nav-btn\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </button>\n </div>\n <div class=\"breadcrumb-path\">\n <i class=\"fa-solid fa-folder\"></i>\n <span class=\"path-text\">{{ folderPath || 'Root' }} /</span>\n </div>\n <div class=\"search-bar\">\n <input type=\"text\"\n class=\"search-input\"\n [(ngModel)]=\"searchQuery\"\n (ngModelChange)=\"onSearchChange($event)\"\n placeholder=\"Search files and folders...\"\n [disabled]=\"isLoading || isMultiProviderSearchMode\">\n <button class=\"search-clear-btn\"\n *ngIf=\"searchQuery && !isMultiProviderSearchMode\"\n (click)=\"clearSearch()\"\n title=\"Clear search\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n <select class=\"file-type-filter\"\n [(ngModel)]=\"fileTypeFilter\"\n (ngModelChange)=\"onFileTypeFilterChange($event)\"\n [disabled]=\"isLoading || isMultiProviderSearchMode\">\n <option value=\"all\">All</option>\n <option value=\"files\">Files</option>\n <option value=\"folders\">Folders</option>\n </select>\n <button class=\"multi-search-btn\"\n [class.active]=\"isMultiProviderSearchMode\"\n (click)=\"toggleMultiAccountSearchMode()\"\n title=\"Search across all storage providers\">\n <i class=\"fa-solid fa-magnifying-glass-plus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Multi-Provider Search Panel -->\n <div class=\"multi-provider-search-panel\" *ngIf=\"isMultiProviderSearchMode\">\n <div class=\"search-panel-header\">\n <h3><i class=\"fa-solid fa-magnifying-glass\"></i> Search Across Providers</h3>\n <button class=\"close-panel-btn\" (click)=\"toggleMultiAccountSearchMode()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <div class=\"search-panel-body\">\n <div class=\"search-input-row\">\n <input type=\"text\"\n class=\"multi-search-input\"\n [(ngModel)]=\"multiProviderSearchQuery\"\n placeholder=\"Enter search term...\"\n (keydown.enter)=\"executeMultiAccountSearch()\"\n [disabled]=\"isSearching\">\n <button class=\"search-execute-btn\"\n (click)=\"executeMultiAccountSearch()\"\n [disabled]=\"isSearching || !multiProviderSearchQuery.trim() || selectedSearchProviders.size === 0\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isSearching\"></i>\n <i class=\"fa-solid fa-search\" *ngIf=\"!isSearching\"></i>\n {{ isSearching ? 'Searching...' : 'Search' }}\n </button>\n </div>\n\n <div class=\"provider-selection\">\n <label class=\"provider-selection-label\">Select accounts to search:</label>\n <div class=\"provider-checkboxes\">\n <label *ngFor=\"let a of availableAccounts\"\n class=\"provider-checkbox\"\n [class.disabled]=\"!accountSupportsSearch(a)\"\n [title]=\"accountSupportsSearch(a) ? '' : 'This account does not support search'\">\n <input type=\"checkbox\"\n [checked]=\"isAccountSelectedForSearch(a.account.ID)\"\n (change)=\"toggleSearchAccount(a.account.ID)\"\n [disabled]=\"!accountSupportsSearch(a)\">\n <span class=\"provider-name\">{{ a.account.Name }}</span>\n <span class=\"provider-type\">({{ a.provider.Name }})</span>\n <span class=\"no-search-badge\" *ngIf=\"!accountSupportsSearch(a)\">(no search)</span>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Search Results -->\n <div class=\"search-results-container\" *ngIf=\"multiProviderSearchResults\">\n <div class=\"search-results-summary\">\n <span class=\"result-count\">{{ multiProviderSearchResults.totalResultsReturned }} result(s) found</span>\n <span class=\"provider-stats\">\n ({{ multiProviderSearchResults.successfulAccounts }} account(s) searched\n <span *ngIf=\"multiProviderSearchResults.failedAccounts > 0\" class=\"failed-count\">\n , {{ multiProviderSearchResults.failedAccounts }} failed\n </span>)\n </span>\n <button class=\"clear-results-btn\" (click)=\"clearMultiProviderSearch()\">\n <i class=\"fa-solid fa-xmark\"></i> Clear\n </button>\n </div>\n\n <div class=\"provider-results-list\">\n <div *ngFor=\"let accountResult of multiProviderSearchResults.accountResults\"\n class=\"provider-result-group\"\n [class.failed]=\"!accountResult.success\">\n <div class=\"provider-result-header\">\n <i class=\"fa-solid fa-cloud\"></i>\n <span class=\"provider-name\">{{ accountResult.accountName }}</span>\n <span class=\"result-count\" *ngIf=\"accountResult.success\">\n ({{ accountResult.results.length }} result(s))\n </span>\n <span class=\"error-badge\" *ngIf=\"!accountResult.success\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ accountResult.errorMessage }}\n </span>\n </div>\n\n <div class=\"provider-result-files\" *ngIf=\"accountResult.success && accountResult.results.length > 0\">\n <div *ngFor=\"let file of accountResult.results\" class=\"search-result-item\">\n <i [class]=\"getSearchResultIcon(file)\" class=\"file-icon\"></i>\n <div class=\"file-info\">\n <span class=\"file-name\">{{ file.name }}</span>\n <span class=\"file-path\">{{ file.path }}</span>\n </div>\n <span class=\"file-size\">{{ formatSearchResultSize(file.size) }}</span>\n <span class=\"file-date\">{{ formatSearchResultDate(file.lastModified) }}</span>\n </div>\n </div>\n\n <div class=\"no-results-message\" *ngIf=\"accountResult.success && accountResult.results.length === 0\">\n No matching files found\n </div>\n </div>\n </div>\n </div>\n\n <!-- Searching State -->\n <div class=\"searching-state\" *ngIf=\"isSearching\">\n <mj-loading text=\"Searching across providers...\"></mj-loading>\n </div>\n </div>\n\n <!-- Loading State -->\n <div class=\"loading-state\" *ngIf=\"isLoading && !isMultiProviderSearchMode\">\n <mj-loading text=\"Loading files...\"></mj-loading>\n </div>\n\n <!-- Error State -->\n <div class=\"error-state\" *ngIf=\"errorMessage && !isLoading\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <p class=\"error-message\">{{ errorMessage }}</p>\n <button class=\"retry-btn\" (click)=\"refresh()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Retry\n </button>\n </div>\n\n <!-- List View -->\n <div class=\"file-table-wrapper\" *ngIf=\"!isLoading && !errorMessage && filteredItems.length > 0 && viewMode === 'list'\">\n <table class=\"file-table\">\n <thead>\n <tr>\n <th class=\"col-name\" (click)=\"onSortChange([{ field: 'name', dir: sort[0]?.field === 'name' && sort[0]?.dir === 'asc' ? 'desc' : 'asc' }])\">\n <span>Name</span>\n <i class=\"fa-solid sort-icon\"\n [class.fa-caret-up]=\"sort[0]?.field === 'name' && sort[0]?.dir === 'asc'\"\n [class.fa-caret-down]=\"sort[0]?.field === 'name' && sort[0]?.dir === 'desc'\"\n [class.fa-sort]=\"sort[0]?.field !== 'name'\"></i>\n </th>\n <th class=\"col-type\">Type</th>\n <th class=\"col-size\" (click)=\"onSortChange([{ field: 'size', dir: sort[0]?.field === 'size' && sort[0]?.dir === 'asc' ? 'desc' : 'asc' }])\">\n <span>Size</span>\n <i class=\"fa-solid sort-icon\"\n [class.fa-caret-up]=\"sort[0]?.field === 'size' && sort[0]?.dir === 'asc'\"\n [class.fa-caret-down]=\"sort[0]?.field === 'size' && sort[0]?.dir === 'desc'\"\n [class.fa-sort]=\"sort[0]?.field !== 'size'\"></i>\n </th>\n <th class=\"col-modified\" (click)=\"onSortChange([{ field: 'lastModified', dir: sort[0]?.field === 'lastModified' && sort[0]?.dir === 'asc' ? 'desc' : 'asc' }])\">\n <span>Modified</span>\n <i class=\"fa-solid sort-icon\"\n [class.fa-caret-up]=\"sort[0]?.field === 'lastModified' && sort[0]?.dir === 'asc'\"\n [class.fa-caret-down]=\"sort[0]?.field === 'lastModified' && sort[0]?.dir === 'desc'\"\n [class.fa-sort]=\"sort[0]?.field !== 'lastModified'\"></i>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let item of filteredItems\"\n class=\"file-row\"\n [class.selected]=\"selectedItems.includes(item.key)\"\n (click)=\"onTileClick(item, $event)\"\n (dblclick)=\"onItemDoubleClick(item)\">\n <td class=\"col-name\">\n <i [class]=\"getItemIcon(item)\" class=\"item-icon\"></i>\n <span class=\"item-name\">{{ item.name }}</span>\n </td>\n <td class=\"col-type\">\n <span class=\"item-type\">{{ getFileType(item) }}</span>\n </td>\n <td class=\"col-size\">\n <span class=\"item-size\">{{ item.type === 'folder' ? '\u2014' : formatFileSize(item.size) }}</span>\n </td>\n <td class=\"col-modified\">\n <span class=\"item-date\">{{ formatDate(item.lastModified) }}</span>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Grid View -->\n <div class=\"file-grid-wrapper\" *ngIf=\"!isLoading && !errorMessage && filteredItems.length > 0 && viewMode === 'grid'\">\n <div class=\"file-grid\">\n <div *ngFor=\"let item of filteredItems\"\n class=\"grid-item\"\n [class.selected]=\"selectedItems.includes(item.key)\"\n (click)=\"onTileClick(item, $event)\"\n (dblclick)=\"onItemDoubleClick(item)\">\n <div class=\"grid-icon\">\n <i [class]=\"getItemIcon(item)\"></i>\n </div>\n <div class=\"grid-name\">{{ item.name }}</div>\n <div class=\"grid-meta\" *ngIf=\"item.type === 'file'\">{{ formatFileSize(item.size) }}</div>\n <div class=\"grid-meta\" *ngIf=\"item.type === 'folder'\">Folder</div>\n </div>\n </div>\n </div>\n\n <!-- Empty State -->\n <div class=\"empty-state\" *ngIf=\"!isLoading && !errorMessage && filteredItems.length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <p class=\"empty-message\">This folder is empty</p>\n <button class=\"upload-btn\" (click)=\"onUploadClick()\">\n <i class=\"fa-solid fa-upload\"></i>\n Upload Files\n </button>\n </div>\n\n <!-- Bottom Toolbar -->\n <div class=\"bottom-toolbar\" *ngIf=\"!isLoading && !errorMessage\">\n <div class=\"toolbar-left\">\n <button class=\"toolbar-btn\" (click)=\"onUploadClick()\">\n <i class=\"fa-solid fa-upload\"></i>\n Upload\n </button>\n <button class=\"toolbar-btn\" (click)=\"onNewFolderClick()\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n New Folder\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length !== 1\"\n (click)=\"onDownloadClick()\">\n <i class=\"fa-solid fa-download\"></i>\n Download\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length !== 1\"\n (click)=\"onRenameClick()\">\n <i class=\"fa-solid fa-pen\"></i>\n Rename\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length !== 1\"\n (click)=\"onCopyClick()\">\n <i class=\"fa-solid fa-copy\"></i>\n Copy\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length !== 1 || getSelectedItem()?.type === 'folder'\"\n (click)=\"onCopyToAccountClick()\"\n title=\"Copy file to another storage account\">\n <i class=\"fa-solid fa-cloud-arrow-up\"></i>\n Copy to...\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length !== 1\"\n (click)=\"onMoveClick()\">\n <i class=\"fa-solid fa-arrows-up-down-left-right\"></i>\n Move\n </button>\n <button class=\"toolbar-btn\"\n [disabled]=\"selectedItems.length === 0\"\n (click)=\"onDeleteClick()\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </button>\n </div>\n <div class=\"toolbar-right\">\n <!-- View Toggle -->\n <div class=\"view-toggle\">\n <button class=\"view-btn\"\n [class.active]=\"viewMode === 'list'\"\n (click)=\"viewMode = 'list'\"\n title=\"List View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button class=\"view-btn\"\n [class.active]=\"viewMode === 'grid'\"\n (click)=\"viewMode = 'grid'\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-th\"></i>\n </button>\n </div>\n <span class=\"item-count\">\n {{ filteredItems.length }} {{ filteredItems.length === 1 ? 'item' : 'filteredItems' }}\n </span>\n </div>\n </div>\n\n <!-- Drag & Drop Overlay -->\n <div class=\"drag-overlay\" *ngIf=\"isDragging\">\n <div class=\"drag-content\">\n <div class=\"drag-icon\">\n <i class=\"fa-solid fa-cloud-arrow-up\"></i>\n </div>\n <h2 class=\"drag-title\">Drop files to upload</h2>\n </div>\n </div>\n\n <!-- Upload Progress -->\n <div class=\"upload-progress\" *ngIf=\"isUploading\">\n <div class=\"progress-content\">\n <div class=\"progress-info\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Uploading {{ uploadingFileName }}...</span>\n </div>\n <div class=\"progress-bar-wrap\">\n <div class=\"progress-bar\" [style.width.%]=\"uploadProgress\"></div>\n </div>\n <span class=\"progress-percent\">{{ uploadProgress }}%</span>\n </div>\n </div>\n</div>\n\n<!-- New Folder Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showNewFolderDialog\" (click)=\"onCancelNewFolder()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Create New Folder</h3>\n <button class=\"modal-close\" (click)=\"onCancelNewFolder()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <label>Folder name:</label>\n <input type=\"text\"\n [(ngModel)]=\"newFolderName\"\n [disabled]=\"isCreatingFolder\"\n placeholder=\"Enter folder name\"\n (keydown.enter)=\"onCreateFolder()\">\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelNewFolder()\" [disabled]=\"isCreatingFolder\">Cancel</button>\n <button (click)=\"onCreateFolder()\" [disabled]=\"!newFolderName.trim() || isCreatingFolder\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isCreatingFolder\"></i>\n {{ isCreatingFolder ? 'Creating...' : 'Create' }}\n </button>\n </div>\n </div>\n</div>\n\n<!-- Delete Confirmation Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showDeleteDialog && itemToDelete\" (click)=\"onCancelDelete()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Delete {{ itemToDelete.type === 'folder' ? 'Folder' : 'File' }}?</h3>\n <button class=\"modal-close\" (click)=\"onCancelDelete()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Are you sure you want to delete <strong>{{ itemToDelete.name }}</strong>?</p>\n <p *ngIf=\"itemToDelete.type === 'folder'\" class=\"warning\">This will delete the folder and all its contents.</p>\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelDelete()\" [disabled]=\"isDeleting\">Cancel</button>\n <button (click)=\"onConfirmDelete()\" [disabled]=\"isDeleting\" class=\"danger\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isDeleting\"></i>\n {{ isDeleting ? 'Deleting...' : 'Delete' }}\n </button>\n </div>\n </div>\n</div>\n\n<!-- Rename Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showRenameDialog && itemToRename\" (click)=\"onCancelRename()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Rename {{ itemToRename.type === 'folder' ? 'Folder' : 'File' }}</h3>\n <button class=\"modal-close\" (click)=\"onCancelRename()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <label>New name:</label>\n <input type=\"text\"\n [(ngModel)]=\"newItemName\"\n [disabled]=\"isRenaming\"\n placeholder=\"Enter new name\"\n (keydown.enter)=\"onConfirmRename()\">\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelRename()\" [disabled]=\"isRenaming\">Cancel</button>\n <button (click)=\"onConfirmRename()\" [disabled]=\"isRenaming || !newItemName.trim()\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isRenaming\"></i>\n {{ isRenaming ? 'Renaming...' : 'Rename' }}\n </button>\n </div>\n </div>\n</div>\n\n<!-- Copy Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showCopyDialog && itemToCopy\" (click)=\"onCancelCopy()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Copy {{ itemToCopy.type === 'folder' ? 'Folder' : 'File' }}</h3>\n <button class=\"modal-close\" (click)=\"onCancelCopy()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Copying: <strong>{{ itemToCopy.name }}</strong></p>\n <label>Destination path:</label>\n <input type=\"text\"\n [(ngModel)]=\"copyDestinationPath\"\n [disabled]=\"isCopying\"\n placeholder=\"Enter destination path\"\n (keydown.enter)=\"onConfirmCopy()\">\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelCopy()\" [disabled]=\"isCopying\">Cancel</button>\n <button (click)=\"onConfirmCopy()\" [disabled]=\"isCopying || !copyDestinationPath.trim()\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isCopying\"></i>\n {{ isCopying ? 'Copying...' : 'Copy' }}\n </button>\n </div>\n </div>\n</div>\n\n<!-- Move Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showMoveDialog && itemToMove\" (click)=\"onCancelMove()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Move {{ itemToMove.type === 'folder' ? 'Folder' : 'File' }}</h3>\n <button class=\"modal-close\" (click)=\"onCancelMove()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Moving: <strong>{{ itemToMove.name }}</strong></p>\n <label>Destination folder path:</label>\n <input type=\"text\"\n [(ngModel)]=\"moveDestinationPath\"\n [disabled]=\"isMoving\"\n placeholder=\"Enter destination folder (e.g., folder1/folder2/)\"\n (keydown.enter)=\"onConfirmMove()\">\n <p style=\"font-size: 11px; color: #666; margin-top: 8px;\">\n File will be moved to: {{ moveDestinationPath }}{{ itemToMove.name }}\n </p>\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelMove()\" [disabled]=\"isMoving\">Cancel</button>\n <button (click)=\"onConfirmMove()\" [disabled]=\"isMoving || !moveDestinationPath.trim()\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isMoving\"></i>\n {{ isMoving ? 'Moving...' : 'Move' }}\n </button>\n </div>\n </div>\n</div>\n\n<!-- Copy to Account Modal -->\n<div class=\"modal-overlay\" *ngIf=\"showCopyToProviderDialog && itemToCopyToProvider\" (click)=\"onCancelCopyToAccount()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3>Copy to Another Account</h3>\n <button class=\"modal-close\" (click)=\"onCancelCopyToAccount()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Copying: <strong>{{ itemToCopyToProvider.name }}</strong></p>\n <p style=\"font-size: 12px; color: #666; margin-bottom: 16px;\">\n From: <strong>{{ account?.account?.Name }}</strong>\n </p>\n\n <label>Select destination account(s):</label>\n <div class=\"account-checkbox-list\">\n <div *ngFor=\"let a of availableAccounts\" class=\"account-checkbox-item\">\n <input type=\"checkbox\"\n [id]=\"'dest-account-' + a.account.ID\"\n [checked]=\"isDestinationAccountSelected(a.account.ID)\"\n [disabled]=\"isCopyingToAccount\"\n (change)=\"toggleDestinationAccount(a.account.ID)\">\n <label [for]=\"'dest-account-' + a.account.ID\">\n {{ a.account.Name }} <span class=\"provider-badge\">{{ a.provider.Name }}</span>\n </label>\n </div>\n </div>\n\n <label style=\"margin-top: 16px;\">Destination filename:</label>\n <input type=\"text\"\n [(ngModel)]=\"copyToAccountDestinationPath\"\n [disabled]=\"isCopyingToAccount\"\n placeholder=\"Enter destination filename\"\n (keydown.enter)=\"onConfirmCopyToAccount()\">\n <div *ngIf=\"copyToAccountProgress\" class=\"copy-progress\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Copying to {{ copyToAccountProgress.currentAccount }} ({{ copyToAccountProgress.current }}/{{ copyToAccountProgress.total }})...\n </div>\n </div>\n <div class=\"modal-footer\">\n <button (click)=\"onCancelCopyToAccount()\" [disabled]=\"isCopyingToAccount\">Cancel</button>\n <button (click)=\"onConfirmCopyToAccount()\"\n [disabled]=\"isCopyingToAccount || selectedDestinationAccounts.size === 0 || !copyToAccountDestinationPath.trim()\">\n <i class=\"fa-solid fa-spinner fa-spin\" *ngIf=\"isCopyingToAccount\"></i>\n {{ isCopyingToAccount ? 'Copying...' : 'Copy to ' + selectedDestinationAccounts.size + ' account' + (selectedDestinationAccounts.size !== 1 ? 's' : '') }}\n </button>\n </div>\n </div>\n</div>\n", styles: ["/* ===========================\n File Grid - Traditional File Manager Style\n =========================== */\n\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.file-grid-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n position: relative;\n}\n\n/* ===========================\n Breadcrumb Navigation Bar\n =========================== */\n\n.breadcrumb-bar {\n display: flex;\n align-items: center;\n padding: 6px 10px;\n background-color: #f8f8f8;\n border-bottom: 1px solid #ccc;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.nav-buttons {\n display: flex;\n gap: 4px;\n}\n\n.nav-btn {\n background: #fff;\n border: 1px solid #ccc;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.nav-btn:hover:not(:disabled) {\n background-color: #e8e8e8;\n}\n\n.nav-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.breadcrumb-path {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: #333;\n}\n\n.breadcrumb-path i {\n color: #666;\n}\n\n.path-text {\n font-weight: 500;\n}\n\n.search-bar {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-left: auto;\n position: relative;\n}\n\n.search-input {\n padding: 4px 30px 4px 8px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 12px;\n font-family: inherit;\n min-width: 200px;\n}\n\n.search-input:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.search-clear-btn {\n position: absolute;\n right: 142px;\n background: none;\n border: none;\n cursor: pointer;\n color: #999;\n padding: 4px;\n font-size: 12px;\n}\n\n.search-clear-btn:hover {\n color: #333;\n}\n\n.file-type-filter {\n padding: 4px 8px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 12px;\n font-family: inherit;\n background: #fff;\n cursor: pointer;\n}\n\n.file-type-filter:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n/* ===========================\n File Table\n =========================== */\n\n.file-table-wrapper {\n flex: 1;\n overflow: auto;\n border-bottom: 1px solid #ccc;\n}\n\n.file-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 12px;\n}\n\n.file-table thead {\n position: sticky;\n top: 0;\n background-color: #f0f0f0;\n z-index: 10;\n}\n\n.file-table th {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid #ccc;\n font-weight: 600;\n color: #333;\n cursor: pointer;\n user-select: none;\n}\n\n.file-table th:hover {\n background-color: #e8e8e8;\n}\n\n.file-table th span {\n margin-right: 4px;\n}\n\n.sort-icon {\n font-size: 10px;\n color: #666;\n}\n\n.file-table tbody tr {\n border-bottom: 1px solid #e8e8e8;\n cursor: pointer;\n transition: background-color 0.1s;\n}\n\n.file-table tbody tr:hover {\n background-color: #f8f8f8;\n}\n\n.file-table tbody tr.selected {\n background-color: #cce8ff;\n}\n\n.file-table tbody tr.selected:hover {\n background-color: #b3d9ff;\n}\n\n.file-table td {\n padding: 6px 10px;\n color: #333;\n}\n\n/* Column Widths */\n.col-name {\n width: 50%;\n}\n\n.col-type {\n width: 15%;\n}\n\n.col-size {\n width: 15%;\n}\n\n.col-modified {\n width: 20%;\n}\n\n/* Name Column with Icon */\n.col-name {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.item-icon {\n font-size: 14px;\n color: #666;\n flex-shrink: 0;\n}\n\n.item-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Folder Icons */\n.fa-folder {\n color: #FFB84D;\n}\n\n/* File Type Icons */\n.fa-file-pdf {\n color: #D32F2F;\n}\n\n.fa-file-word {\n color: #2B579A;\n}\n\n.fa-file-excel {\n color: #217346;\n}\n\n.fa-file-image {\n color: #673AB7;\n}\n\n.fa-file-video {\n color: #F57C00;\n}\n\n.fa-file-audio {\n color: #D32F2F;\n}\n\n.fa-file-archive {\n color: #795548;\n}\n\n.fa-file-code {\n color: #388E3C;\n}\n\n/* ===========================\n Grid View\n =========================== */\n\n.file-grid-wrapper {\n flex: 1;\n overflow: auto;\n padding: 10px;\n border-bottom: 1px solid #ccc;\n}\n\n.file-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 12px 8px;\n border: 1px solid #e8e8e8;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s;\n background: #fff;\n}\n\n.grid-item:hover {\n background-color: #f8f8f8;\n border-color: #ccc;\n}\n\n.grid-item.selected {\n background-color: #cce8ff;\n border-color: #007AFF;\n}\n\n.grid-icon {\n font-size: 48px;\n margin-bottom: 8px;\n color: #666;\n}\n\n.grid-icon i {\n display: block;\n}\n\n.grid-name {\n font-size: 12px;\n color: #333;\n text-align: center;\n word-break: break-word;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n max-width: 100%;\n}\n\n.grid-meta {\n font-size: 11px;\n color: #666;\n margin-top: 4px;\n}\n\n/* ===========================\n Bottom Toolbar\n =========================== */\n\n.bottom-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n background-color: #f8f8f8;\n border-top: 1px solid #ccc;\n min-height: 36px;\n}\n\n.toolbar-left {\n display: flex;\n gap: 6px;\n}\n\n.toolbar-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #fff;\n border: 1px solid #ccc;\n padding: 5px 12px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.toolbar-btn:hover:not(:disabled) {\n background-color: #e8e8e8;\n}\n\n.toolbar-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.toolbar-btn i {\n font-size: 12px;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.view-toggle {\n display: flex;\n border: 1px solid #ccc;\n border-radius: 3px;\n overflow: hidden;\n}\n\n.view-btn {\n background: #fff;\n border: none;\n border-right: 1px solid #ccc;\n padding: 4px 10px;\n cursor: pointer;\n font-size: 12px;\n color: #666;\n transition: all 0.15s;\n}\n\n.view-btn:last-child {\n border-right: none;\n}\n\n.view-btn:hover {\n background-color: #f0f0f0;\n color: #333;\n}\n\n.view-btn.active {\n background-color: #007AFF;\n color: #fff;\n}\n\n.item-count {\n font-size: 11px;\n color: #666;\n}\n\n/* ===========================\n Loading / Error / Empty States\n =========================== */\n\n.loading-state,\n.error-state,\n.empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.error-icon,\n.empty-icon {\n font-size: 48px;\n color: #999;\n margin-bottom: 16px;\n}\n\n.error-message,\n.empty-message {\n font-size: 14px;\n color: #666;\n margin-bottom: 16px;\n}\n\n.retry-btn,\n.upload-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n background: #fff;\n border: 1px solid #ccc;\n padding: 8px 16px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 13px;\n color: #333;\n transition: background-color 0.15s;\n}\n\n.retry-btn:hover,\n.upload-btn:hover {\n background-color: #f0f0f0;\n}\n\n/* ===========================\n Drag & Drop Overlay\n =========================== */\n\n.drag-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(255, 255, 255, 0.95);\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 3px dashed #007AFF;\n}\n\n.drag-content {\n text-align: center;\n}\n\n.drag-icon {\n font-size: 64px;\n color: #007AFF;\n margin-bottom: 16px;\n}\n\n.drag-title {\n font-size: 20px;\n font-weight: 600;\n color: #007AFF;\n margin: 0;\n}\n\n/* ===========================\n Upload Progress\n =========================== */\n\n.upload-progress {\n position: absolute;\n bottom: 40px;\n right: 20px;\n background: #fff;\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 12px 16px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n min-width: 300px;\n z-index: 100;\n}\n\n.progress-content {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.progress-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #333;\n}\n\n.progress-bar-wrap {\n width: 100%;\n height: 6px;\n background-color: #e0e0e0;\n border-radius: 3px;\n overflow: hidden;\n}\n\n.progress-bar {\n height: 100%;\n background-color: #007AFF;\n transition: width 0.3s ease;\n}\n\n.progress-percent {\n font-size: 12px;\n color: #666;\n text-align: right;\n}\n\n/* ===========================\n Modal Dialogs\n =========================== */\n\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 2000;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-dialog {\n background: #fff;\n border: 1px solid #999;\n border-radius: 4px;\n min-width: 400px;\n max-width: 90%;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n}\n\n.modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: #f8f8f8;\n border-bottom: 1px solid #ccc;\n}\n\n.modal-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n}\n\n.modal-close {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 16px;\n color: #666;\n padding: 4px;\n}\n\n.modal-close:hover {\n color: #333;\n}\n\n.modal-body {\n padding: 16px;\n}\n\n.modal-body label {\n display: block;\n margin-bottom: 6px;\n font-size: 12px;\n font-weight: 600;\n color: #333;\n}\n\n.modal-body input[type=\"text\"] {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 13px;\n font-family: inherit;\n}\n\n.modal-body input[type=\"text\"]:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.modal-body select,\n.modal-body .provider-select {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid #ccc;\n border-radius: 3px;\n font-size: 13px;\n font-family: inherit;\n background-color: #fff;\n cursor: pointer;\n}\n\n.modal-body select:focus,\n.modal-body .provider-select:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.modal-body select:disabled,\n.modal-body .provider-select:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n}\n\n.modal-body p {\n margin: 0 0 12px 0;\n font-size: 13px;\n color: #333;\n}\n\n.modal-body .warning {\n color: #D32F2F;\n font-size: 12px;\n}\n\n/* Checkbox list for multi-account selection */\n.account-checkbox-list {\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n border-radius: 4px;\n padding: 8px;\n background: #fafafa;\n}\n\n.account-checkbox-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border-radius: 3px;\n cursor: pointer;\n}\n\n.account-checkbox-item:hover {\n background-color: #e8f4fd;\n}\n\n.account-checkbox-item input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n accent-color: #007AFF;\n}\n\n.account-checkbox-item label {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n font-weight: normal;\n margin: 0;\n}\n\n.provider-badge {\n font-size: 11px;\n color: #666;\n background: #e0e0e0;\n padding: 2px 6px;\n border-radius: 10px;\n}\n\n.copy-progress {\n margin-top: 12px;\n padding: 8px 12px;\n background: #e8f4fd;\n border-radius: 4px;\n font-size: 12px;\n color: #0066cc;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n background-color: #f8f8f8;\n border-top: 1px solid #ccc;\n}\n\n.modal-footer button {\n padding: 6px 16px;\n border: 1px solid #ccc;\n background: #fff;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n font-weight: 500;\n transition: background-color 0.15s;\n}\n\n.modal-footer button:hover:not(:disabled) {\n background-color: #f0f0f0;\n}\n\n.modal-footer button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.modal-footer button.danger {\n background-color: #D32F2F;\n color: #fff;\n border-color: #D32F2F;\n}\n\n.modal-footer button.danger:hover:not(:disabled) {\n background-color: #B71C1C;\n}\n\n/* ===========================\n Scrollbars\n =========================== */\n\n.file-table-wrapper::-webkit-scrollbar {\n width: 12px;\n height: 12px;\n}\n\n.file-table-wrapper::-webkit-scrollbar-track {\n background: #f0f0f0;\n}\n\n.file-table-wrapper::-webkit-scrollbar-thumb {\n background: #c0c0c0;\n border: 2px solid #f0f0f0;\n}\n\n.file-table-wrapper::-webkit-scrollbar-thumb:hover {\n background: #a0a0a0;\n}\n\n/* ===========================\n Responsive Design\n =========================== */\n\n@media screen and (max-width: 768px) {\n .file-table {\n font-size: 11px;\n }\n\n .file-table th,\n .file-table td {\n padding: 4px 6px;\n }\n\n .col-type,\n .col-size {\n display: none;\n }\n\n .col-name {\n width: 60%;\n }\n\n .col-modified {\n width: 40%;\n }\n\n .toolbar-btn span {\n display: none;\n }\n\n .modal-dialog {\n min-width: 90%;\n }\n}\n\n/* ===========================\n Multi-Provider Search\n =========================== */\n\n.multi-search-btn {\n background: #fff;\n border: 1px solid #ccc;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 12px;\n color: #666;\n transition: all 0.15s;\n}\n\n.multi-search-btn:hover {\n background-color: #e8e8e8;\n color: #333;\n}\n\n.multi-search-btn.active {\n background-color: #007AFF;\n color: #fff;\n border-color: #007AFF;\n}\n\n.multi-provider-search-panel {\n background: #fff;\n border-bottom: 1px solid #ccc;\n display: flex;\n flex-direction: column;\n max-height: 70vh;\n overflow: hidden;\n}\n\n.search-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 16px;\n background-color: #f0f7ff;\n border-bottom: 1px solid #cce8ff;\n}\n\n.search-panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #007AFF;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.close-panel-btn {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 16px;\n color: #666;\n padding: 4px;\n}\n\n.close-panel-btn:hover {\n color: #333;\n}\n\n.search-panel-body {\n padding: 16px;\n}\n\n.search-input-row {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.multi-search-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #ccc;\n border-radius: 4px;\n font-size: 13px;\n font-family: inherit;\n}\n\n.multi-search-input:focus {\n outline: none;\n border-color: #007AFF;\n}\n\n.search-execute-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: #007AFF;\n color: #fff;\n border: none;\n padding: 8px 16px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n transition: background-color 0.15s;\n}\n\n.search-execute-btn:hover:not(:disabled) {\n background-color: #0056b3;\n}\n\n.search-execute-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.provider-selection {\n margin-bottom: 8px;\n}\n\n.provider-selection-label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #333;\n margin-bottom: 8px;\n}\n\n.provider-checkboxes {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.provider-checkbox {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #333;\n cursor: pointer;\n padding: 4px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: #fafafa;\n transition: all 0.15s;\n}\n\n.provider-checkbox:hover:not(.disabled) {\n border-color: #007AFF;\n background: #f0f7ff;\n}\n\n.provider-checkbox.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.provider-checkbox input[type=\"checkbox\"] {\n cursor: pointer;\n}\n\n.provider-checkbox .provider-name {\n font-weight: 500;\n}\n\n.no-search-badge {\n font-size: 10px;\n color: #999;\n font-style: italic;\n}\n\n/* Search Results */\n.search-results-container {\n flex: 1;\n overflow: auto;\n border-top: 1px solid #e0e0e0;\n}\n\n.search-results-summary {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 16px;\n background: #f8f8f8;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.search-results-summary .result-count {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n}\n\n.search-results-summary .provider-stats {\n font-size: 12px;\n color: #666;\n}\n\n.search-results-summary .failed-count {\n color: #D32F2F;\n}\n\n.clear-results-btn {\n margin-left: auto;\n background: none;\n border: 1px solid #ccc;\n padding: 4px 10px;\n cursor: pointer;\n border-radius: 3px;\n font-size: 11px;\n color: #666;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.clear-results-btn:hover {\n background: #f0f0f0;\n color: #333;\n}\n\n.provider-results-list {\n padding: 8px 0;\n}\n\n.provider-result-group {\n margin-bottom: 16px;\n}\n\n.provider-result-group:last-child {\n margin-bottom: 0;\n}\n\n.provider-result-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f5f5f5;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n}\n\n.provider-result-header i {\n color: #007AFF;\n}\n\n.provider-result-header .result-count {\n font-weight: normal;\n color: #666;\n}\n\n.provider-result-group.failed .provider-result-header {\n background: #fff5f5;\n}\n\n.provider-result-group.failed .provider-result-header i {\n color: #D32F2F;\n}\n\n.error-badge {\n color: #D32F2F;\n font-weight: normal;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.provider-result-files {\n padding: 0;\n}\n\n.search-result-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 16px 8px 40px;\n border-bottom: 1px solid #f0f0f0;\n cursor: pointer;\n transition: background-color 0.1s;\n}\n\n.search-result-item:hover {\n background-color: #f8f8f8;\n}\n\n.search-result-item:last-child {\n border-bottom: none;\n}\n\n.search-result-item .file-icon {\n font-size: 16px;\n color: #666;\n flex-shrink: 0;\n}\n\n.search-result-item .file-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.search-result-item .file-name {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.search-result-item .file-path {\n font-size: 11px;\n color: #999;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.search-result-item .file-size {\n font-size: 12px;\n color: #666;\n flex-shrink: 0;\n min-width: 60px;\n text-align: right;\n}\n\n.search-result-item .file-date {\n font-size: 12px;\n color: #666;\n flex-shrink: 0;\n min-width: 140px;\n text-align: right;\n}\n\n.no-results-message {\n padding: 16px 40px;\n font-size: 12px;\n color: #999;\n font-style: italic;\n}\n\n.searching-state {\n padding: 40px 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n"] }]
2384
+ }], () => [], { account: [{
2385
+ type: Input
2386
+ }], folderPath: [{
2387
+ type: Input
2388
+ }], folderNavigate: [{
2389
+ type: Output
2390
+ }], folderStructureChanged: [{
2391
+ type: Output
2392
+ }] }); })();
2393
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FileGridComponent, { className: "FileGridComponent", filePath: "src/lib/file-browser/file-grid.component.ts", lineNumber: 67 }); })();
2394
+ //# sourceMappingURL=file-grid.component.js.map