@memberjunction/ng-file-storage 5.21.0 → 5.23.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,7 +3,7 @@ import { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/g
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 "@progress/kendo-angular-buttons";
6
+ import * as i2 from "@memberjunction/ng-ui-components";
7
7
  function FolderTreeComponent_Conditional_1_For_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
8
8
  i0.ɵɵelement(0, "i", 13);
9
9
  } }
@@ -334,7 +334,7 @@ export class FolderTreeComponent {
334
334
  this.loadFolders();
335
335
  }
336
336
  static ɵfac = function FolderTreeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FolderTreeComponent)(); };
337
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FolderTreeComponent, selectors: [["mj-folder-tree"]], inputs: { account: "account" }, outputs: { folderSelected: "folderSelected" }, standalone: false, decls: 6, vars: 4, consts: [[1, "folder-tree"], [1, "navigation-bar"], [1, "tree-content"], ["text", "Loading folders..."], [1, "tree-error"], [1, "folder-list"], [1, "nav-buttons"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Go back", 1, "nav-button", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], ["kendoButton", "", "fillMode", "flat", "size", "small", "title", "Go forward", 1, "nav-button", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-right"], [1, "breadcrumbs"], ["kendoButton", "", "fillMode", "flat", "size", "small", 1, "breadcrumb-item", 3, "click"], [1, "fa-solid", "fa-chevron-right", "breadcrumb-separator"], [1, "error-icon"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "error-text"], [1, "folder-item"], [1, "tree-placeholder"], [1, "folder-item", 3, "click"], [1, "fa-solid", "fa-folder", "folder-icon"], [1, "folder-name"], [1, "placeholder-icon"], [1, "fa-solid", "fa-folder-open"], [1, "placeholder-text"], [1, "placeholder-hint"]], template: function FolderTreeComponent_Template(rf, ctx) { if (rf & 1) {
337
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FolderTreeComponent, selectors: [["mj-folder-tree"]], inputs: { account: "account" }, outputs: { folderSelected: "folderSelected" }, standalone: false, decls: 6, vars: 4, consts: [[1, "folder-tree"], [1, "navigation-bar"], [1, "tree-content"], ["text", "Loading folders..."], [1, "tree-error"], [1, "folder-list"], [1, "nav-buttons"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Go back", 1, "nav-button", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Go forward", 1, "nav-button", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-right"], [1, "breadcrumbs"], ["mjButton", "", "variant", "flat", "size", "sm", 1, "breadcrumb-item", 3, "click"], [1, "fa-solid", "fa-chevron-right", "breadcrumb-separator"], [1, "error-icon"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "error-text"], [1, "folder-item"], [1, "tree-placeholder"], [1, "folder-item", 3, "click"], [1, "fa-solid", "fa-folder", "folder-icon"], [1, "folder-name"], [1, "placeholder-icon"], [1, "fa-solid", "fa-folder-open"], [1, "placeholder-text"], [1, "placeholder-hint"]], template: function FolderTreeComponent_Template(rf, ctx) { if (rf & 1) {
338
338
  i0.ɵɵelementStart(0, "div", 0);
339
339
  i0.ɵɵconditionalCreate(1, FolderTreeComponent_Conditional_1_Template, 9, 2, "div", 1);
340
340
  i0.ɵɵelementStart(2, "div", 2);
@@ -351,11 +351,11 @@ export class FolderTreeComponent {
351
351
  i0.ɵɵconditional(ctx.errorMessage && !ctx.isLoading ? 4 : -1);
352
352
  i0.ɵɵadvance();
353
353
  i0.ɵɵconditional(!ctx.isLoading && !ctx.errorMessage ? 5 : -1);
354
- } }, dependencies: [i1.LoadingComponent, i2.ButtonComponent], styles: [".folder-tree[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.navigation-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n\n\n.nav-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.nav-button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n min-width: 28px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n.nav-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.nav-button[_ngcontent-%COMP%]:hover:not([disabled]) {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.nav-button[disabled][_ngcontent-%COMP%] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.nav-button[disabled][_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.breadcrumbs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 28px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n border-radius: 4px;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n cursor: default;\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%]:hover {\n background-color: transparent;\n}\n\n.breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar {\n height: 4px;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 2px;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n.tree-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n\n\n.tree-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.placeholder-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n margin-bottom: 16px;\n opacity: 0.5;\n color: var(--mj-status-warning);\n}\n\n.placeholder-text[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.placeholder-hint[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n.folder-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.folder-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.folder-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.folder-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-status-warning);\n flex-shrink: 0;\n}\n\n.folder-name[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.tree-error[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.error-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-status-error);\n}\n\n.error-text[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n\n\n@media screen and (max-width: 768px) {\n .navigation-bar[_ngcontent-%COMP%] {\n padding: 6px 8px;\n }\n\n .nav-button[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n min-width: 24px;\n }\n\n .nav-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .breadcrumb-item[_ngcontent-%COMP%] {\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 9px;\n }\n\n .folder-item[_ngcontent-%COMP%] {\n padding: 8px 10px;\n }\n\n .folder-name[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n}"] });
354
+ } }, dependencies: [i1.LoadingComponent, i2.MJButtonDirective], styles: [".folder-tree[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.navigation-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n\n\n.nav-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.nav-button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n min-width: 28px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n.nav-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.nav-button[_ngcontent-%COMP%]:hover:not([disabled]) {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.nav-button[disabled][_ngcontent-%COMP%] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.nav-button[disabled][_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n\n\n\n.breadcrumbs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 28px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n border-radius: 4px;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n cursor: default;\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%]:hover {\n background-color: transparent;\n}\n\n.breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar {\n height: 4px;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 2px;\n}\n\n.breadcrumbs[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n.tree-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n\n\n.tree-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.placeholder-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n margin-bottom: 16px;\n opacity: 0.5;\n color: var(--mj-status-warning);\n}\n\n.placeholder-text[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.placeholder-hint[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.tree-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n\n\n.folder-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.folder-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.folder-item[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.folder-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-status-warning);\n flex-shrink: 0;\n}\n\n.folder-name[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.tree-error[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.error-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-status-error);\n}\n\n.error-text[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n\n\n@media screen and (max-width: 768px) {\n .navigation-bar[_ngcontent-%COMP%] {\n padding: 6px 8px;\n }\n\n .nav-button[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n min-width: 24px;\n }\n\n .nav-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n }\n\n .breadcrumb-item[_ngcontent-%COMP%] {\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 9px;\n }\n\n .folder-item[_ngcontent-%COMP%] {\n padding: 8px 10px;\n }\n\n .folder-name[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n}"] });
355
355
  }
356
356
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FolderTreeComponent, [{
357
357
  type: Component,
358
- args: [{ standalone: false, selector: 'mj-folder-tree', template: "<div class=\"folder-tree\">\n <!-- Navigation bar with back/forward buttons and breadcrumbs -->\n @if (account) {\n <div class=\"navigation-bar\">\n <!-- Back/Forward buttons -->\n <div class=\"nav-buttons\">\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n [disabled]=\"!canGoBack()\"\n (click)=\"navigateBack()\"\n title=\"Go back\"\n class=\"nav-button\"\n >\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n [disabled]=\"!canGoForward()\"\n (click)=\"navigateForward()\"\n title=\"Go forward\"\n class=\"nav-button\"\n >\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n <!-- Breadcrumb path -->\n <div class=\"breadcrumbs\">\n @for (item of breadcrumbs; track item; let last = $last) {\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n (click)=\"onBreadcrumbClick(item)\"\n [class.current]=\"last\"\n class=\"breadcrumb-item\"\n >\n {{ item.label }}\n </button>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n </div>\n }\n\n <!-- Folder tree content -->\n <div class=\"tree-content\">\n <!-- Loading state -->\n @if (isLoading) {\n <mj-loading text=\"Loading folders...\"></mj-loading>\n }\n\n <!-- Error state -->\n @if (errorMessage && !isLoading) {\n <div class=\"tree-error\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </div>\n <p class=\"error-text\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Folder list -->\n @if (!isLoading && !errorMessage) {\n <div class=\"folder-list\">\n @for (folder of folders; track folder) {\n <div\n class=\"folder-item\"\n (click)=\"onFolderClick(folder)\"\n >\n <i class=\"fa-solid fa-folder folder-icon\"></i>\n <span class=\"folder-name\">{{ folder.name }}</span>\n </div>\n }\n <!-- Empty state -->\n @if (folders.length === 0) {\n <div class=\"tree-placeholder\">\n <div class=\"placeholder-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <p class=\"placeholder-text\">No folders in this location</p>\n @if (account) {\n <p class=\"placeholder-hint\">\n Account: {{ account.account.Name }}\n </p>\n }\n <p class=\"placeholder-hint\">\n Path: {{ currentPath }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n", styles: [".folder-tree {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Navigation Bar */\n.navigation-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* Back/Forward buttons */\n.nav-buttons {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.nav-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n.nav-button i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.nav-button:hover:not([disabled]) {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.nav-button[disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.nav-button[disabled] i {\n color: var(--mj-text-disabled);\n}\n\n/* Breadcrumbs */\n.breadcrumbs {\n display: flex;\n align-items: center;\n gap: 4px;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n}\n\n.breadcrumb-item {\n flex-shrink: 0;\n height: 28px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n border-radius: 4px;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.breadcrumb-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.breadcrumb-item.current {\n color: var(--mj-brand-primary);\n font-weight: 600;\n cursor: default;\n}\n\n.breadcrumb-item.current:hover {\n background-color: transparent;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n/* Breadcrumbs scrollbar */\n.breadcrumbs::-webkit-scrollbar {\n height: 4px;\n}\n\n.breadcrumbs::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.breadcrumbs::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 2px;\n}\n\n.breadcrumbs::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Tree content area */\n.tree-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n/* Placeholder styling */\n.tree-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.placeholder-icon {\n font-size: 64px;\n margin-bottom: 16px;\n opacity: 0.5;\n color: var(--mj-status-warning);\n}\n\n.placeholder-text {\n margin: 0 0 8px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.placeholder-hint {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n/* Scrollbar styling for tree content */\n.tree-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.tree-content::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tree-content::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.tree-content::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Folder list */\n.folder-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.folder-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.folder-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.folder-icon {\n font-size: 16px;\n color: var(--mj-status-warning);\n flex-shrink: 0;\n}\n\n.folder-name {\n font-size: 14px;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Error state */\n.tree-error {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.error-icon {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-status-error);\n}\n\n.error-text {\n margin: 0;\n font-size: 14px;\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n/* Responsive adjustments */\n@media screen and (max-width: 768px) {\n .navigation-bar {\n padding: 6px 8px;\n }\n\n .nav-button {\n width: 24px;\n height: 24px;\n min-width: 24px;\n }\n\n .nav-button i {\n font-size: 11px;\n }\n\n .breadcrumb-item {\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .breadcrumb-separator {\n font-size: 9px;\n }\n\n .folder-item {\n padding: 8px 10px;\n }\n\n .folder-name {\n font-size: 13px;\n }\n}\n"] }]
358
+ args: [{ standalone: false, selector: 'mj-folder-tree', template: "<div class=\"folder-tree\">\n <!-- Navigation bar with back/forward buttons and breadcrumbs -->\n @if (account) {\n <div class=\"navigation-bar\">\n <!-- Back/Forward buttons -->\n <div class=\"nav-buttons\">\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n [disabled]=\"!canGoBack()\"\n (click)=\"navigateBack()\"\n title=\"Go back\"\n class=\"nav-button\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n [disabled]=\"!canGoForward()\"\n (click)=\"navigateForward()\"\n title=\"Go forward\"\n class=\"nav-button\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n <!-- Breadcrumb path -->\n <div class=\"breadcrumbs\">\n @for (item of breadcrumbs; track item; let last = $last) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"onBreadcrumbClick(item)\"\n [class.current]=\"last\"\n class=\"breadcrumb-item\">\n {{ item.label }}\n </button>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n </div>\n }\n\n <!-- Folder tree content -->\n <div class=\"tree-content\">\n <!-- Loading state -->\n @if (isLoading) {\n <mj-loading text=\"Loading folders...\"></mj-loading>\n }\n\n <!-- Error state -->\n @if (errorMessage && !isLoading) {\n <div class=\"tree-error\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </div>\n <p class=\"error-text\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Folder list -->\n @if (!isLoading && !errorMessage) {\n <div class=\"folder-list\">\n @for (folder of folders; track folder) {\n <div\n class=\"folder-item\"\n (click)=\"onFolderClick(folder)\"\n >\n <i class=\"fa-solid fa-folder folder-icon\"></i>\n <span class=\"folder-name\">{{ folder.name }}</span>\n </div>\n }\n <!-- Empty state -->\n @if (folders.length === 0) {\n <div class=\"tree-placeholder\">\n <div class=\"placeholder-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <p class=\"placeholder-text\">No folders in this location</p>\n @if (account) {\n <p class=\"placeholder-hint\">\n Account: {{ account.account.Name }}\n </p>\n }\n <p class=\"placeholder-hint\">\n Path: {{ currentPath }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n", styles: [".folder-tree {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Navigation Bar */\n.navigation-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* Back/Forward buttons */\n.nav-buttons {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.nav-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n.nav-button i {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.nav-button:hover:not([disabled]) {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.nav-button[disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.nav-button[disabled] i {\n color: var(--mj-text-disabled);\n}\n\n/* Breadcrumbs */\n.breadcrumbs {\n display: flex;\n align-items: center;\n gap: 4px;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n}\n\n.breadcrumb-item {\n flex-shrink: 0;\n height: 28px;\n padding: 0 10px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n border-radius: 4px;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.breadcrumb-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.breadcrumb-item.current {\n color: var(--mj-brand-primary);\n font-weight: 600;\n cursor: default;\n}\n\n.breadcrumb-item.current:hover {\n background-color: transparent;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n/* Breadcrumbs scrollbar */\n.breadcrumbs::-webkit-scrollbar {\n height: 4px;\n}\n\n.breadcrumbs::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.breadcrumbs::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 2px;\n}\n\n.breadcrumbs::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Tree content area */\n.tree-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n}\n\n/* Placeholder styling */\n.tree-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.placeholder-icon {\n font-size: 64px;\n margin-bottom: 16px;\n opacity: 0.5;\n color: var(--mj-status-warning);\n}\n\n.placeholder-text {\n margin: 0 0 8px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.placeholder-hint {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: var(--mj-text-disabled);\n}\n\n/* Scrollbar styling for tree content */\n.tree-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.tree-content::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tree-content::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.tree-content::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Folder list */\n.folder-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.folder-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.folder-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.folder-icon {\n font-size: 16px;\n color: var(--mj-status-warning);\n flex-shrink: 0;\n}\n\n.folder-name {\n font-size: 14px;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Error state */\n.tree-error {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.error-icon {\n font-size: 48px;\n margin-bottom: 16px;\n color: var(--mj-status-error);\n}\n\n.error-text {\n margin: 0;\n font-size: 14px;\n color: var(--mj-status-error);\n font-weight: 500;\n}\n\n/* Responsive adjustments */\n@media screen and (max-width: 768px) {\n .navigation-bar {\n padding: 6px 8px;\n }\n\n .nav-button {\n width: 24px;\n height: 24px;\n min-width: 24px;\n }\n\n .nav-button i {\n font-size: 11px;\n }\n\n .breadcrumb-item {\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .breadcrumb-separator {\n font-size: 9px;\n }\n\n .folder-item {\n padding: 8px 10px;\n }\n\n .folder-name {\n font-size: 13px;\n }\n}\n"] }]
359
359
  }], () => [], { account: [{
360
360
  type: Input
361
361
  }], folderSelected: [{
@@ -1 +1 @@
1
- {"version":3,"file":"folder-tree.component.js","sourceRoot":"","sources":["../../../src/lib/file-browser/folder-tree.component.ts","../../../src/lib/file-browser/folder-tree.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';\nimport { StorageAccountWithProvider } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Represents a breadcrumb item in the path\n */\nexport interface BreadcrumbItem {\n label: string;\n path: string;\n}\n\n/**\n * Represents a folder in the tree\n */\nexport interface FolderItem {\n name: string;\n fullPath: string;\n}\n\n/**\n * Folder tree navigation component with breadcrumbs and history navigation.\n * Provides Mac Finder-style navigation with back/forward buttons and breadcrumb path.\n * Loads actual folder structure from storage accounts via GraphQL.\n */\n@Component({\n standalone: false,\n selector: 'mj-folder-tree',\n templateUrl: './folder-tree.component.html',\n styleUrls: ['./folder-tree.component.css']\n})\nexport class FolderTreeComponent {\n /**\n * GraphQL client for file storage operations\n */\n private storageClient: GraphQLFileStorageClient;\n\n /**\n * Currently selected storage account with provider details\n */\n private _account: StorageAccountWithProvider | null = null;\n\n constructor() {\n this.storageClient = new GraphQLFileStorageClient(GraphQLDataProvider.Instance);\n }\n\n @Input()\n set account(value: StorageAccountWithProvider | null) {\n const previousAccount = this._account;\n this._account = value;\n\n if (value && !UUIDsEqual(value.account.ID, previousAccount?.account.ID)) {\n this.resetNavigation();\n this.loadFolders();\n }\n }\n get account(): StorageAccountWithProvider | null {\n return this._account;\n }\n\n /**\n * Emits when a folder is selected in the tree\n */\n @Output() folderSelected = new EventEmitter<string>();\n\n /**\n * Current folder path\n */\n public currentPath: string = '/';\n\n /**\n * Navigation history (for back button)\n */\n public history: string[] = [];\n\n /**\n * Current position in history\n */\n public historyIndex: number = -1;\n\n /**\n * Breadcrumb items for current path\n */\n public breadcrumbs: BreadcrumbItem[] = [];\n\n /**\n * Folders in current path\n */\n public folders: FolderItem[] = [];\n\n /**\n * Loading state\n */\n public isLoading: boolean = false;\n\n /**\n * Error message\n */\n public errorMessage: string | null = null;\n\n /**\n * Resets navigation when provider changes\n */\n private resetNavigation(): void {\n this.currentPath = '/';\n this.history = ['/'];\n this.historyIndex = 0;\n this.updateBreadcrumbs();\n }\n\n /**\n * Navigates to a specific folder path\n */\n public navigateToPath(path: string): void {\n // Don't navigate if already at this path\n if (path === this.currentPath) {\n return;\n }\n\n // Add to history if navigating from user action (not back/forward)\n if (this.historyIndex === this.history.length - 1) {\n this.history.push(path);\n this.historyIndex = this.history.length - 1;\n } else {\n // Navigating from middle of history - truncate forward history\n this.history = this.history.slice(0, this.historyIndex + 1);\n this.history.push(path);\n this.historyIndex = this.history.length - 1;\n }\n\n this.currentPath = path;\n this.updateBreadcrumbs();\n this.loadFolders();\n this.folderSelected.emit(path);\n }\n\n /**\n * Refreshes the current folder view without changing navigation\n * Used when folder structure changes (e.g., folder deleted) but we're staying in the same location\n */\n public refresh(): void {\n this.loadFolders();\n }\n\n /**\n * Navigates back in history\n */\n public navigateBack(): void {\n if (!this.canGoBack()) {\n return;\n }\n\n this.historyIndex--;\n this.currentPath = this.history[this.historyIndex];\n this.updateBreadcrumbs();\n this.folderSelected.emit(this.currentPath);\n this.loadFolders();\n }\n\n /**\n * Navigates forward in history\n */\n public navigateForward(): void {\n if (!this.canGoForward()) {\n return;\n }\n\n this.historyIndex++;\n this.currentPath = this.history[this.historyIndex];\n this.updateBreadcrumbs();\n this.folderSelected.emit(this.currentPath);\n this.loadFolders();\n }\n\n /**\n * Checks if can navigate back\n */\n public canGoBack(): boolean {\n return this.historyIndex > 0;\n }\n\n /**\n * Checks if can navigate forward\n */\n public canGoForward(): boolean {\n return this.historyIndex < this.history.length - 1;\n }\n\n /**\n * Updates breadcrumbs based on current path\n */\n private updateBreadcrumbs(): void {\n if (!this.account) {\n this.breadcrumbs = [];\n return;\n }\n\n // Start with account root (show account name)\n const items: BreadcrumbItem[] = [\n {\n label: this.account.account.Name,\n path: '/'\n }\n ];\n\n // Add path segments if not at root\n if (this.currentPath !== '/') {\n const segments = this.currentPath.split('/').filter(s => s.length > 0);\n let builtPath = '';\n\n for (const segment of segments) {\n builtPath += '/' + segment;\n items.push({\n label: segment,\n path: builtPath\n });\n }\n }\n\n this.breadcrumbs = items;\n }\n\n /**\n * Handles breadcrumb click\n */\n public onBreadcrumbClick(item: BreadcrumbItem): void {\n this.navigateToPath(item.path);\n this.loadFolders();\n }\n\n /**\n * Loads folders from the storage account for the current path\n */\n private async loadFolders(): Promise<void> {\n if (!this.account) {\n this.folders = [];\n return;\n }\n\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const listResult = await this.storageClient.ListObjects(\n this.account.account.ID,\n this.currentPath === '/' ? '' : this.currentPath,\n '/'\n );\n\n console.log('[FolderTree] ListObjects result:', {\n prefixesCount: listResult.prefixes?.length || 0,\n prefixes: listResult.prefixes,\n objectsCount: listResult.objects?.length || 0\n });\n\n // Convert prefixes to FolderItems\n const prefixes = listResult.prefixes || [];\n console.log('[FolderTree] Processing prefixes:', prefixes);\n this.folders = prefixes.map((prefix: string) => {\n // Remove trailing slash and get just the folder name\n const cleanPath = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const name = cleanPath.split('/').pop() || cleanPath;\n\n return {\n name,\n fullPath: prefix\n };\n });\n } catch (error) {\n console.error('Error loading folders:', error);\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load folders';\n this.folders = [];\n } finally {\n this.isLoading = false;\n }\n }\n\n /**\n * Handles folder click for navigation\n */\n public onFolderClick(folder: FolderItem): void {\n this.navigateToPath(folder.fullPath);\n this.loadFolders();\n }\n}\n","<div class=\"folder-tree\">\n <!-- Navigation bar with back/forward buttons and breadcrumbs -->\n @if (account) {\n <div class=\"navigation-bar\">\n <!-- Back/Forward buttons -->\n <div class=\"nav-buttons\">\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n [disabled]=\"!canGoBack()\"\n (click)=\"navigateBack()\"\n title=\"Go back\"\n class=\"nav-button\"\n >\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n [disabled]=\"!canGoForward()\"\n (click)=\"navigateForward()\"\n title=\"Go forward\"\n class=\"nav-button\"\n >\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n <!-- Breadcrumb path -->\n <div class=\"breadcrumbs\">\n @for (item of breadcrumbs; track item; let last = $last) {\n <button\n kendoButton\n fillMode=\"flat\"\n size=\"small\"\n (click)=\"onBreadcrumbClick(item)\"\n [class.current]=\"last\"\n class=\"breadcrumb-item\"\n >\n {{ item.label }}\n </button>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n </div>\n }\n\n <!-- Folder tree content -->\n <div class=\"tree-content\">\n <!-- Loading state -->\n @if (isLoading) {\n <mj-loading text=\"Loading folders...\"></mj-loading>\n }\n\n <!-- Error state -->\n @if (errorMessage && !isLoading) {\n <div class=\"tree-error\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </div>\n <p class=\"error-text\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Folder list -->\n @if (!isLoading && !errorMessage) {\n <div class=\"folder-list\">\n @for (folder of folders; track folder) {\n <div\n class=\"folder-item\"\n (click)=\"onFolderClick(folder)\"\n >\n <i class=\"fa-solid fa-folder folder-icon\"></i>\n <span class=\"folder-name\">{{ folder.name }}</span>\n </div>\n }\n <!-- Empty state -->\n @if (folders.length === 0) {\n <div class=\"tree-placeholder\">\n <div class=\"placeholder-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <p class=\"placeholder-text\">No folders in this location</p>\n @if (account) {\n <p class=\"placeholder-hint\">\n Account: {{ account.account.Name }}\n </p>\n }\n <p class=\"placeholder-hint\">\n Path: {{ currentPath }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"folder-tree.component.js","sourceRoot":"","sources":["../../../src/lib/file-browser/folder-tree.component.ts","../../../src/lib/file-browser/folder-tree.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';\nimport { StorageAccountWithProvider } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Represents a breadcrumb item in the path\n */\nexport interface BreadcrumbItem {\n label: string;\n path: string;\n}\n\n/**\n * Represents a folder in the tree\n */\nexport interface FolderItem {\n name: string;\n fullPath: string;\n}\n\n/**\n * Folder tree navigation component with breadcrumbs and history navigation.\n * Provides Mac Finder-style navigation with back/forward buttons and breadcrumb path.\n * Loads actual folder structure from storage accounts via GraphQL.\n */\n@Component({\n standalone: false,\n selector: 'mj-folder-tree',\n templateUrl: './folder-tree.component.html',\n styleUrls: ['./folder-tree.component.css']\n})\nexport class FolderTreeComponent {\n /**\n * GraphQL client for file storage operations\n */\n private storageClient: GraphQLFileStorageClient;\n\n /**\n * Currently selected storage account with provider details\n */\n private _account: StorageAccountWithProvider | null = null;\n\n constructor() {\n this.storageClient = new GraphQLFileStorageClient(GraphQLDataProvider.Instance);\n }\n\n @Input()\n set account(value: StorageAccountWithProvider | null) {\n const previousAccount = this._account;\n this._account = value;\n\n if (value && !UUIDsEqual(value.account.ID, previousAccount?.account.ID)) {\n this.resetNavigation();\n this.loadFolders();\n }\n }\n get account(): StorageAccountWithProvider | null {\n return this._account;\n }\n\n /**\n * Emits when a folder is selected in the tree\n */\n @Output() folderSelected = new EventEmitter<string>();\n\n /**\n * Current folder path\n */\n public currentPath: string = '/';\n\n /**\n * Navigation history (for back button)\n */\n public history: string[] = [];\n\n /**\n * Current position in history\n */\n public historyIndex: number = -1;\n\n /**\n * Breadcrumb items for current path\n */\n public breadcrumbs: BreadcrumbItem[] = [];\n\n /**\n * Folders in current path\n */\n public folders: FolderItem[] = [];\n\n /**\n * Loading state\n */\n public isLoading: boolean = false;\n\n /**\n * Error message\n */\n public errorMessage: string | null = null;\n\n /**\n * Resets navigation when provider changes\n */\n private resetNavigation(): void {\n this.currentPath = '/';\n this.history = ['/'];\n this.historyIndex = 0;\n this.updateBreadcrumbs();\n }\n\n /**\n * Navigates to a specific folder path\n */\n public navigateToPath(path: string): void {\n // Don't navigate if already at this path\n if (path === this.currentPath) {\n return;\n }\n\n // Add to history if navigating from user action (not back/forward)\n if (this.historyIndex === this.history.length - 1) {\n this.history.push(path);\n this.historyIndex = this.history.length - 1;\n } else {\n // Navigating from middle of history - truncate forward history\n this.history = this.history.slice(0, this.historyIndex + 1);\n this.history.push(path);\n this.historyIndex = this.history.length - 1;\n }\n\n this.currentPath = path;\n this.updateBreadcrumbs();\n this.loadFolders();\n this.folderSelected.emit(path);\n }\n\n /**\n * Refreshes the current folder view without changing navigation\n * Used when folder structure changes (e.g., folder deleted) but we're staying in the same location\n */\n public refresh(): void {\n this.loadFolders();\n }\n\n /**\n * Navigates back in history\n */\n public navigateBack(): void {\n if (!this.canGoBack()) {\n return;\n }\n\n this.historyIndex--;\n this.currentPath = this.history[this.historyIndex];\n this.updateBreadcrumbs();\n this.folderSelected.emit(this.currentPath);\n this.loadFolders();\n }\n\n /**\n * Navigates forward in history\n */\n public navigateForward(): void {\n if (!this.canGoForward()) {\n return;\n }\n\n this.historyIndex++;\n this.currentPath = this.history[this.historyIndex];\n this.updateBreadcrumbs();\n this.folderSelected.emit(this.currentPath);\n this.loadFolders();\n }\n\n /**\n * Checks if can navigate back\n */\n public canGoBack(): boolean {\n return this.historyIndex > 0;\n }\n\n /**\n * Checks if can navigate forward\n */\n public canGoForward(): boolean {\n return this.historyIndex < this.history.length - 1;\n }\n\n /**\n * Updates breadcrumbs based on current path\n */\n private updateBreadcrumbs(): void {\n if (!this.account) {\n this.breadcrumbs = [];\n return;\n }\n\n // Start with account root (show account name)\n const items: BreadcrumbItem[] = [\n {\n label: this.account.account.Name,\n path: '/'\n }\n ];\n\n // Add path segments if not at root\n if (this.currentPath !== '/') {\n const segments = this.currentPath.split('/').filter(s => s.length > 0);\n let builtPath = '';\n\n for (const segment of segments) {\n builtPath += '/' + segment;\n items.push({\n label: segment,\n path: builtPath\n });\n }\n }\n\n this.breadcrumbs = items;\n }\n\n /**\n * Handles breadcrumb click\n */\n public onBreadcrumbClick(item: BreadcrumbItem): void {\n this.navigateToPath(item.path);\n this.loadFolders();\n }\n\n /**\n * Loads folders from the storage account for the current path\n */\n private async loadFolders(): Promise<void> {\n if (!this.account) {\n this.folders = [];\n return;\n }\n\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const listResult = await this.storageClient.ListObjects(\n this.account.account.ID,\n this.currentPath === '/' ? '' : this.currentPath,\n '/'\n );\n\n console.log('[FolderTree] ListObjects result:', {\n prefixesCount: listResult.prefixes?.length || 0,\n prefixes: listResult.prefixes,\n objectsCount: listResult.objects?.length || 0\n });\n\n // Convert prefixes to FolderItems\n const prefixes = listResult.prefixes || [];\n console.log('[FolderTree] Processing prefixes:', prefixes);\n this.folders = prefixes.map((prefix: string) => {\n // Remove trailing slash and get just the folder name\n const cleanPath = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const name = cleanPath.split('/').pop() || cleanPath;\n\n return {\n name,\n fullPath: prefix\n };\n });\n } catch (error) {\n console.error('Error loading folders:', error);\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load folders';\n this.folders = [];\n } finally {\n this.isLoading = false;\n }\n }\n\n /**\n * Handles folder click for navigation\n */\n public onFolderClick(folder: FolderItem): void {\n this.navigateToPath(folder.fullPath);\n this.loadFolders();\n }\n}\n","<div class=\"folder-tree\">\n <!-- Navigation bar with back/forward buttons and breadcrumbs -->\n @if (account) {\n <div class=\"navigation-bar\">\n <!-- Back/Forward buttons -->\n <div class=\"nav-buttons\">\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n [disabled]=\"!canGoBack()\"\n (click)=\"navigateBack()\"\n title=\"Go back\"\n class=\"nav-button\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n [disabled]=\"!canGoForward()\"\n (click)=\"navigateForward()\"\n title=\"Go forward\"\n class=\"nav-button\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n <!-- Breadcrumb path -->\n <div class=\"breadcrumbs\">\n @for (item of breadcrumbs; track item; let last = $last) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"onBreadcrumbClick(item)\"\n [class.current]=\"last\"\n class=\"breadcrumb-item\">\n {{ item.label }}\n </button>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n </div>\n }\n\n <!-- Folder tree content -->\n <div class=\"tree-content\">\n <!-- Loading state -->\n @if (isLoading) {\n <mj-loading text=\"Loading folders...\"></mj-loading>\n }\n\n <!-- Error state -->\n @if (errorMessage && !isLoading) {\n <div class=\"tree-error\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </div>\n <p class=\"error-text\">{{ errorMessage }}</p>\n </div>\n }\n\n <!-- Folder list -->\n @if (!isLoading && !errorMessage) {\n <div class=\"folder-list\">\n @for (folder of folders; track folder) {\n <div\n class=\"folder-item\"\n (click)=\"onFolderClick(folder)\"\n >\n <i class=\"fa-solid fa-folder folder-icon\"></i>\n <span class=\"folder-name\">{{ folder.name }}</span>\n </div>\n }\n <!-- Empty state -->\n @if (folders.length === 0) {\n <div class=\"tree-placeholder\">\n <div class=\"placeholder-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <p class=\"placeholder-text\">No folders in this location</p>\n @if (account) {\n <p class=\"placeholder-hint\">\n Account: {{ account.account.Name }}\n </p>\n }\n <p class=\"placeholder-hint\">\n Path: {{ currentPath }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n"]}
@@ -1,14 +1,21 @@
1
1
  import { EventEmitter, OnInit } from '@angular/core';
2
2
  import { MJFileEntity } from '@memberjunction/core-entities';
3
- import { FileInfo, SelectEvent } from '@progress/kendo-angular-upload';
4
3
  import { z } from 'zod';
5
4
  import * as i0 from "@angular/core";
5
+ /**
6
+ * Minimal file info interface replacing Kendo's FileInfo.
7
+ */
8
+ export interface FileSelectInfo {
9
+ name: string;
10
+ size: number;
11
+ rawFile: File;
12
+ }
6
13
  export type FileUploadEvent = {
7
14
  success: true;
8
15
  file: MJFileEntity;
9
16
  } | {
10
17
  success: false;
11
- file: FileInfo;
18
+ file: FileSelectInfo;
12
19
  };
13
20
  declare const FileUploadMutationSchema: z.ZodObject<{
14
21
  CreateMJFile: z.ZodObject<{
@@ -129,10 +136,10 @@ declare const FileUploadMutationSchema: z.ZodObject<{
129
136
  };
130
137
  }>;
131
138
  type ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateMJFile']['File'];
132
- type UploadTuple = [FileInfo, ApiFile, string];
139
+ type UploadTuple = [FileSelectInfo, ApiFile, string];
133
140
  export declare class FileUploadComponent implements OnInit {
134
141
  ConfirmQueue: Array<UploadTuple>;
135
- UploadQueue: Array<FileInfo>;
142
+ UploadQueue: Array<FileSelectInfo>;
136
143
  private defaultProviderID;
137
144
  private md;
138
145
  get IsUploading(): boolean;
@@ -145,7 +152,10 @@ export declare class FileUploadComponent implements OnInit {
145
152
  Refresh(): Promise<void>;
146
153
  Confirm(): void;
147
154
  CancelConfirm(): Promise<void>;
148
- SelectEventHandler(e: SelectEvent): Promise<void>;
155
+ /**
156
+ * Handles the native file input change event.
157
+ */
158
+ OnFileSelected(event: Event): void;
149
159
  private _processUploadQueue;
150
160
  private _uploadFile;
151
161
  static ɵfac: i0.ɵɵFactoryDeclaration<FileUploadComponent, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,MAAM,EAAU,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,YAAY,EAA6C,MAAM,+BAA+B,CAAC;AAGxG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;AAExB,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAgCzG,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAChF,KAAK,WAAW,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE/C,qBAMa,mBAAoB,YAAW,MAAM;IACzC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAM;IACzC,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,EAAE,CAAkB;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;;IAIQ,QAAQ,UAAS;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAC1C,aAAa,qBAA4B;IACzC,UAAU,gCAAuC;IAE3D,QAAQ,IAAI,IAAI;IAIV,OAAO;IASb,OAAO;IAOD,aAAa;IAab,kBAAkB,CAAC,CAAC,EAAE,WAAW;YAQzB,mBAAmB;YAkCnB,WAAW;yCA5Fd,mBAAmB;2CAAnB,mBAAmB;CAoH/B"}
1
+ {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,MAAM,EAAU,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,YAAY,EAA6C,MAAM,+BAA+B,CAAC;AAGxG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;AAExB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAgC/G,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAChF,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,qBAMa,mBAAoB,YAAW,MAAM;IACzC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAM;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,EAAE,CAAkB;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;;IAIQ,QAAQ,UAAS;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAC1C,aAAa,qBAA4B;IACzC,UAAU,gCAAuC;IAE3D,QAAQ,IAAI,IAAI;IAIV,OAAO;IASb,OAAO;IAOD,aAAa;IAanB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK;YAyBb,mBAAmB;YAkCnB,WAAW;yCAhHd,mBAAmB;2CAAnB,mBAAmB;CAwI/B"}
@@ -4,29 +4,15 @@ import { MJFileSchema } from '@memberjunction/core-entities';
4
4
  import { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';
5
5
  import { z } from 'zod';
6
6
  import * as i0 from "@angular/core";
7
- import * as i1 from "@progress/kendo-angular-dialog";
8
- import * as i2 from "@progress/kendo-angular-buttons";
9
- import * as i3 from "@progress/kendo-angular-upload";
10
- function FileUploadComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
11
- const _r1 = i0.ɵɵgetCurrentView();
12
- i0.ɵɵelementStart(0, "kendo-dialog", 2);
13
- i0.ɵɵlistener("close", function FileUploadComponent_Conditional_2_Template_kendo_dialog_close_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelConfirm()); });
14
- i0.ɵɵelementStart(1, "p", 3);
15
- i0.ɵɵtext(2);
7
+ import * as i1 from "@memberjunction/ng-ui-components";
8
+ function FileUploadComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
9
+ i0.ɵɵelementStart(0, "p", 4);
10
+ i0.ɵɵtext(1);
16
11
  i0.ɵɵelementEnd();
17
- i0.ɵɵelementStart(3, "kendo-dialog-actions")(4, "button", 4);
18
- i0.ɵɵlistener("click", function FileUploadComponent_Conditional_2_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelConfirm()); });
19
- i0.ɵɵtext(5, "Cancel");
20
- i0.ɵɵelementEnd();
21
- i0.ɵɵelementStart(6, "button", 5);
22
- i0.ɵɵlistener("click", function FileUploadComponent_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Confirm()); });
23
- i0.ɵɵtext(7, "Overwrite");
24
- i0.ɵɵelementEnd()()();
25
12
  } if (rf & 2) {
26
- const ctx_r1 = i0.ɵɵnextContext();
27
- i0.ɵɵproperty("minWidth", 250)("width", 450);
28
- i0.ɵɵadvance(2);
29
- i0.ɵɵtextInterpolate1(" This will overwrite an existing file named '", ctx_r1.ConfirmQueue[0][0].name, "'. Are you sure you want to continue? ");
13
+ const ctx_r0 = i0.ɵɵnextContext();
14
+ i0.ɵɵadvance();
15
+ i0.ɵɵtextInterpolate1(" This will overwrite an existing file named '", ctx_r0.ConfirmQueue[0][0].name, "'. Are you sure you want to continue? ");
30
16
  } }
31
17
  const FileFieldsFragment = gql `
32
18
  fragment FileFields on MJFile_ {
@@ -103,10 +89,27 @@ export class FileUploadComponent {
103
89
  this.fileUpload.emit({ success: false, file });
104
90
  }
105
91
  }
106
- async SelectEventHandler(e) {
107
- e.preventDefault();
92
+ /**
93
+ * Handles the native file input change event.
94
+ */
95
+ OnFileSelected(event) {
96
+ const input = event.target;
97
+ if (!input.files || input.files.length === 0) {
98
+ return;
99
+ }
108
100
  this.uploadStarted.emit();
109
- this.UploadQueue = e.files;
101
+ // Convert native File objects to our FileSelectInfo format
102
+ for (let i = 0; i < input.files.length; i++) {
103
+ const nativeFile = input.files[i];
104
+ const fileInfo = {
105
+ name: nativeFile.name,
106
+ size: nativeFile.size,
107
+ rawFile: nativeFile,
108
+ };
109
+ this.UploadQueue.push(fileInfo);
110
+ }
111
+ // Reset input so the same file can be selected again
112
+ input.value = '';
110
113
  this._processUploadQueue();
111
114
  }
112
115
  async _processUploadQueue() {
@@ -165,22 +168,40 @@ export class FileUploadComponent {
165
168
  }
166
169
  }
167
170
  static ɵfac = function FileUploadComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FileUploadComponent)(); };
168
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { disabled: "disabled", CategoryID: "CategoryID" }, outputs: { uploadStarted: "uploadStarted", fileUpload: "fileUpload" }, standalone: false, decls: 3, vars: 3, consts: [[3, "select", "disabled", "multiple"], ["title", "Please confirm", 3, "minWidth", "width"], ["title", "Please confirm", 3, "close", "minWidth", "width"], [2, "margin", "30px", "text-align", "center"], ["kendoButton", "", 3, "click"], ["kendoButton", "", "themeColor", "primary", 3, "click"]], template: function FileUploadComponent_Template(rf, ctx) { if (rf & 1) {
169
- i0.ɵɵelementStart(0, "div")(1, "kendo-fileselect", 0);
170
- i0.ɵɵlistener("select", function FileUploadComponent_Template_kendo_fileselect_select_1_listener($event) { return ctx.SelectEventHandler($event); });
171
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { disabled: "disabled", CategoryID: "CategoryID" }, outputs: { uploadStarted: "uploadStarted", fileUpload: "fileUpload" }, standalone: false, decls: 13, vars: 7, consts: [[1, "mj-file-select"], [1, "fa-solid", "fa-upload"], ["type", "file", 1, "mj-file-input", 3, "change", "disabled"], ["Title", "Please confirm", 3, "Close", "Visible", "Width", "MinWidth"], [1, "confirm-message"], ["mjButton", "", "variant", "primary", 3, "click"], ["mjButton", "", 3, "click"]], template: function FileUploadComponent_Template(rf, ctx) { if (rf & 1) {
172
+ i0.ɵɵelementStart(0, "div")(1, "label", 0);
173
+ i0.ɵɵelement(2, "i", 1);
174
+ i0.ɵɵelementStart(3, "span");
175
+ i0.ɵɵtext(4, "Select file to upload");
171
176
  i0.ɵɵelementEnd();
172
- i0.ɵɵconditionalCreate(2, FileUploadComponent_Conditional_2_Template, 8, 3, "kendo-dialog", 1);
177
+ i0.ɵɵelementStart(5, "input", 2);
178
+ i0.ɵɵlistener("change", function FileUploadComponent_Template_input_change_5_listener($event) { return ctx.OnFileSelected($event); });
179
+ i0.ɵɵelementEnd()();
180
+ i0.ɵɵelementStart(6, "mj-dialog", 3);
181
+ i0.ɵɵlistener("Close", function FileUploadComponent_Template_mj_dialog_Close_6_listener() { return ctx.CancelConfirm(); });
182
+ i0.ɵɵconditionalCreate(7, FileUploadComponent_Conditional_7_Template, 2, 1, "p", 4);
183
+ i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 5);
184
+ i0.ɵɵlistener("click", function FileUploadComponent_Template_button_click_9_listener() { return ctx.Confirm(); });
185
+ i0.ɵɵtext(10, "Overwrite");
173
186
  i0.ɵɵelementEnd();
187
+ i0.ɵɵelementStart(11, "button", 6);
188
+ i0.ɵɵlistener("click", function FileUploadComponent_Template_button_click_11_listener() { return ctx.CancelConfirm(); });
189
+ i0.ɵɵtext(12, "Cancel");
190
+ i0.ɵɵelementEnd()()()();
174
191
  } if (rf & 2) {
175
192
  i0.ɵɵadvance();
176
- i0.ɵɵproperty("disabled", ctx.IsUploading || ctx.disabled)("multiple", false);
193
+ i0.ɵɵclassProp("disabled", ctx.IsUploading || ctx.disabled);
194
+ i0.ɵɵadvance(4);
195
+ i0.ɵɵproperty("disabled", ctx.IsUploading || ctx.disabled);
196
+ i0.ɵɵadvance();
197
+ i0.ɵɵproperty("Visible", ctx.ConfirmQueue.length > 0)("Width", 450)("MinWidth", 250);
177
198
  i0.ɵɵadvance();
178
- i0.ɵɵconditional(ctx.ConfirmQueue.length > 0 ? 2 : -1);
179
- } }, dependencies: [i1.DialogComponent, i1.DialogActionsComponent, i2.ButtonComponent, i3.FileSelectComponent], encapsulation: 2 });
199
+ i0.ɵɵconditional(ctx.ConfirmQueue.length > 0 ? 7 : -1);
200
+ } }, dependencies: [i1.MJButtonDirective, i1.MJDialogComponent, i1.MJDialogActionsComponent], styles: [".mj-file-select[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n margin: 8px 0;\n border: 1px dashed var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: border-color 0.15s, background-color 0.15s;\n}\n\n.mj-file-select[_ngcontent-%COMP%]:hover:not(.disabled) {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.mj-file-select.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: default;\n}\n\n.mj-file-input[_ngcontent-%COMP%] {\n display: none;\n}\n\n.confirm-message[_ngcontent-%COMP%] {\n margin: 30px;\n text-align: center;\n color: var(--mj-text-primary);\n}"] });
180
201
  }
181
202
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FileUploadComponent, [{
182
203
  type: Component,
183
- args: [{ standalone: false, selector: 'mj-files-file-upload', template: "<div>\n <kendo-fileselect [disabled]=\"IsUploading || disabled\" [multiple]=\"false\" (select)=\"SelectEventHandler($event)\"> </kendo-fileselect>\n @if (ConfirmQueue.length > 0) {\n <kendo-dialog title=\"Please confirm\" (close)=\"CancelConfirm()\" [minWidth]=\"250\" [width]=\"450\">\n <p style=\"margin: 30px; text-align: center\">\n This will overwrite an existing file named '{{ConfirmQueue[0][0].name}}'. Are you sure you want to continue?\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"CancelConfirm()\">Cancel</button>\n <button kendoButton (click)=\"Confirm()\" themeColor=\"primary\">Overwrite</button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n</div>\n" }]
204
+ args: [{ standalone: false, selector: 'mj-files-file-upload', template: "<div>\n <label class=\"mj-file-select\" [class.disabled]=\"IsUploading || disabled\">\n <i class=\"fa-solid fa-upload\"></i>\n <span>Select file to upload</span>\n <input\n type=\"file\"\n class=\"mj-file-input\"\n [disabled]=\"IsUploading || disabled\"\n (change)=\"OnFileSelected($event)\" />\n </label>\n\n <mj-dialog\n [Visible]=\"ConfirmQueue.length > 0\"\n Title=\"Please confirm\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"CancelConfirm()\">\n @if (ConfirmQueue.length > 0) {\n <p class=\"confirm-message\">\n This will overwrite an existing file named '{{ ConfirmQueue[0][0].name }}'. Are you sure you want to continue?\n </p>\n }\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"Confirm()\">Overwrite</button>\n <button mjButton (click)=\"CancelConfirm()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n</div>\n", styles: [".mj-file-select {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n margin: 8px 0;\n border: 1px dashed var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: border-color 0.15s, background-color 0.15s;\n}\n\n.mj-file-select:hover:not(.disabled) {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.mj-file-select.disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.mj-file-input {\n display: none;\n}\n\n.confirm-message {\n margin: 30px;\n text-align: center;\n color: var(--mj-text-primary);\n}\n"] }]
184
205
  }], () => [], { disabled: [{
185
206
  type: Input
186
207
  }], CategoryID: [{
@@ -190,5 +211,5 @@ export class FileUploadComponent {
190
211
  }], fileUpload: [{
191
212
  type: Output
192
213
  }] }); })();
193
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FileUploadComponent, { className: "FileUploadComponent", filePath: "src/lib/file-upload/file-upload.ts", lineNumber: 58 }); })();
214
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FileUploadComponent, { className: "FileUploadComponent", filePath: "src/lib/file-upload/file-upload.ts", lineNumber: 66 }); })();
194
215
  //# sourceMappingURL=file-upload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.js","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts","../../../src/lib/file-upload/file-upload.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\n\nimport { FileInfo, SelectEvent } from '@progress/kendo-angular-upload';\nimport { z } from 'zod';\n\nexport type FileUploadEvent = { success: true; file: MJFileEntity } | { success: false; file: FileInfo };\n\nconst FileFieldsFragment = gql`\n fragment FileFields on MJFile_ {\n Category\n CategoryID\n ContentType\n _mj__CreatedAt\n Description\n ID\n Name\n Provider\n ProviderID\n ProviderKey\n Status\n _mj__UpdatedAt\n }\n`;\n\nconst FileUploadMutation = gql`\n ${FileFieldsFragment}\n mutation CreateMJFile($input: CreateMJFileInput!) {\n CreateMJFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateMJFile: z.object({\n NameExists: z.boolean(),\n UploadUrl: z.string(),\n File: MJFileSchema.omit({ __mj_CreatedAt: true, __mj_UpdatedAt: true }).passthrough(),\n }),\n});\n\ntype ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateMJFile']['File'];\ntype UploadTuple = [FileInfo, ApiFile, string];\n\n@Component({\n standalone: false,\n selector: 'mj-files-file-upload',\n templateUrl: './file-upload.html',\n styleUrls: ['./file-upload.css'],\n})\nexport class FileUploadComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileInfo> = [];\n private defaultProviderID = '';\n private md = new Metadata();\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() {}\n\n @Input() disabled = false;\n @Input() CategoryID: string | undefined = undefined;\n @Output() uploadStarted = new EventEmitter<void>();\n @Output() fileUpload = new EventEmitter<FileUploadEvent>();\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async Refresh() {\n const rv = new RunView();\n const viewResults = await rv.RunView({ EntityName: 'MJ: File Storage Providers', ExtraFilter: 'IsActive = 1', OrderBy: 'Priority DESC' });\n const provider: MJFileStorageProviderEntity | undefined = viewResults.Results[0];\n if (typeof provider?.ID === 'string') {\n this.defaultProviderID = provider.ID;\n }\n }\n\n Confirm() {\n const confirmed = this.ConfirmQueue.shift();\n if (confirmed) {\n this._uploadFile(...confirmed);\n }\n }\n\n async CancelConfirm() {\n const cancelled = this.ConfirmQueue.shift();\n if (cancelled) {\n const [file, fileRecord] = cancelled;\n\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n await fileEntity.Delete();\n\n this.fileUpload.emit({ success: false, file });\n }\n }\n\n async SelectEventHandler(e: SelectEvent) {\n e.preventDefault();\n this.uploadStarted.emit();\n\n this.UploadQueue = e.files;\n this._processUploadQueue();\n }\n\n private async _processUploadQueue() {\n // for each selected file to upload\n let file = this.UploadQueue.shift();\n while (file) {\n const input = {\n Name: file.name,\n ProviderID: this.defaultProviderID,\n Status: 'Pending',\n CategoryID: this.CategoryID,\n };\n\n // call the gql\n const result = await GraphQLDataProvider.ExecuteGQL(FileUploadMutation, { input });\n\n // make sure the response is correct\n const parsedResult = FileUploadMutationSchema.safeParse(result);\n if (parsedResult.success) {\n const { File, UploadUrl, NameExists } = parsedResult.data.CreateMJFile;\n const uploadTuple: UploadTuple = [file, File, UploadUrl];\n\n // Confirm we want to overwrite\n if (NameExists) {\n this.ConfirmQueue.push(uploadTuple);\n } else {\n await this._uploadFile(...uploadTuple);\n }\n } else {\n console.error('The API returned an unexpected result', parsedResult.error.issues);\n this.fileUpload.emit({ success: false, file });\n }\n file = this.UploadQueue.shift();\n }\n }\n\n private async _uploadFile(file: FileInfo, fileRecord: ApiFile, uploadUrl: string) {\n try {\n // now upload to the url\n await window.fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'x-ms-blob-type': 'BlockBlob' },\n body: file.rawFile,\n });\n\n // now update that file to set status\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n fileEntity.Status = 'Uploaded';\n await fileEntity.Save();\n\n // emit an event about a new file uploaded, include the file data\n this.fileUpload.emit({ success: true, file: fileEntity });\n // Could also emit a progress event with each iteration\n } catch (e) {\n console.error(e);\n // something failed when actually uploading or when updating the API, what do to about pending file?\n this.fileUpload.emit({ success: false, file });\n }\n }\n}\n","<div>\n <kendo-fileselect [disabled]=\"IsUploading || disabled\" [multiple]=\"false\" (select)=\"SelectEventHandler($event)\"> </kendo-fileselect>\n @if (ConfirmQueue.length > 0) {\n <kendo-dialog title=\"Please confirm\" (close)=\"CancelConfirm()\" [minWidth]=\"250\" [width]=\"450\">\n <p style=\"margin: 30px; text-align: center\">\n This will overwrite an existing file named '{{ConfirmQueue[0][0].name}}'. Are you sure you want to continue?\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"CancelConfirm()\">Cancel</button>\n <button kendoButton (click)=\"Confirm()\" themeColor=\"primary\">Overwrite</button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n</div>\n"]}
1
+ {"version":3,"file":"file-upload.js","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts","../../../src/lib/file-upload/file-upload.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\n\nimport { z } from 'zod';\n\n/**\n * Minimal file info interface replacing Kendo's FileInfo.\n */\nexport interface FileSelectInfo {\n name: string;\n size: number;\n rawFile: File;\n}\n\nexport type FileUploadEvent = { success: true; file: MJFileEntity } | { success: false; file: FileSelectInfo };\n\nconst FileFieldsFragment = gql`\n fragment FileFields on MJFile_ {\n Category\n CategoryID\n ContentType\n _mj__CreatedAt\n Description\n ID\n Name\n Provider\n ProviderID\n ProviderKey\n Status\n _mj__UpdatedAt\n }\n`;\n\nconst FileUploadMutation = gql`\n ${FileFieldsFragment}\n mutation CreateMJFile($input: CreateMJFileInput!) {\n CreateMJFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateMJFile: z.object({\n NameExists: z.boolean(),\n UploadUrl: z.string(),\n File: MJFileSchema.omit({ __mj_CreatedAt: true, __mj_UpdatedAt: true }).passthrough(),\n }),\n});\n\ntype ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateMJFile']['File'];\ntype UploadTuple = [FileSelectInfo, ApiFile, string];\n\n@Component({\n standalone: false,\n selector: 'mj-files-file-upload',\n templateUrl: './file-upload.html',\n styleUrls: ['./file-upload.css'],\n})\nexport class FileUploadComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileSelectInfo> = [];\n private defaultProviderID = '';\n private md = new Metadata();\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() {}\n\n @Input() disabled = false;\n @Input() CategoryID: string | undefined = undefined;\n @Output() uploadStarted = new EventEmitter<void>();\n @Output() fileUpload = new EventEmitter<FileUploadEvent>();\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async Refresh() {\n const rv = new RunView();\n const viewResults = await rv.RunView({ EntityName: 'MJ: File Storage Providers', ExtraFilter: 'IsActive = 1', OrderBy: 'Priority DESC' });\n const provider: MJFileStorageProviderEntity | undefined = viewResults.Results[0];\n if (typeof provider?.ID === 'string') {\n this.defaultProviderID = provider.ID;\n }\n }\n\n Confirm() {\n const confirmed = this.ConfirmQueue.shift();\n if (confirmed) {\n this._uploadFile(...confirmed);\n }\n }\n\n async CancelConfirm() {\n const cancelled = this.ConfirmQueue.shift();\n if (cancelled) {\n const [file, fileRecord] = cancelled;\n\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n await fileEntity.Delete();\n\n this.fileUpload.emit({ success: false, file });\n }\n }\n\n /**\n * Handles the native file input change event.\n */\n OnFileSelected(event: Event) {\n const input = event.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) {\n return;\n }\n\n this.uploadStarted.emit();\n\n // Convert native File objects to our FileSelectInfo format\n for (let i = 0; i < input.files.length; i++) {\n const nativeFile = input.files[i];\n const fileInfo: FileSelectInfo = {\n name: nativeFile.name,\n size: nativeFile.size,\n rawFile: nativeFile,\n };\n this.UploadQueue.push(fileInfo);\n }\n\n // Reset input so the same file can be selected again\n input.value = '';\n\n this._processUploadQueue();\n }\n\n private async _processUploadQueue() {\n // for each selected file to upload\n let file = this.UploadQueue.shift();\n while (file) {\n const input = {\n Name: file.name,\n ProviderID: this.defaultProviderID,\n Status: 'Pending',\n CategoryID: this.CategoryID,\n };\n\n // call the gql\n const result = await GraphQLDataProvider.ExecuteGQL(FileUploadMutation, { input });\n\n // make sure the response is correct\n const parsedResult = FileUploadMutationSchema.safeParse(result);\n if (parsedResult.success) {\n const { File, UploadUrl, NameExists } = parsedResult.data.CreateMJFile;\n const uploadTuple: UploadTuple = [file, File, UploadUrl];\n\n // Confirm we want to overwrite\n if (NameExists) {\n this.ConfirmQueue.push(uploadTuple);\n } else {\n await this._uploadFile(...uploadTuple);\n }\n } else {\n console.error('The API returned an unexpected result', parsedResult.error.issues);\n this.fileUpload.emit({ success: false, file });\n }\n file = this.UploadQueue.shift();\n }\n }\n\n private async _uploadFile(file: FileSelectInfo, fileRecord: ApiFile, uploadUrl: string) {\n try {\n // now upload to the url\n await window.fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'x-ms-blob-type': 'BlockBlob' },\n body: file.rawFile,\n });\n\n // now update that file to set status\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n fileEntity.Status = 'Uploaded';\n await fileEntity.Save();\n\n // emit an event about a new file uploaded, include the file data\n this.fileUpload.emit({ success: true, file: fileEntity });\n // Could also emit a progress event with each iteration\n } catch (e) {\n console.error(e);\n // something failed when actually uploading or when updating the API, what do to about pending file?\n this.fileUpload.emit({ success: false, file });\n }\n }\n}\n","<div>\n <label class=\"mj-file-select\" [class.disabled]=\"IsUploading || disabled\">\n <i class=\"fa-solid fa-upload\"></i>\n <span>Select file to upload</span>\n <input\n type=\"file\"\n class=\"mj-file-input\"\n [disabled]=\"IsUploading || disabled\"\n (change)=\"OnFileSelected($event)\" />\n </label>\n\n <mj-dialog\n [Visible]=\"ConfirmQueue.length > 0\"\n Title=\"Please confirm\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"CancelConfirm()\">\n @if (ConfirmQueue.length > 0) {\n <p class=\"confirm-message\">\n This will overwrite an existing file named '{{ ConfirmQueue[0][0].name }}'. Are you sure you want to continue?\n </p>\n }\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"Confirm()\">Overwrite</button>\n <button mjButton (click)=\"CancelConfirm()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n</div>\n"]}
@@ -1,6 +1,7 @@
1
1
  import { OnChanges, OnInit, SimpleChanges } from '@angular/core';
2
2
  import { MJFileEntity } from '@memberjunction/core-entities';
3
3
  import { SharedService } from '@memberjunction/ng-shared';
4
+ import { ColDef, GridReadyEvent, type Theme } from 'ag-grid-community';
4
5
  import { FileUploadEvent } from '../file-upload/file-upload';
5
6
  import * as i0 from "@angular/core";
6
7
  export declare class FilesGridComponent implements OnInit, OnChanges {
@@ -8,10 +9,15 @@ export declare class FilesGridComponent implements OnInit, OnChanges {
8
9
  files: MJFileEntity[];
9
10
  isLoading: boolean;
10
11
  editFile: MJFileEntity | undefined;
12
+ GridTheme: Theme;
13
+ ColumnDefs: ColDef[];
14
+ DefaultColDef: ColDef;
15
+ private gridApi;
11
16
  constructor(sharedService: SharedService);
12
17
  CategoryID: string | undefined;
13
18
  ngOnInit(): void;
14
19
  ngOnChanges(changes: SimpleChanges): void;
20
+ OnGridReady(event: GridReadyEvent): void;
15
21
  /**
16
22
  * Resets the edited file.
17
23
  *
@@ -64,6 +70,14 @@ export declare class FilesGridComponent implements OnInit, OnChanges {
64
70
  * @returns {Promise<void>} - A promise that resolves when the data is refreshed.
65
71
  */
66
72
  Refresh(): Promise<void>;
73
+ /**
74
+ * Builds AG Grid column definitions from the entity fields.
75
+ */
76
+ private buildColumnDefs;
77
+ /**
78
+ * Creates a small action button element for the AG Grid cell renderer.
79
+ */
80
+ private createActionButton;
67
81
  static ɵfac: i0.ɵɵFactoryDeclaration<FilesGridComponent, never>;
68
82
  static ɵcmp: i0.ɵɵComponentDeclaration<FilesGridComponent, "mj-files-grid", never, { "CategoryID": { "alias": "CategoryID"; "required": false; }; }, {}, never, never, false, never>;
69
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"files-grid.d.ts","sourceRoot":"","sources":["../../../src/lib/files-grid/files-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;;AAgD7D,qBAMa,kBAAmB,YAAW,MAAM,EAAE,SAAS;IAK9C,OAAO,CAAC,aAAa;IAJ1B,KAAK,EAAE,YAAY,EAAE,CAAM;IAC3B,SAAS,EAAE,OAAO,CAAS;IAC3B,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAC;gBAEtB,aAAa,EAAE,aAAa;IAEvC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAEpD,QAAQ,IAAI,IAAI;IAIhB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAMzC;;;;;;OAMG;IACI,aAAa;IAKpB;;;;;;;OAOG;IACU,YAAY;IAezB;;;;;;OAMG;IACI,YAAY,GAAU,MAAM,YAAY,mBAkB7C;IAEF;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAOhD;;;;;;OAMG;IACI,UAAU,GAAU,MAAM,YAAY,mBAY3C;IAEF;;;;;OAKG;IACI,gBAAgB,CAAC,CAAC,EAAE,eAAe;IAU1C;;;OAGG;IACG,OAAO;yCAvIF,kBAAkB;2CAAlB,kBAAkB;CAuJ9B"}
1
+ {"version":3,"file":"files-grid.d.ts","sourceRoot":"","sources":["../../../src/lib/files-grid/files-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EACL,MAAM,EACN,cAAc,EAMd,KAAK,KAAK,EAEX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;;AAmD7D,qBAMa,kBAAmB,YAAW,MAAM,EAAE,SAAS;IAe9C,OAAO,CAAC,aAAa;IAd1B,KAAK,EAAE,YAAY,EAAE,CAAM;IAC3B,SAAS,EAAE,OAAO,CAAS;IAC3B,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAC;IAGnC,SAAS,EAAE,KAAK,CAA6C;IAC7D,UAAU,EAAE,MAAM,EAAE,CAAM;IAC1B,aAAa,EAAE,MAAM,CAI1B;IACF,OAAO,CAAC,OAAO,CAAwB;gBAEnB,aAAa,EAAE,aAAa;IAIvC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAEpD,QAAQ,IAAI,IAAI;IAIhB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAMlC,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAI/C;;;;;;OAMG;IACI,aAAa;IAKpB;;;;;;;OAOG;IACU,YAAY;IAmBzB;;;;;;OAMG;IACI,YAAY,GAAU,MAAM,YAAY,mBAkB7C;IAEF;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAMhD;;;;;;OAMG;IACI,UAAU,GAAU,MAAM,YAAY,mBAY3C;IAEF;;;;;OAKG;IACI,gBAAgB,CAAC,CAAC,EAAE,eAAe;IAW1C;;;OAGG;IACG,OAAO;IAiBb;;OAEG;IACH,OAAO,CAAC,eAAe;IAmCvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;yCArNf,kBAAkB;2CAAlB,kBAAkB;CA8N9B"}