@memberjunction/ng-file-storage 5.42.0 → 5.44.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.
@@ -3,65 +3,52 @@ import { FileStorageEngineBase } from '@memberjunction/core-entities';
3
3
  import { UUIDsEqual } from '@memberjunction/global';
4
4
  import * as i0 from "@angular/core";
5
5
  import * as i1 from "@memberjunction/ng-shared-generic";
6
+ import * as i2 from "@memberjunction/ng-ui-components";
6
7
  function StorageProvidersListComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
7
8
  i0.ɵɵelementStart(0, "div", 3);
8
9
  i0.ɵɵelement(1, "mj-loading", 7);
9
10
  i0.ɵɵelementEnd();
10
11
  } }
11
12
  function StorageProvidersListComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
12
- i0.ɵɵelementStart(0, "div", 4)(1, "div", 8);
13
- i0.ɵɵelement(2, "i", 9);
14
- i0.ɵɵelementEnd();
15
- i0.ɵɵelementStart(3, "p", 10);
16
- i0.ɵɵtext(4);
17
- i0.ɵɵelementEnd()();
13
+ i0.ɵɵelement(0, "mj-empty-state", 4);
18
14
  } if (rf & 2) {
19
15
  const ctx_r0 = i0.ɵɵnextContext();
20
- i0.ɵɵadvance(4);
21
- i0.ɵɵtextInterpolate(ctx_r0.errorMessage);
16
+ i0.ɵɵproperty("Title", ctx_r0.errorMessage);
22
17
  } }
23
18
  function StorageProvidersListComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelementStart(0, "div", 5)(1, "div", 11);
25
- i0.ɵɵelement(2, "i", 12);
26
- i0.ɵɵelementEnd();
27
- i0.ɵɵelementStart(3, "p", 13);
28
- i0.ɵɵtext(4, "No storage accounts configured");
29
- i0.ɵɵelementEnd();
30
- i0.ɵɵelementStart(5, "p", 14);
31
- i0.ɵɵtext(6, "Contact your administrator to set up file storage accounts");
32
- i0.ɵɵelementEnd()();
19
+ i0.ɵɵelement(0, "mj-empty-state", 5);
33
20
  } }
34
21
  function StorageProvidersListComponent_Conditional_7_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
35
- i0.ɵɵelementStart(0, "span", 22);
36
- i0.ɵɵelement(1, "i", 25);
22
+ i0.ɵɵelementStart(0, "span", 15);
23
+ i0.ɵɵelement(1, "i", 18);
37
24
  i0.ɵɵelementEnd();
38
25
  } }
39
26
  function StorageProvidersListComponent_Conditional_7_For_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
40
- i0.ɵɵelementStart(0, "span", 23);
41
- i0.ɵɵelement(1, "i", 26);
27
+ i0.ɵɵelementStart(0, "span", 16);
28
+ i0.ɵɵelement(1, "i", 19);
42
29
  i0.ɵɵelementEnd();
43
30
  } }
44
31
  function StorageProvidersListComponent_Conditional_7_For_2_Conditional_11_Template(rf, ctx) { if (rf & 1) {
45
- i0.ɵɵelementStart(0, "span", 24);
46
- i0.ɵɵelement(1, "i", 27);
32
+ i0.ɵɵelementStart(0, "span", 17);
33
+ i0.ɵɵelement(1, "i", 20);
47
34
  i0.ɵɵelementEnd();
48
35
  } }
49
36
  function StorageProvidersListComponent_Conditional_7_For_2_Template(rf, ctx) { if (rf & 1) {
50
37
  const _r2 = i0.ɵɵgetCurrentView();
51
- i0.ɵɵelementStart(0, "div", 16);
38
+ i0.ɵɵelementStart(0, "div", 9);
52
39
  i0.ɵɵlistener("click", function StorageProvidersListComponent_Conditional_7_For_2_Template_div_click_0_listener() { const item_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.selectAccount(item_r3)); });
53
- i0.ɵɵelementStart(1, "div", 17);
40
+ i0.ɵɵelementStart(1, "div", 10);
54
41
  i0.ɵɵelement(2, "i");
55
42
  i0.ɵɵelementEnd();
56
- i0.ɵɵelementStart(3, "div", 18)(4, "div", 19);
43
+ i0.ɵɵelementStart(3, "div", 11)(4, "div", 12);
57
44
  i0.ɵɵtext(5);
58
45
  i0.ɵɵelementEnd();
59
- i0.ɵɵelementStart(6, "div", 20)(7, "span", 21);
46
+ i0.ɵɵelementStart(6, "div", 13)(7, "span", 14);
60
47
  i0.ɵɵtext(8);
61
48
  i0.ɵɵelementEnd();
62
- i0.ɵɵconditionalCreate(9, StorageProvidersListComponent_Conditional_7_For_2_Conditional_9_Template, 2, 0, "span", 22);
63
- i0.ɵɵconditionalCreate(10, StorageProvidersListComponent_Conditional_7_For_2_Conditional_10_Template, 2, 0, "span", 23);
64
- i0.ɵɵconditionalCreate(11, StorageProvidersListComponent_Conditional_7_For_2_Conditional_11_Template, 2, 0, "span", 24);
49
+ i0.ɵɵconditionalCreate(9, StorageProvidersListComponent_Conditional_7_For_2_Conditional_9_Template, 2, 0, "span", 15);
50
+ i0.ɵɵconditionalCreate(10, StorageProvidersListComponent_Conditional_7_For_2_Conditional_10_Template, 2, 0, "span", 16);
51
+ i0.ɵɵconditionalCreate(11, StorageProvidersListComponent_Conditional_7_For_2_Conditional_11_Template, 2, 0, "span", 17);
65
52
  i0.ɵɵelementEnd()()();
66
53
  } if (rf & 2) {
67
54
  const item_r3 = ctx.$implicit;
@@ -85,7 +72,7 @@ function StorageProvidersListComponent_Conditional_7_For_2_Template(rf, ctx) { i
85
72
  } }
86
73
  function StorageProvidersListComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
87
74
  i0.ɵɵelementStart(0, "div", 6);
88
- i0.ɵɵrepeaterCreate(1, StorageProvidersListComponent_Conditional_7_For_2_Template, 12, 11, "div", 15, i0.ɵɵrepeaterTrackByIdentity);
75
+ i0.ɵɵrepeaterCreate(1, StorageProvidersListComponent_Conditional_7_For_2_Template, 12, 11, "div", 8, i0.ɵɵrepeaterTrackByIdentity);
89
76
  i0.ɵɵelementEnd();
90
77
  } if (rf & 2) {
91
78
  const ctx_r0 = i0.ɵɵnextContext();
@@ -211,13 +198,13 @@ export class StorageProvidersListComponent {
211
198
  FileStorageEngineBase.Instance.Config(true).then(() => this.loadAccounts());
212
199
  }
213
200
  static ɵfac = function StorageProvidersListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || StorageProvidersListComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
214
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: StorageProvidersListComponent, selectors: [["mj-storage-providers-list"]], outputs: { accountSelected: "accountSelected" }, standalone: false, decls: 8, vars: 4, consts: [[1, "providers-list"], [1, "providers-header"], [1, "header-title"], [1, "loading-state"], [1, "error-state"], [1, "empty-state"], [1, "providers-container"], ["text", "Loading accounts..."], [1, "error-icon"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "error-message"], [1, "empty-icon"], [1, "fa-solid", "fa-folder-plus"], [1, "empty-message"], [1, "empty-hint"], [1, "provider-item", 3, "selected", "title"], [1, "provider-item", 3, "click", "title"], [1, "provider-icon"], [1, "provider-info"], [1, "provider-name"], [1, "provider-meta"], [1, "provider-type-badge", 3, "title"], ["title", "Supports search", 1, "search-badge"], ["title", "Credentials configured", 1, "credential-badge"], ["title", "No credentials configured", 1, "unconfigured-badge"], [1, "fa-solid", "fa-magnifying-glass"], [1, "fa-solid", "fa-key"], [1, "fa-solid", "fa-exclamation-triangle"]], template: function StorageProvidersListComponent_Template(rf, ctx) { if (rf & 1) {
201
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: StorageProvidersListComponent, selectors: [["mj-storage-providers-list"]], outputs: { accountSelected: "accountSelected" }, standalone: false, decls: 8, vars: 4, consts: [[1, "providers-list"], [1, "providers-header"], [1, "header-title"], [1, "loading-state"], ["Variant", "error", "Icon", "fa-solid fa-triangle-exclamation", "Size", "compact", 1, "storage-providers-empty-fill", 3, "Title"], ["Icon", "fa-solid fa-folder-plus", "Title", "No storage accounts configured", "Message", "Contact your administrator to set up file storage accounts", "Size", "compact", 1, "storage-providers-empty-fill"], [1, "providers-container"], ["text", "Loading accounts..."], [1, "provider-item", 3, "selected", "title"], [1, "provider-item", 3, "click", "title"], [1, "provider-icon"], [1, "provider-info"], [1, "provider-name"], [1, "provider-meta"], [1, "provider-type-badge", 3, "title"], ["title", "Supports search", 1, "search-badge"], ["title", "Credentials configured", 1, "credential-badge"], ["title", "No credentials configured", 1, "unconfigured-badge"], [1, "fa-solid", "fa-magnifying-glass"], [1, "fa-solid", "fa-key"], [1, "fa-solid", "fa-exclamation-triangle"]], template: function StorageProvidersListComponent_Template(rf, ctx) { if (rf & 1) {
215
202
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "span", 2);
216
203
  i0.ɵɵtext(3, "Storage Accounts");
217
204
  i0.ɵɵelementEnd()();
218
205
  i0.ɵɵconditionalCreate(4, StorageProvidersListComponent_Conditional_4_Template, 2, 0, "div", 3);
219
- i0.ɵɵconditionalCreate(5, StorageProvidersListComponent_Conditional_5_Template, 5, 1, "div", 4);
220
- i0.ɵɵconditionalCreate(6, StorageProvidersListComponent_Conditional_6_Template, 7, 0, "div", 5);
206
+ i0.ɵɵconditionalCreate(5, StorageProvidersListComponent_Conditional_5_Template, 1, 1, "mj-empty-state", 4);
207
+ i0.ɵɵconditionalCreate(6, StorageProvidersListComponent_Conditional_6_Template, 1, 0, "mj-empty-state", 5);
221
208
  i0.ɵɵconditionalCreate(7, StorageProvidersListComponent_Conditional_7_Template, 3, 0, "div", 6);
222
209
  i0.ɵɵelementEnd();
223
210
  } if (rf & 2) {
@@ -229,11 +216,11 @@ export class StorageProvidersListComponent {
229
216
  i0.ɵɵconditional(!ctx.isLoading && !ctx.errorMessage && ctx.accounts.length === 0 ? 6 : -1);
230
217
  i0.ɵɵadvance();
231
218
  i0.ɵɵconditional(!ctx.isLoading && !ctx.errorMessage && ctx.accounts.length > 0 ? 7 : -1);
232
- } }, dependencies: [i1.LoadingComponent], styles: ["\n\n\n\n\n.providers-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n\n\n.providers-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.header-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.add-provider-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 14px;\n}\n\n.add-provider-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n\n.add-provider-btn[_ngcontent-%COMP%]:disabled {\n background-color: var(--mj-border-strong);\n cursor: not-allowed;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%], \n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px;\n text-align: center;\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n.error-icon[_ngcontent-%COMP%], \n.empty-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.7;\n}\n\n.error-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.error-message[_ngcontent-%COMP%], \n.empty-message[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n margin: 0 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.empty-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin: 4px 0 0 0;\n max-width: 180px;\n line-height: 1.4;\n}\n\n\n\n.providers-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n\n\n.provider-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n position: relative;\n}\n\n.provider-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-card);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.provider-item.selected[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: var(--mj-brand-primary);\n}\n\n\n\n.provider-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: var(--mj-text-secondary);\n margin-right: 12px;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n\n.provider-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.provider-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.provider-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n\n\n.default-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.default-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.provider-type-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-type-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n\n\n.search-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .search-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.search-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.credential-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .credential-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n color: var(--mj-status-success);\n}\n\n.credential-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.unconfigured-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.unconfigured-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.oauth-connected-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.oauth-connected-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.oauth-disconnected-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-warning);\n}\n\n.oauth-disconnected-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.provider-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: 8px;\n}\n\n.connect-btn[_ngcontent-%COMP%], \n.disconnect-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n}\n\n.connect-btn[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.connect-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n transform: scale(1.05);\n}\n\n.connect-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.disconnect-btn[_ngcontent-%COMP%] {\n background-color: transparent;\n color: var(--mj-text-muted);\n}\n\n.disconnect-btn[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n\n\n.remove-provider-btn[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 50%;\n background-color: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n opacity: 0;\n margin-left: 8px;\n}\n\n.provider-item[_ngcontent-%COMP%]:hover .remove-provider-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.remove-provider-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.remove-provider-btn[_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n\n\n\n.add-provider-dialog[_ngcontent-%COMP%] {\n min-height: 150px;\n}\n\n.dialog-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.dialog-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 30px 20px;\n text-align: center;\n}\n\n.dialog-empty-icon[_ngcontent-%COMP%] {\n font-size: 40px;\n color: var(--mj-status-success);\n margin-bottom: 12px;\n}\n\n.dialog-empty-message[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.dialog-empty-hint[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n.dialog-instruction[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n padding: 0 4px;\n}\n\n.available-providers[_ngcontent-%COMP%] {\n max-height: 350px;\n overflow-y: auto;\n}\n\n.available-provider-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.available-provider-item[_ngcontent-%COMP%]:hover:not(.disabled) {\n background-color: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n}\n\n.available-provider-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--mj-bg-surface-card);\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-icon[_ngcontent-%COMP%] {\n margin-right: 12px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n line-height: 1.3;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-warning[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-status-warning);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.available-provider-item[_ngcontent-%COMP%] .oauth-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .oauth-hint[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.available-provider-item.oauth-provider[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n}\n\n.available-provider-item.oauth-provider[_ngcontent-%COMP%]:hover:not(.disabled) {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.add-indicator[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n\n\n@media screen and (max-width: 768px) {\n .providers-header[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .header-title[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .add-provider-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n font-size: 12px;\n }\n\n .provider-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .provider-icon[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n font-size: 18px;\n margin-right: 10px;\n }\n\n .provider-name[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .provider-status[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .remove-provider-btn[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n font-size: 11px;\n opacity: 1;\n }\n}"] });
219
+ } }, dependencies: [i1.LoadingComponent, i2.MJEmptyStateComponent], styles: ["\n\n\n\n\n.providers-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n\n\n.providers-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.header-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.add-provider-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 14px;\n}\n\n.add-provider-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n\n.add-provider-btn[_ngcontent-%COMP%]:disabled {\n background-color: var(--mj-border-strong);\n cursor: not-allowed;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px;\n text-align: center;\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n\n\n.storage-providers-empty-fill[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.providers-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n\n\n.provider-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n position: relative;\n}\n\n.provider-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-card);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.provider-item.selected[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: var(--mj-brand-primary);\n}\n\n\n\n.provider-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: var(--mj-text-secondary);\n margin-right: 12px;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n\n.provider-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.provider-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.provider-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n\n\n.default-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.default-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.provider-type-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .provider-type-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n\n\n.search-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .search-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.search-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.credential-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.provider-item.selected[_ngcontent-%COMP%] .credential-badge[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n color: var(--mj-status-success);\n}\n\n.credential-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.unconfigured-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.unconfigured-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.oauth-connected-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.oauth-connected-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.oauth-disconnected-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-warning);\n}\n\n.oauth-disconnected-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n\n\n.provider-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: 8px;\n}\n\n.connect-btn[_ngcontent-%COMP%], \n.disconnect-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n}\n\n.connect-btn[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.connect-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n transform: scale(1.05);\n}\n\n.connect-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.disconnect-btn[_ngcontent-%COMP%] {\n background-color: transparent;\n color: var(--mj-text-muted);\n}\n\n.disconnect-btn[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n\n\n.remove-provider-btn[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 50%;\n background-color: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n opacity: 0;\n margin-left: 8px;\n}\n\n.provider-item[_ngcontent-%COMP%]:hover .remove-provider-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.remove-provider-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.remove-provider-btn[_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.providers-container[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n\n\n\n.add-provider-dialog[_ngcontent-%COMP%] {\n min-height: 150px;\n}\n\n.dialog-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.dialog-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 30px 20px;\n text-align: center;\n}\n\n.dialog-empty-icon[_ngcontent-%COMP%] {\n font-size: 40px;\n color: var(--mj-status-success);\n margin-bottom: 12px;\n}\n\n.dialog-empty-message[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.dialog-empty-hint[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n.dialog-instruction[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n padding: 0 4px;\n}\n\n.available-providers[_ngcontent-%COMP%] {\n max-height: 350px;\n overflow-y: auto;\n}\n\n.available-provider-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.available-provider-item[_ngcontent-%COMP%]:hover:not(.disabled) {\n background-color: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n}\n\n.available-provider-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--mj-bg-surface-card);\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-icon[_ngcontent-%COMP%] {\n margin-right: 12px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n line-height: 1.3;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-warning[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-status-warning);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .provider-warning[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.available-provider-item[_ngcontent-%COMP%] .oauth-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item[_ngcontent-%COMP%] .oauth-hint[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.available-provider-item.oauth-provider[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n}\n\n.available-provider-item.oauth-provider[_ngcontent-%COMP%]:hover:not(.disabled) {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.add-indicator[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n\n\n@media screen and (max-width: 768px) {\n .providers-header[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .header-title[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .add-provider-btn[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n font-size: 12px;\n }\n\n .provider-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .provider-icon[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n font-size: 18px;\n margin-right: 10px;\n }\n\n .provider-name[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .provider-status[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .remove-provider-btn[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n font-size: 11px;\n opacity: 1;\n }\n}"] });
233
220
  }
234
221
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(StorageProvidersListComponent, [{
235
222
  type: Component,
236
- args: [{ standalone: false, selector: 'mj-storage-providers-list', template: "<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading accounts...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (errorMessage && !isLoading) {\n <div class=\"error-state\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n </div>\n <p class=\"error-message\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Empty State -->\n @if (!isLoading && !errorMessage && accounts.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n </div>\n <p class=\"empty-message\">No storage accounts configured</p>\n <p class=\"empty-hint\">Contact your administrator to set up file storage accounts</p>\n </div>\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\"\n >\n <div class=\"provider-icon\">\n <i [class]=\"getProviderIcon(item.provider.Name)\"></i>\n </div>\n <div class=\"provider-info\">\n <div class=\"provider-name\">{{ item.account.Name }}</div>\n <div class=\"provider-meta\">\n <!-- Provider type badge -->\n <span class=\"provider-type-badge\" [title]=\"item.provider.Name\">\n {{ item.provider.Name }}\n </span>\n <!-- Search support badge -->\n @if (item.provider.SupportsSearch) {\n <span class=\"search-badge\" title=\"Supports search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </span>\n }\n <!-- Credential configured badge -->\n @if (item.account.CredentialID) {\n <span class=\"credential-badge\" title=\"Credentials configured\">\n <i class=\"fa-solid fa-key\"></i>\n </span>\n }\n <!-- No credential warning -->\n @if (!item.account.CredentialID) {\n <span class=\"unconfigured-badge\" title=\"No credentials configured\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* ===========================\n Storage Providers List\n =========================== */\n\n.providers-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n/* Header with Add Button */\n.providers-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.header-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.add-provider-btn {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 14px;\n}\n\n.add-provider-btn:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n\n.add-provider-btn:disabled {\n background-color: var(--mj-border-strong);\n cursor: not-allowed;\n}\n\n/* Loading, Error, and Empty States */\n.loading-state,\n.error-state,\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px;\n text-align: center;\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n.error-icon,\n.empty-icon {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.7;\n}\n\n.error-icon {\n color: var(--mj-status-error);\n}\n\n.empty-icon {\n color: var(--mj-brand-primary);\n}\n\n.error-message,\n.empty-message {\n font-size: 14px;\n font-weight: 500;\n margin: 0 0 4px 0;\n color: var(--mj-text-primary);\n}\n\n.empty-hint {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin: 4px 0 0 0;\n max-width: 180px;\n line-height: 1.4;\n}\n\n/* Provider List Container */\n.providers-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Individual Provider Item */\n.provider-item {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n position: relative;\n}\n\n.provider-item:hover {\n background-color: var(--mj-bg-surface-card);\n}\n\n.provider-item.selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.provider-item.selected::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: var(--mj-brand-primary);\n}\n\n/* Provider Icon */\n.provider-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: var(--mj-text-secondary);\n margin-right: 12px;\n}\n\n.provider-item.selected .provider-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Provider Info */\n.provider-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.provider-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected .provider-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.provider-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Default Badge */\n.default-badge {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.default-badge i {\n font-size: 10px;\n}\n\n/* Provider Type Badge */\n.provider-type-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected .provider-type-badge {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n/* Search Badge */\n.search-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n.provider-item.selected .search-badge {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.search-badge i {\n font-size: 9px;\n}\n\n/* Credential Badge */\n.credential-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.provider-item.selected .credential-badge {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n color: var(--mj-status-success);\n}\n\n.credential-badge i {\n font-size: 9px;\n}\n\n/* Unconfigured Badge */\n.unconfigured-badge {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.unconfigured-badge i {\n font-size: 10px;\n}\n\n/* OAuth Status Badges */\n.oauth-connected-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.oauth-connected-badge i {\n font-size: 9px;\n}\n\n.oauth-disconnected-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-warning);\n}\n\n.oauth-disconnected-badge i {\n font-size: 9px;\n}\n\n/* Provider Actions (OAuth connect/disconnect buttons) */\n.provider-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: 8px;\n}\n\n.connect-btn,\n.disconnect-btn {\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n}\n\n.connect-btn {\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.connect-btn:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n transform: scale(1.05);\n}\n\n.connect-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.disconnect-btn {\n background-color: transparent;\n color: var(--mj-text-muted);\n}\n\n.disconnect-btn:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* Remove Provider Button */\n.remove-provider-btn {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 50%;\n background-color: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n opacity: 0;\n margin-left: 8px;\n}\n\n.provider-item:hover .remove-provider-btn {\n opacity: 1;\n}\n\n.remove-provider-btn:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.remove-provider-btn:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Scrollbar Styling */\n.providers-container::-webkit-scrollbar {\n width: 6px;\n}\n\n.providers-container::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.providers-container::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.providers-container::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* ===========================\n Add Provider Dialog\n =========================== */\n\n.add-provider-dialog {\n min-height: 150px;\n}\n\n.dialog-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.dialog-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 30px 20px;\n text-align: center;\n}\n\n.dialog-empty-icon {\n font-size: 40px;\n color: var(--mj-status-success);\n margin-bottom: 12px;\n}\n\n.dialog-empty-message {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.dialog-empty-hint {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n.dialog-instruction {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n padding: 0 4px;\n}\n\n.available-providers {\n max-height: 350px;\n overflow-y: auto;\n}\n\n.available-provider-item {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.available-provider-item:hover:not(.disabled) {\n background-color: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n}\n\n.available-provider-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--mj-bg-surface-card);\n}\n\n.available-provider-item .provider-icon {\n margin-right: 12px;\n}\n\n.available-provider-item .provider-info {\n flex: 1;\n}\n\n.available-provider-item .provider-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.available-provider-item .provider-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n line-height: 1.3;\n}\n\n.available-provider-item .provider-warning {\n font-size: 11px;\n color: var(--mj-status-warning);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item .provider-warning i {\n font-size: 10px;\n}\n\n/* OAuth hint in add provider dialog */\n.available-provider-item .oauth-hint {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item .oauth-hint i {\n font-size: 10px;\n}\n\n.available-provider-item.oauth-provider {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n}\n\n.available-provider-item.oauth-provider:hover:not(.disabled) {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.add-indicator {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n/* Responsive Adjustments */\n@media screen and (max-width: 768px) {\n .providers-header {\n padding: 10px 12px;\n }\n\n .header-title {\n font-size: 12px;\n }\n\n .add-provider-btn {\n width: 26px;\n height: 26px;\n font-size: 12px;\n }\n\n .provider-item {\n padding: 10px 12px;\n }\n\n .provider-icon {\n width: 28px;\n height: 28px;\n font-size: 18px;\n margin-right: 10px;\n }\n\n .provider-name {\n font-size: 12px;\n }\n\n .provider-status {\n font-size: 10px;\n }\n\n .remove-provider-btn {\n width: 22px;\n height: 22px;\n font-size: 11px;\n opacity: 1;\n }\n}\n"] }]
223
+ args: [{ standalone: false, selector: 'mj-storage-providers-list', template: "<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading accounts...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (errorMessage && !isLoading) {\n <mj-empty-state\n class=\"storage-providers-empty-fill\"\n Variant=\"error\"\n Icon=\"fa-solid fa-triangle-exclamation\"\n [Title]=\"errorMessage\"\n Size=\"compact\" />\n }\n\n <!-- Empty State -->\n @if (!isLoading && !errorMessage && accounts.length === 0) {\n <mj-empty-state\n class=\"storage-providers-empty-fill\"\n Icon=\"fa-solid fa-folder-plus\"\n Title=\"No storage accounts configured\"\n Message=\"Contact your administrator to set up file storage accounts\"\n Size=\"compact\" />\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\"\n >\n <div class=\"provider-icon\">\n <i [class]=\"getProviderIcon(item.provider.Name)\"></i>\n </div>\n <div class=\"provider-info\">\n <div class=\"provider-name\">{{ item.account.Name }}</div>\n <div class=\"provider-meta\">\n <!-- Provider type badge -->\n <span class=\"provider-type-badge\" [title]=\"item.provider.Name\">\n {{ item.provider.Name }}\n </span>\n <!-- Search support badge -->\n @if (item.provider.SupportsSearch) {\n <span class=\"search-badge\" title=\"Supports search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </span>\n }\n <!-- Credential configured badge -->\n @if (item.account.CredentialID) {\n <span class=\"credential-badge\" title=\"Credentials configured\">\n <i class=\"fa-solid fa-key\"></i>\n </span>\n }\n <!-- No credential warning -->\n @if (!item.account.CredentialID) {\n <span class=\"unconfigured-badge\" title=\"No credentials configured\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* ===========================\n Storage Providers List\n =========================== */\n\n.providers-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n/* Header with Add Button */\n.providers-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.header-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.add-provider-btn {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 14px;\n}\n\n.add-provider-btn:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n\n.add-provider-btn:disabled {\n background-color: var(--mj-border-strong);\n cursor: not-allowed;\n}\n\n/* Loading State */\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px;\n text-align: center;\n color: var(--mj-text-muted);\n flex: 1;\n}\n\n/* Empty/error states fill the panel vertically (flex-parent gotcha) */\n.storage-providers-empty-fill {\n flex: 1;\n}\n\n/* Provider List Container */\n.providers-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Individual Provider Item */\n.provider-item {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 1px solid var(--mj-bg-surface-sunken);\n position: relative;\n}\n\n.provider-item:hover {\n background-color: var(--mj-bg-surface-card);\n}\n\n.provider-item.selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.provider-item.selected::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background-color: var(--mj-brand-primary);\n}\n\n/* Provider Icon */\n.provider-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n color: var(--mj-text-secondary);\n margin-right: 12px;\n}\n\n.provider-item.selected .provider-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Provider Info */\n.provider-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.provider-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected .provider-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.provider-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n/* Default Badge */\n.default-badge {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.default-badge i {\n font-size: 10px;\n}\n\n/* Provider Type Badge */\n.provider-type-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n max-width: 100px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.provider-item.selected .provider-type-badge {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n/* Search Badge */\n.search-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n.provider-item.selected .search-badge {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.search-badge i {\n font-size: 9px;\n}\n\n/* Credential Badge */\n.credential-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.provider-item.selected .credential-badge {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n color: var(--mj-status-success);\n}\n\n.credential-badge i {\n font-size: 9px;\n}\n\n/* Unconfigured Badge */\n.unconfigured-badge {\n display: inline-flex;\n align-items: center;\n color: var(--mj-status-warning);\n}\n\n.unconfigured-badge i {\n font-size: 10px;\n}\n\n/* OAuth Status Badges */\n.oauth-connected-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-success);\n}\n\n.oauth-connected-badge i {\n font-size: 9px;\n}\n\n.oauth-disconnected-badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background-color: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 10px;\n color: var(--mj-status-warning);\n}\n\n.oauth-disconnected-badge i {\n font-size: 9px;\n}\n\n/* Provider Actions (OAuth connect/disconnect buttons) */\n.provider-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-left: 8px;\n}\n\n.connect-btn,\n.disconnect-btn {\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n}\n\n.connect-btn {\n background-color: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.connect-btn:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n transform: scale(1.05);\n}\n\n.connect-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.disconnect-btn {\n background-color: transparent;\n color: var(--mj-text-muted);\n}\n\n.disconnect-btn:hover {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* Remove Provider Button */\n.remove-provider-btn {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 50%;\n background-color: transparent;\n color: var(--mj-text-disabled);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n font-size: 12px;\n opacity: 0;\n margin-left: 8px;\n}\n\n.provider-item:hover .remove-provider-btn {\n opacity: 1;\n}\n\n.remove-provider-btn:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.remove-provider-btn:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Scrollbar Styling */\n.providers-container::-webkit-scrollbar {\n width: 6px;\n}\n\n.providers-container::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.providers-container::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.providers-container::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* ===========================\n Add Provider Dialog\n =========================== */\n\n.add-provider-dialog {\n min-height: 150px;\n}\n\n.dialog-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.dialog-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 30px 20px;\n text-align: center;\n}\n\n.dialog-empty-icon {\n font-size: 40px;\n color: var(--mj-status-success);\n margin-bottom: 12px;\n}\n\n.dialog-empty-message {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n}\n\n.dialog-empty-hint {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin: 0;\n}\n\n.dialog-instruction {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n padding: 0 4px;\n}\n\n.available-providers {\n max-height: 350px;\n overflow-y: auto;\n}\n\n.available-provider-item {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-bottom: 8px;\n border: 1px solid var(--mj-border-default);\n}\n\n.available-provider-item:hover:not(.disabled) {\n background-color: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n}\n\n.available-provider-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--mj-bg-surface-card);\n}\n\n.available-provider-item .provider-icon {\n margin-right: 12px;\n}\n\n.available-provider-item .provider-info {\n flex: 1;\n}\n\n.available-provider-item .provider-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.available-provider-item .provider-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n line-height: 1.3;\n}\n\n.available-provider-item .provider-warning {\n font-size: 11px;\n color: var(--mj-status-warning);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item .provider-warning i {\n font-size: 10px;\n}\n\n/* OAuth hint in add provider dialog */\n.available-provider-item .oauth-hint {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-top: 4px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.available-provider-item .oauth-hint i {\n font-size: 10px;\n}\n\n.available-provider-item.oauth-provider {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n}\n\n.available-provider-item.oauth-provider:hover:not(.disabled) {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-style: solid;\n}\n\n.add-indicator {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n/* Responsive Adjustments */\n@media screen and (max-width: 768px) {\n .providers-header {\n padding: 10px 12px;\n }\n\n .header-title {\n font-size: 12px;\n }\n\n .add-provider-btn {\n width: 26px;\n height: 26px;\n font-size: 12px;\n }\n\n .provider-item {\n padding: 10px 12px;\n }\n\n .provider-icon {\n width: 28px;\n height: 28px;\n font-size: 18px;\n margin-right: 10px;\n }\n\n .provider-name {\n font-size: 12px;\n }\n\n .provider-status {\n font-size: 10px;\n }\n\n .remove-provider-btn {\n width: 22px;\n height: 22px;\n font-size: 11px;\n opacity: 1;\n }\n}\n"] }]
237
224
  }], () => [{ type: i0.ChangeDetectorRef }], { accountSelected: [{
238
225
  type: Output
239
226
  }] }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"storage-providers-list.component.js","sourceRoot":"","sources":["../../../src/lib/file-browser/storage-providers-list.component.ts","../../../src/lib/file-browser/storage-providers-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, OnInit, Output, ChangeDetectorRef } from '@angular/core';\nimport { FileStorageEngineBase, StorageAccountWithProvider } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Displays a list of organizational file storage accounts.\n * In the enterprise model, accounts are configured by administrators\n * and available to users based on permissions. Users no longer manage\n * their own OAuth connections - credentials are handled at the org level.\n */\n@Component({\n standalone: false,\n selector: 'mj-storage-providers-list',\n templateUrl: './storage-providers-list.component.html',\n styleUrls: ['./storage-providers-list.component.css']\n})\nexport class StorageProvidersListComponent implements OnInit {\n /**\n * Emits when an account is selected by the user, or null when no accounts are available.\n * Emits the full account-with-provider object for downstream components to use.\n */\n @Output() accountSelected = new EventEmitter<StorageAccountWithProvider | null>();\n\n /**\n * All available storage accounts with their provider details.\n */\n public accounts: StorageAccountWithProvider[] = [];\n\n /**\n * Currently selected account.\n */\n public selectedAccount: StorageAccountWithProvider | null = null;\n\n /**\n * Loading state indicator.\n */\n public isLoading: boolean = false;\n\n /**\n * Error message if loading fails.\n */\n public errorMessage: string | null = null;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n this.loadAccounts();\n }\n\n /**\n * Loads all available file storage accounts with their provider details.\n * Uses FileStorageEngineBase for centralized, cached access.\n */\n private async loadAccounts(): Promise<void> {\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const engine = FileStorageEngineBase.Instance;\n await engine.Config(false); // Use cached data if available\n\n // Only show accounts whose provider is active\n this.accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive);\n\n console.log('[StorageAccountsList] Loaded accounts:', this.accounts.map(a => ({\n name: a.account.Name,\n provider: a.provider.Name,\n hasCredential: !!a.account.CredentialID\n })));\n\n // Auto-select first account if available\n if (this.accounts.length > 0) {\n this.selectAccount(this.accounts[0]);\n } else {\n this.accountSelected.emit(null);\n }\n\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load storage accounts';\n console.error('[StorageProvidersList] Error loading accounts:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handles account selection by the user.\n */\n public selectAccount(accountWithProvider: StorageAccountWithProvider): void {\n this.selectedAccount = accountWithProvider;\n this.accountSelected.emit(accountWithProvider);\n }\n\n /**\n * Checks if an account is currently selected.\n */\n public isSelected(accountWithProvider: StorageAccountWithProvider): boolean {\n return UUIDsEqual(this.selectedAccount?.account.ID, accountWithProvider.account.ID);\n }\n\n /**\n * Gets the icon class for a provider based on its name.\n */\n public getProviderIcon(providerName: string): string {\n const name = providerName.toLowerCase();\n\n if (name.includes('aws') || name.includes('s3')) {\n return 'fa-brands fa-aws';\n } else if (name.includes('azure')) {\n return 'fa-brands fa-microsoft';\n } else if (name.includes('google drive')) {\n return 'fa-brands fa-google-drive';\n } else if (name.includes('google cloud')) {\n return 'fa-brands fa-google';\n } else if (name.includes('dropbox')) {\n return 'fa-brands fa-dropbox';\n } else if (name.includes('box')) {\n return 'fa-solid fa-box';\n } else if (name.includes('sharepoint') || name.includes('onedrive')) {\n return 'fa-brands fa-microsoft';\n } else {\n return 'fa-solid fa-cloud';\n }\n }\n\n /**\n * Refreshes the accounts list by forcing a reload from the database.\n */\n public refresh(): void {\n FileStorageEngineBase.Instance.Config(true).then(() => this.loadAccounts());\n }\n}\n","<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading accounts...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (errorMessage && !isLoading) {\n <div class=\"error-state\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n </div>\n <p class=\"error-message\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Empty State -->\n @if (!isLoading && !errorMessage && accounts.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n </div>\n <p class=\"empty-message\">No storage accounts configured</p>\n <p class=\"empty-hint\">Contact your administrator to set up file storage accounts</p>\n </div>\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\"\n >\n <div class=\"provider-icon\">\n <i [class]=\"getProviderIcon(item.provider.Name)\"></i>\n </div>\n <div class=\"provider-info\">\n <div class=\"provider-name\">{{ item.account.Name }}</div>\n <div class=\"provider-meta\">\n <!-- Provider type badge -->\n <span class=\"provider-type-badge\" [title]=\"item.provider.Name\">\n {{ item.provider.Name }}\n </span>\n <!-- Search support badge -->\n @if (item.provider.SupportsSearch) {\n <span class=\"search-badge\" title=\"Supports search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </span>\n }\n <!-- Credential configured badge -->\n @if (item.account.CredentialID) {\n <span class=\"credential-badge\" title=\"Credentials configured\">\n <i class=\"fa-solid fa-key\"></i>\n </span>\n }\n <!-- No credential warning -->\n @if (!item.account.CredentialID) {\n <span class=\"unconfigured-badge\" title=\"No credentials configured\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n"]}
1
+ {"version":3,"file":"storage-providers-list.component.js","sourceRoot":"","sources":["../../../src/lib/file-browser/storage-providers-list.component.ts","../../../src/lib/file-browser/storage-providers-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, OnInit, Output, ChangeDetectorRef } from '@angular/core';\nimport { FileStorageEngineBase, StorageAccountWithProvider } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Displays a list of organizational file storage accounts.\n * In the enterprise model, accounts are configured by administrators\n * and available to users based on permissions. Users no longer manage\n * their own OAuth connections - credentials are handled at the org level.\n */\n@Component({\n standalone: false,\n selector: 'mj-storage-providers-list',\n templateUrl: './storage-providers-list.component.html',\n styleUrls: ['./storage-providers-list.component.css']\n})\nexport class StorageProvidersListComponent implements OnInit {\n /**\n * Emits when an account is selected by the user, or null when no accounts are available.\n * Emits the full account-with-provider object for downstream components to use.\n */\n @Output() accountSelected = new EventEmitter<StorageAccountWithProvider | null>();\n\n /**\n * All available storage accounts with their provider details.\n */\n public accounts: StorageAccountWithProvider[] = [];\n\n /**\n * Currently selected account.\n */\n public selectedAccount: StorageAccountWithProvider | null = null;\n\n /**\n * Loading state indicator.\n */\n public isLoading: boolean = false;\n\n /**\n * Error message if loading fails.\n */\n public errorMessage: string | null = null;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n this.loadAccounts();\n }\n\n /**\n * Loads all available file storage accounts with their provider details.\n * Uses FileStorageEngineBase for centralized, cached access.\n */\n private async loadAccounts(): Promise<void> {\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const engine = FileStorageEngineBase.Instance;\n await engine.Config(false); // Use cached data if available\n\n // Only show accounts whose provider is active\n this.accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive);\n\n console.log('[StorageAccountsList] Loaded accounts:', this.accounts.map(a => ({\n name: a.account.Name,\n provider: a.provider.Name,\n hasCredential: !!a.account.CredentialID\n })));\n\n // Auto-select first account if available\n if (this.accounts.length > 0) {\n this.selectAccount(this.accounts[0]);\n } else {\n this.accountSelected.emit(null);\n }\n\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load storage accounts';\n console.error('[StorageProvidersList] Error loading accounts:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handles account selection by the user.\n */\n public selectAccount(accountWithProvider: StorageAccountWithProvider): void {\n this.selectedAccount = accountWithProvider;\n this.accountSelected.emit(accountWithProvider);\n }\n\n /**\n * Checks if an account is currently selected.\n */\n public isSelected(accountWithProvider: StorageAccountWithProvider): boolean {\n return UUIDsEqual(this.selectedAccount?.account.ID, accountWithProvider.account.ID);\n }\n\n /**\n * Gets the icon class for a provider based on its name.\n */\n public getProviderIcon(providerName: string): string {\n const name = providerName.toLowerCase();\n\n if (name.includes('aws') || name.includes('s3')) {\n return 'fa-brands fa-aws';\n } else if (name.includes('azure')) {\n return 'fa-brands fa-microsoft';\n } else if (name.includes('google drive')) {\n return 'fa-brands fa-google-drive';\n } else if (name.includes('google cloud')) {\n return 'fa-brands fa-google';\n } else if (name.includes('dropbox')) {\n return 'fa-brands fa-dropbox';\n } else if (name.includes('box')) {\n return 'fa-solid fa-box';\n } else if (name.includes('sharepoint') || name.includes('onedrive')) {\n return 'fa-brands fa-microsoft';\n } else {\n return 'fa-solid fa-cloud';\n }\n }\n\n /**\n * Refreshes the accounts list by forcing a reload from the database.\n */\n public refresh(): void {\n FileStorageEngineBase.Instance.Config(true).then(() => this.loadAccounts());\n }\n}\n","<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading accounts...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (errorMessage && !isLoading) {\n <mj-empty-state\n class=\"storage-providers-empty-fill\"\n Variant=\"error\"\n Icon=\"fa-solid fa-triangle-exclamation\"\n [Title]=\"errorMessage\"\n Size=\"compact\" />\n }\n\n <!-- Empty State -->\n @if (!isLoading && !errorMessage && accounts.length === 0) {\n <mj-empty-state\n class=\"storage-providers-empty-fill\"\n Icon=\"fa-solid fa-folder-plus\"\n Title=\"No storage accounts configured\"\n Message=\"Contact your administrator to set up file storage accounts\"\n Size=\"compact\" />\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\"\n >\n <div class=\"provider-icon\">\n <i [class]=\"getProviderIcon(item.provider.Name)\"></i>\n </div>\n <div class=\"provider-info\">\n <div class=\"provider-name\">{{ item.account.Name }}</div>\n <div class=\"provider-meta\">\n <!-- Provider type badge -->\n <span class=\"provider-type-badge\" [title]=\"item.provider.Name\">\n {{ item.provider.Name }}\n </span>\n <!-- Search support badge -->\n @if (item.provider.SupportsSearch) {\n <span class=\"search-badge\" title=\"Supports search\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </span>\n }\n <!-- Credential configured badge -->\n @if (item.account.CredentialID) {\n <span class=\"credential-badge\" title=\"Credentials configured\">\n <i class=\"fa-solid fa-key\"></i>\n </span>\n }\n <!-- No credential warning -->\n @if (!item.account.CredentialID) {\n <span class=\"unconfigured-badge\" title=\"No credentials configured\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n"]}
@@ -16,7 +16,7 @@ import * as i14 from "@memberjunction/ng-shared-generic";
16
16
  import * as i15 from "@memberjunction/ng-ui-components";
17
17
  export declare class FileStorageModule {
18
18
  static ɵfac: i0.ɵɵFactoryDeclaration<FileStorageModule, never>;
19
- static ɵmod: i0.ɵɵNgModuleDeclaration<FileStorageModule, [typeof i1.CategoryTreeComponent, typeof i2.FilesGridComponent, typeof i3.FileUploadComponent, typeof i4.FileBrowserComponent, typeof i5.FileBrowserDemoComponent, typeof i6.FileBrowserResource, typeof i7.StorageProvidersListComponent, typeof i8.FolderTreeComponent, typeof i9.FileGridComponent], [typeof i10.CommonModule, typeof i11.FormsModule, typeof i12.AgGridModule, typeof i13.ContainerDirectivesModule, typeof i14.SharedGenericModule, typeof i15.MJButtonDirective, typeof i15.MJDialogComponent, typeof i15.MJDialogActionsComponent, typeof i15.MJPageHeaderComponent, typeof i15.MJPageLayoutComponent], [typeof i1.CategoryTreeComponent, typeof i2.FilesGridComponent, typeof i3.FileUploadComponent, typeof i4.FileBrowserComponent, typeof i5.FileBrowserDemoComponent, typeof i6.FileBrowserResource]>;
19
+ static ɵmod: i0.ɵɵNgModuleDeclaration<FileStorageModule, [typeof i1.CategoryTreeComponent, typeof i2.FilesGridComponent, typeof i3.FileUploadComponent, typeof i4.FileBrowserComponent, typeof i5.FileBrowserDemoComponent, typeof i6.FileBrowserResource, typeof i7.StorageProvidersListComponent, typeof i8.FolderTreeComponent, typeof i9.FileGridComponent], [typeof i10.CommonModule, typeof i11.FormsModule, typeof i12.AgGridModule, typeof i13.ContainerDirectivesModule, typeof i14.SharedGenericModule, typeof i15.MJButtonDirective, typeof i15.MJDialogComponent, typeof i15.MJDialogActionsComponent, typeof i15.MJEmptyStateComponent, typeof i15.MJPageHeaderComponent, typeof i15.MJPageLayoutComponent], [typeof i1.CategoryTreeComponent, typeof i2.FilesGridComponent, typeof i3.FileUploadComponent, typeof i4.FileBrowserComponent, typeof i5.FileBrowserDemoComponent, typeof i6.FileBrowserResource]>;
20
20
  static ɵinj: i0.ɵɵInjectorDeclaration<FileStorageModule>;
21
21
  }
22
22
  //# sourceMappingURL=module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAwBA,qBAiCa,iBAAiB;yCAAjB,iBAAiB;0CAAjB,iBAAiB;0CAAjB,iBAAiB;CAAG"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAyBA,qBAkCa,iBAAiB;yCAAjB,iBAAiB;0CAAjB,iBAAiB;0CAAjB,iBAAiB;CAAG"}
@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
2
2
  import { NgModule } from '@angular/core';
3
3
  import { FormsModule } from '@angular/forms';
4
4
  import { AgGridModule } from 'ag-grid-angular';
5
- import { MJButtonDirective, MJDialogComponent, MJDialogActionsComponent, MJPageHeaderComponent, MJPageLayoutComponent } from '@memberjunction/ng-ui-components';
5
+ import { MJButtonDirective, MJDialogComponent, MJDialogActionsComponent, MJEmptyStateComponent, MJPageHeaderComponent, MJPageLayoutComponent } from '@memberjunction/ng-ui-components';
6
6
  import { ContainerDirectivesModule } from '@memberjunction/ng-container-directives';
7
7
  import { SharedGenericModule } from '@memberjunction/ng-shared-generic';
8
8
  import { CategoryTreeComponent } from './category-tree/category-tree';
@@ -25,6 +25,7 @@ export class FileStorageModule {
25
25
  SharedGenericModule,
26
26
  MJDialogComponent,
27
27
  MJDialogActionsComponent,
28
+ MJEmptyStateComponent,
28
29
  MJPageHeaderComponent,
29
30
  MJPageLayoutComponent] });
30
31
  }
@@ -51,6 +52,7 @@ export class FileStorageModule {
51
52
  MJButtonDirective,
52
53
  MJDialogComponent,
53
54
  MJDialogActionsComponent,
55
+ MJEmptyStateComponent,
54
56
  MJPageHeaderComponent,
55
57
  MJPageLayoutComponent,
56
58
  ],
@@ -80,6 +82,7 @@ export class FileStorageModule {
80
82
  MJButtonDirective,
81
83
  MJDialogComponent,
82
84
  MJDialogActionsComponent,
85
+ MJEmptyStateComponent,
83
86
  MJPageHeaderComponent,
84
87
  MJPageLayoutComponent], exports: [CategoryTreeComponent,
85
88
  FilesGridComponent,
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAC;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,iDAAiD,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;;AAmCvE,MAAM,OAAO,iBAAiB;2GAAjB,iBAAiB;4DAAjB,iBAAiB;gEApB1B,YAAY;YACZ,WAAW;YACX,YAAY;YACZ,yBAAyB;YACzB,mBAAmB;YAEnB,iBAAiB;YACjB,wBAAwB;YACxB,qBAAqB;YACrB,qBAAqB;;iFAWZ,iBAAiB;cAjC7B,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,qBAAqB;oBACrB,kBAAkB;oBAClB,mBAAmB;oBACnB,oBAAoB;oBACpB,wBAAwB;oBACxB,mBAAmB;oBACnB,6BAA6B;oBAC7B,mBAAmB;oBACnB,iBAAiB;iBAClB;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,YAAY;oBACZ,yBAAyB;oBACzB,mBAAmB;oBACnB,iBAAiB;oBACjB,iBAAiB;oBACjB,wBAAwB;oBACxB,qBAAqB;oBACrB,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,qBAAqB;oBACrB,kBAAkB;oBAClB,mBAAmB;oBACnB,oBAAoB;oBACpB,wBAAwB;oBACxB,mBAAmB;iBACpB;aACF;;wFACY,iBAAiB,mBA/B1B,qBAAqB;QACrB,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,wBAAwB;QACxB,mBAAmB;QACnB,6BAA6B;QAC7B,mBAAmB;QACnB,iBAAiB,aAGjB,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,yBAAyB;QACzB,mBAAmB;QACnB,iBAAiB;QACjB,iBAAiB;QACjB,wBAAwB;QACxB,qBAAqB;QACrB,qBAAqB,aAGrB,qBAAqB;QACrB,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,wBAAwB;QACxB,mBAAmB","sourcesContent":["import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { AgGridModule } from 'ag-grid-angular';\nimport {\n MJButtonDirective,\n MJDialogComponent,\n MJDialogActionsComponent,\n MJPageHeaderComponent,\n MJPageLayoutComponent\n} from '@memberjunction/ng-ui-components';\nimport { ContainerDirectivesModule } from '@memberjunction/ng-container-directives';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { CategoryTreeComponent } from './category-tree/category-tree';\nimport { FileUploadComponent } from './file-upload/file-upload';\nimport { FilesGridComponent } from './files-grid/files-grid';\nimport { FileBrowserComponent } from './file-browser/file-browser.component';\nimport { FileBrowserDemoComponent } from './file-browser/file-browser-demo.component';\nimport { FileBrowserResource } from './file-browser/file-browser-resource.component';\nimport { StorageProvidersListComponent } from './file-browser/storage-providers-list.component';\nimport { FolderTreeComponent } from './file-browser/folder-tree.component';\nimport { FileGridComponent } from './file-browser/file-grid.component';\n\n@NgModule({\n declarations: [\n CategoryTreeComponent,\n FilesGridComponent,\n FileUploadComponent,\n FileBrowserComponent,\n FileBrowserDemoComponent,\n FileBrowserResource,\n StorageProvidersListComponent,\n FolderTreeComponent,\n FileGridComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n AgGridModule,\n ContainerDirectivesModule,\n SharedGenericModule,\n MJButtonDirective,\n MJDialogComponent,\n MJDialogActionsComponent,\n MJPageHeaderComponent,\n MJPageLayoutComponent,\n ],\n exports: [\n CategoryTreeComponent,\n FilesGridComponent,\n FileUploadComponent,\n FileBrowserComponent,\n FileBrowserDemoComponent,\n FileBrowserResource\n ],\n})\nexport class FileStorageModule {}\n"]}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAC;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,iDAAiD,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;;AAoCvE,MAAM,OAAO,iBAAiB;2GAAjB,iBAAiB;4DAAjB,iBAAiB;gEArB1B,YAAY;YACZ,WAAW;YACX,YAAY;YACZ,yBAAyB;YACzB,mBAAmB;YAEnB,iBAAiB;YACjB,wBAAwB;YACxB,qBAAqB;YACrB,qBAAqB;YACrB,qBAAqB;;iFAWZ,iBAAiB;cAlC7B,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,qBAAqB;oBACrB,kBAAkB;oBAClB,mBAAmB;oBACnB,oBAAoB;oBACpB,wBAAwB;oBACxB,mBAAmB;oBACnB,6BAA6B;oBAC7B,mBAAmB;oBACnB,iBAAiB;iBAClB;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,YAAY;oBACZ,yBAAyB;oBACzB,mBAAmB;oBACnB,iBAAiB;oBACjB,iBAAiB;oBACjB,wBAAwB;oBACxB,qBAAqB;oBACrB,qBAAqB;oBACrB,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,qBAAqB;oBACrB,kBAAkB;oBAClB,mBAAmB;oBACnB,oBAAoB;oBACpB,wBAAwB;oBACxB,mBAAmB;iBACpB;aACF;;wFACY,iBAAiB,mBAhC1B,qBAAqB;QACrB,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,wBAAwB;QACxB,mBAAmB;QACnB,6BAA6B;QAC7B,mBAAmB;QACnB,iBAAiB,aAGjB,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,yBAAyB;QACzB,mBAAmB;QACnB,iBAAiB;QACjB,iBAAiB;QACjB,wBAAwB;QACxB,qBAAqB;QACrB,qBAAqB;QACrB,qBAAqB,aAGrB,qBAAqB;QACrB,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,wBAAwB;QACxB,mBAAmB","sourcesContent":["import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { AgGridModule } from 'ag-grid-angular';\nimport {\n MJButtonDirective,\n MJDialogComponent,\n MJDialogActionsComponent,\n MJEmptyStateComponent,\n MJPageHeaderComponent,\n MJPageLayoutComponent\n} from '@memberjunction/ng-ui-components';\nimport { ContainerDirectivesModule } from '@memberjunction/ng-container-directives';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { CategoryTreeComponent } from './category-tree/category-tree';\nimport { FileUploadComponent } from './file-upload/file-upload';\nimport { FilesGridComponent } from './files-grid/files-grid';\nimport { FileBrowserComponent } from './file-browser/file-browser.component';\nimport { FileBrowserDemoComponent } from './file-browser/file-browser-demo.component';\nimport { FileBrowserResource } from './file-browser/file-browser-resource.component';\nimport { StorageProvidersListComponent } from './file-browser/storage-providers-list.component';\nimport { FolderTreeComponent } from './file-browser/folder-tree.component';\nimport { FileGridComponent } from './file-browser/file-grid.component';\n\n@NgModule({\n declarations: [\n CategoryTreeComponent,\n FilesGridComponent,\n FileUploadComponent,\n FileBrowserComponent,\n FileBrowserDemoComponent,\n FileBrowserResource,\n StorageProvidersListComponent,\n FolderTreeComponent,\n FileGridComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n AgGridModule,\n ContainerDirectivesModule,\n SharedGenericModule,\n MJButtonDirective,\n MJDialogComponent,\n MJDialogActionsComponent,\n MJEmptyStateComponent,\n MJPageHeaderComponent,\n MJPageLayoutComponent,\n ],\n exports: [\n CategoryTreeComponent,\n FilesGridComponent,\n FileUploadComponent,\n FileBrowserComponent,\n FileBrowserDemoComponent,\n FileBrowserResource\n ],\n})\nexport class FileStorageModule {}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-file-storage",
3
- "version": "5.42.0",
3
+ "version": "5.44.0",
4
4
  "description": "MemberJunction: Angular components for managing files, and related components.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -29,6 +29,7 @@
29
29
  "devDependencies": {
30
30
  "@angular/compiler": "21.1.3",
31
31
  "@angular/compiler-cli": "21.1.3",
32
+ "@memberjunction/ng-test-utils": "5.44.0",
32
33
  "vitest": "^4.0.18"
33
34
  },
34
35
  "peerDependencies": {
@@ -38,16 +39,16 @@
38
39
  "@angular/router": "21.1.3"
39
40
  },
40
41
  "dependencies": {
41
- "@memberjunction/ng-ui-components": "5.42.0",
42
+ "@memberjunction/ng-ui-components": "5.44.0",
42
43
  "@angular/platform-browser": "21.1.3",
43
- "@memberjunction/core": "5.42.0",
44
- "@memberjunction/ng-base-types": "5.42.0",
45
- "@memberjunction/core-entities": "5.42.0",
46
- "@memberjunction/global": "5.42.0",
47
- "@memberjunction/graphql-dataprovider": "5.42.0",
48
- "@memberjunction/ng-container-directives": "5.42.0",
49
- "@memberjunction/ng-shared": "5.42.0",
50
- "@memberjunction/ng-shared-generic": "5.42.0",
44
+ "@memberjunction/core": "5.44.0",
45
+ "@memberjunction/ng-base-types": "5.44.0",
46
+ "@memberjunction/core-entities": "5.44.0",
47
+ "@memberjunction/global": "5.44.0",
48
+ "@memberjunction/graphql-dataprovider": "5.44.0",
49
+ "@memberjunction/ng-container-directives": "5.44.0",
50
+ "@memberjunction/ng-shared": "5.44.0",
51
+ "@memberjunction/ng-shared-generic": "5.44.0",
51
52
  "ag-grid-angular": "^35.0.1",
52
53
  "ag-grid-community": "^35.0.1",
53
54
  "tslib": "^2.8.1",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=exports.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"exports.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/exports.test.ts"],"names":[],"mappings":""}
@@ -1,17 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { existsSync } from 'fs';
3
- import { resolve } from 'path';
4
- describe('@memberjunction/ng-file-storage', () => {
5
- it('should have a public API entry point', () => {
6
- const pkgRoot = resolve(__dirname, '../..');
7
- const hasPublicApi = existsSync(resolve(pkgRoot, 'src/public-api.ts'));
8
- const hasIndex = existsSync(resolve(pkgRoot, 'src/index.ts'));
9
- expect(hasPublicApi || hasIndex).toBe(true);
10
- });
11
- it('should have a package.json with correct name', () => {
12
- const pkgRoot = resolve(__dirname, '../..');
13
- const pkg = require(resolve(pkgRoot, 'package.json'));
14
- expect(pkg.name).toBe('@memberjunction/ng-file-storage');
15
- });
16
- });
17
- //# sourceMappingURL=exports.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"exports.test.js","sourceRoot":"","sources":["../../src/__tests__/exports.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect } from 'vitest';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\n\ndescribe('@memberjunction/ng-file-storage', () => {\n it('should have a public API entry point', () => {\n const pkgRoot = resolve(__dirname, '../..');\n const hasPublicApi = existsSync(resolve(pkgRoot, 'src/public-api.ts'));\n const hasIndex = existsSync(resolve(pkgRoot, 'src/index.ts'));\n expect(hasPublicApi || hasIndex).toBe(true);\n });\n\n it('should have a package.json with correct name', () => {\n const pkgRoot = resolve(__dirname, '../..');\n const pkg = require(resolve(pkgRoot, 'package.json'));\n expect(pkg.name).toBe('@memberjunction/ng-file-storage');\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- describe('@memberjunction/ng-file-storage', () => {
3
- it('should have a passing test', () => {
4
- expect(true).toBe(true);
5
- });
6
- });
7
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect } from 'vitest';\n\ndescribe('@memberjunction/ng-file-storage', () => {\n it('should have a passing test', () => {\n expect(true).toBe(true);\n });\n});\n"]}