@memberjunction/ng-file-storage 6.2.0-edge.0 → 6.2.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/lib/admin/storage-admin-dialog.component.d.ts +1 -1
  2. package/dist/lib/admin/storage-admin-dialog.component.js +2 -2
  3. package/dist/lib/admin/storage-admin-dialog.component.js.map +1 -1
  4. package/dist/lib/category-tree/category-tree.d.ts +83 -9
  5. package/dist/lib/category-tree/category-tree.d.ts.map +1 -1
  6. package/dist/lib/category-tree/category-tree.js +192 -50
  7. package/dist/lib/category-tree/category-tree.js.map +1 -1
  8. package/dist/lib/file-browser/file-browser.component.d.ts +30 -4
  9. package/dist/lib/file-browser/file-browser.component.d.ts.map +1 -1
  10. package/dist/lib/file-browser/file-browser.component.js +68 -16
  11. package/dist/lib/file-browser/file-browser.component.js.map +1 -1
  12. package/dist/lib/file-browser/file-grid.component.d.ts +404 -58
  13. package/dist/lib/file-browser/file-grid.component.d.ts.map +1 -1
  14. package/dist/lib/file-browser/file-grid.component.js +1040 -396
  15. package/dist/lib/file-browser/file-grid.component.js.map +1 -1
  16. package/dist/lib/file-browser/folder-tree.component.d.ts +65 -9
  17. package/dist/lib/file-browser/folder-tree.component.d.ts.map +1 -1
  18. package/dist/lib/file-browser/folder-tree.component.js +166 -58
  19. package/dist/lib/file-browser/folder-tree.component.js.map +1 -1
  20. package/dist/lib/file-browser/storage-providers-list.component.d.ts +55 -7
  21. package/dist/lib/file-browser/storage-providers-list.component.d.ts.map +1 -1
  22. package/dist/lib/file-browser/storage-providers-list.component.js +124 -34
  23. package/dist/lib/file-browser/storage-providers-list.component.js.map +1 -1
  24. package/dist/lib/file-upload/file-upload.d.ts +22 -2
  25. package/dist/lib/file-upload/file-upload.d.ts.map +1 -1
  26. package/dist/lib/file-upload/file-upload.js +40 -10
  27. package/dist/lib/file-upload/file-upload.js.map +1 -1
  28. package/dist/lib/files-grid/files-grid.d.ts +28 -4
  29. package/dist/lib/files-grid/files-grid.d.ts.map +1 -1
  30. package/dist/lib/files-grid/files-grid.js +71 -23
  31. package/dist/lib/files-grid/files-grid.js.map +1 -1
  32. package/dist/lib/record-attachments/record-attachments.component.d.ts +15 -7
  33. package/dist/lib/record-attachments/record-attachments.component.d.ts.map +1 -1
  34. package/dist/lib/record-attachments/record-attachments.component.js +34 -18
  35. package/dist/lib/record-attachments/record-attachments.component.js.map +1 -1
  36. package/package.json +13 -13
@@ -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, inject } from '@angular/core';\nimport { FileStorageEngineBase, StorageAccountWithProvider, MJFileStorageAccountEntity } from '@memberjunction/core-entities';\nimport { Metadata, type IMetadataProvider } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { StorageAdminTab } from '../admin/storage-admin-dialog.component';\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 private cdr = inject(ChangeDetectorRef);\n\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 /**\n * Whether current user has admin rights to configure storage accounts or providers.\n */\n public userCanManage: boolean = false;\n\n /**\n * Admin dialog state\n */\n public isManageDialogOpen: boolean = false;\n public adminDialogTab: StorageAdminTab = 'accounts';\n public accountToEdit: MJFileStorageAccountEntity | null = null;\n\n public Provider: IMetadataProvider | null = null;\n\n public get ProviderToUse(): IMetadataProvider {\n return this.Provider ?? Metadata.Provider;\n }\n\n constructor() {}\n\n ngOnInit(): void {\n if (!this.userCanManage) {\n this.checkPermissions();\n }\n this.loadAccounts();\n }\n\n /**\n * Checks if current user has create or update permissions on storage entities.\n */\n private checkPermissions(): void {\n try {\n const md = this.ProviderToUse;\n const user = md.CurrentUser;\n if (!user) {\n return;\n }\n\n const provEntity = md.Entities.find(e => e.Name === 'MJ: File Storage Providers');\n const acctEntity = md.Entities.find(e => e.Name === 'MJ: File Storage Accounts');\n\n const provCanManage = provEntity ? provEntity.GetUserPermisions(user).CanCreate || provEntity.GetUserPermisions(user).CanUpdate : false;\n const acctCanManage = acctEntity ? acctEntity.GetUserPermisions(user).CanCreate || acctEntity.GetUserPermisions(user).CanUpdate : false;\n\n this.userCanManage = !!(provCanManage || acctCanManage);\n } catch {\n this.userCanManage = false;\n }\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(forceRefresh = false): Promise<void> {\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const engine = FileStorageEngineBase.Instance;\n await engine.Config(forceRefresh);\n\n // Only show accounts whose provider is active\n this.accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive !== false);\n\n if (this.accounts.length === 0 && !forceRefresh) {\n await engine.Config(true);\n this.accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive !== false);\n }\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 void this.loadAccounts(true);\n }\n\n /**\n * Opens the storage administration dialog\n */\n public openAdminDialog(tab: StorageAdminTab = 'accounts', account?: MJFileStorageAccountEntity | null): void {\n this.adminDialogTab = tab;\n this.accountToEdit = account ?? null;\n this.isManageDialogOpen = true;\n this.cdr.markForCheck();\n }\n\n /**\n * Closes the storage administration dialog\n */\n public closeAdminDialog(): void {\n this.isManageDialogOpen = false;\n this.accountToEdit = null;\n this.cdr.markForCheck();\n }\n\n /**\n * Handles storage configuration changes from the admin dialog\n */\n public onAdminAccountsChanged(): void {\n this.refresh();\n }\n\n /**\n * Handles inline edit click on an account item\n */\n public onEditAccountClick(item: StorageAccountWithProvider, event: MouseEvent): void {\n event.stopPropagation();\n this.openAdminDialog('accounts', item.account);\n }\n}\n","<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n @if (userCanManage) {\n <div class=\"admin-header-actions\">\n <button\n type=\"button\"\n class=\"admin-action-btn\"\n title=\"Add Storage Account\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button\n type=\"button\"\n class=\"admin-action-btn\"\n title=\"Manage Storage Providers & Accounts\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-gear\"></i>\n </button>\n </div>\n }\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]=\"userCanManage ? 'No storage accounts configured' : 'No storage accounts available'\"\n [Message]=\"userCanManage ? 'Configure storage accounts to connect MemberJunction to cloud storage providers.' : 'Contact your administrator to set up file storage accounts.'\"\n Size=\"compact\">\n @if (userCanManage) {\n <button\n type=\"button\"\n class=\"mj-empty-action-btn\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Configure Account</span>\n </button>\n }\n </mj-empty-state>\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item.account.ID) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\">\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 @if (userCanManage) {\n <button\n type=\"button\"\n class=\"provider-edit-btn\"\n title=\"Edit Storage Account\"\n (click)=\"onEditAccountClick(item, $event)\">\n <i class=\"fa-solid fa-pen-to-square\"></i>\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Storage Administration Dialog -->\n@if (isManageDialogOpen) {\n <mj-storage-admin-dialog\n [Visible]=\"isManageDialogOpen\"\n [ActiveTab]=\"adminDialogTab\"\n (Close)=\"closeAdminDialog()\"\n (AccountsChanged)=\"onAdminAccountsChanged()\">\n </mj-storage-admin-dialog>\n}\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, inject } from '@angular/core';\nimport { FileStorageEngineBase, StorageAccountWithProvider, MJFileStorageAccountEntity } from '@memberjunction/core-entities';\nimport { Metadata, type IMetadataProvider } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { StorageAdminTab } from '../admin/storage-admin-dialog.component';\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 private cdr = inject(ChangeDetectorRef);\n\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 * @deprecated Use {@link AccountSelected}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (accountSelected) keeps working. Must stay AFTER AccountSelected: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() accountSelected = this.AccountSelected;\n\n /**\n * All available storage accounts with their provider details.\n */\n public Accounts: StorageAccountWithProvider[] = [];\n\n /** @deprecated Use {@link Accounts}. */\n public get accounts(): StorageAccountWithProvider[] {\n return this.Accounts;\n }\n /** @deprecated Use {@link Accounts}. */\n public set accounts(value: StorageAccountWithProvider[]) {\n this.Accounts = value;\n }\n\n /**\n * Currently selected account.\n */\n public SelectedAccount: StorageAccountWithProvider | null = null;\n\n /** @deprecated Use {@link SelectedAccount}. */\n public get selectedAccount(): StorageAccountWithProvider | null {\n return this.SelectedAccount;\n }\n /** @deprecated Use {@link SelectedAccount}. */\n public set selectedAccount(value: StorageAccountWithProvider | null) {\n this.SelectedAccount = value;\n }\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 /**\n * Whether current user has admin rights to configure storage accounts or providers.\n */\n public UserCanManage: boolean = false;\n\n /** @deprecated Use {@link UserCanManage}. */\n public get userCanManage(): boolean {\n return this.UserCanManage;\n }\n /** @deprecated Use {@link UserCanManage}. */\n public set userCanManage(value: boolean) {\n this.UserCanManage = value;\n }\n\n /**\n * Admin dialog state\n */\n public IsManageDialogOpen: boolean = false;\n\n /** @deprecated Use {@link IsManageDialogOpen}. */\n public get isManageDialogOpen(): boolean {\n return this.IsManageDialogOpen;\n }\n /** @deprecated Use {@link IsManageDialogOpen}. */\n public set isManageDialogOpen(value: boolean) {\n this.IsManageDialogOpen = value;\n }\n public AdminDialogTab: StorageAdminTab = 'accounts';\n\n /** @deprecated Use {@link AdminDialogTab}. */\n public get adminDialogTab(): StorageAdminTab {\n return this.AdminDialogTab;\n }\n /** @deprecated Use {@link AdminDialogTab}. */\n public set adminDialogTab(value: StorageAdminTab) {\n this.AdminDialogTab = value;\n }\n public AccountToEdit: MJFileStorageAccountEntity | null = null;\n\n /** @deprecated Use {@link AccountToEdit}. */\n public get accountToEdit(): MJFileStorageAccountEntity | null {\n return this.AccountToEdit;\n }\n /** @deprecated Use {@link AccountToEdit}. */\n public set accountToEdit(value: MJFileStorageAccountEntity | null) {\n this.AccountToEdit = value;\n }\n\n public Provider: IMetadataProvider | null = null;\n\n public get ProviderToUse(): IMetadataProvider {\n return this.Provider ?? Metadata.Provider;\n }\n\n constructor() {}\n\n ngOnInit(): void {\n if (!this.UserCanManage) {\n this.checkPermissions();\n }\n this.loadAccounts();\n }\n\n /**\n * Checks if current user has create or update permissions on storage entities.\n */\n private checkPermissions(): void {\n try {\n const md = this.ProviderToUse;\n const user = md.CurrentUser;\n if (!user) {\n return;\n }\n\n const provEntity = md.Entities.find(e => e.Name === 'MJ: File Storage Providers');\n const acctEntity = md.Entities.find(e => e.Name === 'MJ: File Storage Accounts');\n\n const provCanManage = provEntity ? provEntity.GetUserPermisions(user).CanCreate || provEntity.GetUserPermisions(user).CanUpdate : false;\n const acctCanManage = acctEntity ? acctEntity.GetUserPermisions(user).CanCreate || acctEntity.GetUserPermisions(user).CanUpdate : false;\n\n this.UserCanManage = !!(provCanManage || acctCanManage);\n } catch {\n this.UserCanManage = false;\n }\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(forceRefresh = false): Promise<void> {\n this.isLoading = true;\n this.errorMessage = null;\n\n try {\n const engine = FileStorageEngineBase.Instance;\n await engine.Config(forceRefresh);\n\n // Only show accounts whose provider is active\n this.Accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive !== false);\n\n if (this.Accounts.length === 0 && !forceRefresh) {\n await engine.Config(true);\n this.Accounts = engine.AccountsWithProviders.filter(a => a.provider.IsActive !== false);\n }\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 /** @deprecated Use {@link SelectAccount}. */\n public selectAccount(accountWithProvider: StorageAccountWithProvider): void {\n return this.SelectAccount(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 /** @deprecated Use {@link IsSelected}. */\n public isSelected(accountWithProvider: StorageAccountWithProvider): boolean {\n return this.IsSelected(accountWithProvider);\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 /** @deprecated Use {@link GetProviderIcon}. */\n public getProviderIcon(providerName: string): string {\n return this.GetProviderIcon(providerName);\n }\n\n /**\n * Refreshes the accounts list by forcing a reload from the database.\n */\n public Refresh(): void {\n void this.loadAccounts(true);\n }\n\n /** @deprecated Use {@link Refresh}. */\n public refresh(): void {\n return this.Refresh();\n }\n\n /**\n * Opens the storage administration dialog\n */\n public OpenAdminDialog(tab: StorageAdminTab = 'accounts', account?: MJFileStorageAccountEntity | null): void {\n this.AdminDialogTab = tab;\n this.AccountToEdit = account ?? null;\n this.IsManageDialogOpen = true;\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link OpenAdminDialog}. */\n public openAdminDialog(tab: StorageAdminTab = 'accounts', account?: MJFileStorageAccountEntity | null): void {\n return this.OpenAdminDialog(tab, account);\n }\n\n /**\n * Closes the storage administration dialog\n */\n public CloseAdminDialog(): void {\n this.IsManageDialogOpen = false;\n this.AccountToEdit = null;\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link CloseAdminDialog}. */\n public closeAdminDialog(): void {\n return this.CloseAdminDialog();\n }\n\n /**\n * Handles storage configuration changes from the admin dialog\n */\n public OnAdminAccountsChanged(): void {\n this.Refresh();\n }\n\n /** @deprecated Use {@link OnAdminAccountsChanged}. */\n public onAdminAccountsChanged(): void {\n return this.OnAdminAccountsChanged();\n }\n\n /**\n * Handles inline edit click on an account item\n */\n public OnEditAccountClick(item: StorageAccountWithProvider, event: MouseEvent): void {\n event.stopPropagation();\n this.OpenAdminDialog('accounts', item.account);\n }\n\n /** @deprecated Use {@link OnEditAccountClick}. */\n public onEditAccountClick(item: StorageAccountWithProvider, event: MouseEvent): void {\n return this.OnEditAccountClick(item, event);\n }\n}\n","<div class=\"providers-list\">\n <!-- Header -->\n <div class=\"providers-header\">\n <span class=\"header-title\">Storage Accounts</span>\n @if (userCanManage) {\n <div class=\"admin-header-actions\">\n <button\n type=\"button\"\n class=\"admin-action-btn\"\n title=\"Add Storage Account\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button\n type=\"button\"\n class=\"admin-action-btn\"\n title=\"Manage Storage Providers & Accounts\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-gear\"></i>\n </button>\n </div>\n }\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]=\"userCanManage ? 'No storage accounts configured' : 'No storage accounts available'\"\n [Message]=\"userCanManage ? 'Configure storage accounts to connect MemberJunction to cloud storage providers.' : 'Contact your administrator to set up file storage accounts.'\"\n Size=\"compact\">\n @if (userCanManage) {\n <button\n type=\"button\"\n class=\"mj-empty-action-btn\"\n (click)=\"openAdminDialog('accounts')\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Configure Account</span>\n </button>\n }\n </mj-empty-state>\n }\n\n <!-- Account List -->\n @if (!isLoading && !errorMessage && accounts.length > 0) {\n <div class=\"providers-container\">\n @for (item of accounts; track item.account.ID) {\n <div\n class=\"provider-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectAccount(item)\"\n [title]=\"item.account.Description || item.account.Name\">\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 @if (userCanManage) {\n <button\n type=\"button\"\n class=\"provider-edit-btn\"\n title=\"Edit Storage Account\"\n (click)=\"onEditAccountClick(item, $event)\">\n <i class=\"fa-solid fa-pen-to-square\"></i>\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Storage Administration Dialog -->\n@if (isManageDialogOpen) {\n <mj-storage-admin-dialog\n [Visible]=\"isManageDialogOpen\"\n [ActiveTab]=\"adminDialogTab\"\n (Close)=\"closeAdminDialog()\"\n (AccountsChanged)=\"onAdminAccountsChanged()\">\n </mj-storage-admin-dialog>\n}\n"]}
@@ -145,9 +145,29 @@ export declare class FileUploadComponent extends BaseAngularComponent implements
145
145
  private get md();
146
146
  get IsUploading(): boolean;
147
147
  constructor();
148
- disabled: boolean;
148
+ Disabled: boolean;
149
+ /** @deprecated Use {@link Disabled}. */
150
+ set disabled(value: FileUploadComponent['Disabled']);
151
+ /** @deprecated Use {@link Disabled}. */
152
+ get disabled(): FileUploadComponent['Disabled'];
149
153
  CategoryID: string | undefined;
154
+ UploadStarted: EventEmitter<void>;
155
+ /**
156
+ * @deprecated Use {@link UploadStarted}.
157
+ *
158
+ * The same emitter under the old binding name, so a template still binding
159
+ * (uploadStarted) keeps working. Must stay AFTER UploadStarted: class fields
160
+ * initialise in order, and the other way round this captures undefined.
161
+ */
150
162
  uploadStarted: EventEmitter<void>;
163
+ FileUpload: EventEmitter<FileUploadEvent>;
164
+ /**
165
+ * @deprecated Use {@link FileUpload}.
166
+ *
167
+ * The same emitter under the old binding name, so a template still binding
168
+ * (fileUpload) keeps working. Must stay AFTER FileUpload: class fields
169
+ * initialise in order, and the other way round this captures undefined.
170
+ */
151
171
  fileUpload: EventEmitter<FileUploadEvent>;
152
172
  ngOnInit(): void;
153
173
  Refresh(): Promise<void>;
@@ -160,7 +180,7 @@ export declare class FileUploadComponent extends BaseAngularComponent implements
160
180
  private _processUploadQueue;
161
181
  private _uploadFile;
162
182
  static ɵfac: i0.ɵɵFactoryDeclaration<FileUploadComponent, never>;
163
- static ɵcmp: i0.ɵɵComponentDeclaration<FileUploadComponent, "mj-files-file-upload", never, { "disabled": { "alias": "disabled"; "required": false; }; "CategoryID": { "alias": "CategoryID"; "required": false; }; }, { "uploadStarted": "uploadStarted"; "fileUpload": "fileUpload"; }, never, never, false, never>;
183
+ static ɵcmp: i0.ɵɵComponentDeclaration<FileUploadComponent, "mj-files-file-upload", never, { "Disabled": { "alias": "Disabled"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "CategoryID": { "alias": "CategoryID"; "required": false; }; }, { "UploadStarted": "UploadStarted"; "uploadStarted": "uploadStarted"; "FileUpload": "FileUpload"; "fileUpload": "fileUpload"; }, never, never, false, never>;
164
184
  }
165
185
  export {};
166
186
  //# sourceMappingURL=file-upload.d.ts.map
@@ -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;AAC/E,OAAO,EAAE,YAAY,EAAoE,MAAM,+BAA+B,CAAC;AAE/H,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,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,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,qBAMa,mBAAoB,SAAQ,oBAAqB,YAAW,MAAM;IACtE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAM;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,KAAK,EAAE,GAAiC;IAE/C,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;IAWb,OAAO;IAOD,aAAa;IAanB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK;YAyBb,mBAAmB;YAkCnB,WAAW;yCAlHd,mBAAmB;2CAAnB,mBAAmB;CA0I/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;AAC/E,OAAO,EAAE,YAAY,EAAoE,MAAM,+BAA+B,CAAC;AAE/H,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,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,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,qBAMa,mBAAoB,SAAQ,oBAAqB,YAAW,MAAM;IACtE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAM;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,KAAK,EAAE,GAAiC;IAE/C,IAAI,WAAW,IAAI,OAAO,CAEzB;;IAIQ,QAAQ,UAAS;IAE1B,wCAAwC;IACxC,IAAa,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EAE3D;IACD,wCAAwC;IACxC,IAAI,QAAQ,IAAI,mBAAmB,CAAC,UAAU,CAAC,CAE9C;IACQ,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAC1C,aAAa,qBAA4B;IAEnD;;;;;;OAMG;IACO,aAAa,qBAAsB;IACnC,UAAU,gCAAuC;IAE3D;;;;;;OAMG;IACO,UAAU,gCAAmB;IAEvC,QAAQ,IAAI,IAAI;IAIV,OAAO;IAWb,OAAO;IAOD,aAAa;IAanB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK;YAyBb,mBAAmB;YAkCnB,WAAW;yCA7Id,mBAAmB;2CAAnB,mBAAmB;CAqK/B"}
@@ -58,10 +58,34 @@ export class FileUploadComponent extends BaseAngularComponent {
58
58
  return this.UploadQueue.length + this.ConfirmQueue.length > 0;
59
59
  }
60
60
  constructor() { super(); }
61
- disabled = false;
61
+ Disabled = false;
62
+ /** @deprecated Use {@link Disabled}. */
63
+ set disabled(value) {
64
+ this.Disabled = value;
65
+ }
66
+ /** @deprecated Use {@link Disabled}. */
67
+ get disabled() {
68
+ return this.Disabled;
69
+ }
62
70
  CategoryID = undefined;
63
- uploadStarted = new EventEmitter();
64
- fileUpload = new EventEmitter();
71
+ UploadStarted = new EventEmitter();
72
+ /**
73
+ * @deprecated Use {@link UploadStarted}.
74
+ *
75
+ * The same emitter under the old binding name, so a template still binding
76
+ * (uploadStarted) keeps working. Must stay AFTER UploadStarted: class fields
77
+ * initialise in order, and the other way round this captures undefined.
78
+ */
79
+ uploadStarted = this.UploadStarted;
80
+ FileUpload = new EventEmitter();
81
+ /**
82
+ * @deprecated Use {@link FileUpload}.
83
+ *
84
+ * The same emitter under the old binding name, so a template still binding
85
+ * (fileUpload) keeps working. Must stay AFTER FileUpload: class fields
86
+ * initialise in order, and the other way round this captures undefined.
87
+ */
88
+ fileUpload = this.FileUpload;
65
89
  ngOnInit() {
66
90
  this.Refresh();
67
91
  }
@@ -88,7 +112,7 @@ export class FileUploadComponent extends BaseAngularComponent {
88
112
  const fileEntity = await this.md.GetEntityObject('MJ: Files');
89
113
  await fileEntity.LoadFromData(fileRecord);
90
114
  await fileEntity.Delete();
91
- this.fileUpload.emit({ success: false, file });
115
+ this.FileUpload.emit({ success: false, file });
92
116
  }
93
117
  }
94
118
  /**
@@ -99,7 +123,7 @@ export class FileUploadComponent extends BaseAngularComponent {
99
123
  if (!input.files || input.files.length === 0) {
100
124
  return;
101
125
  }
102
- this.uploadStarted.emit();
126
+ this.UploadStarted.emit();
103
127
  // Convert native File objects to our FileSelectInfo format
104
128
  for (let i = 0; i < input.files.length; i++) {
105
129
  const nativeFile = input.files[i];
@@ -141,7 +165,7 @@ export class FileUploadComponent extends BaseAngularComponent {
141
165
  }
142
166
  else {
143
167
  console.error('The API returned an unexpected result', parsedResult.error.issues);
144
- this.fileUpload.emit({ success: false, file });
168
+ this.FileUpload.emit({ success: false, file });
145
169
  }
146
170
  file = this.UploadQueue.shift();
147
171
  }
@@ -160,17 +184,17 @@ export class FileUploadComponent extends BaseAngularComponent {
160
184
  fileEntity.Status = 'Uploaded';
161
185
  await fileEntity.Save();
162
186
  // emit an event about a new file uploaded, include the file data
163
- this.fileUpload.emit({ success: true, file: fileEntity });
187
+ this.FileUpload.emit({ success: true, file: fileEntity });
164
188
  // Could also emit a progress event with each iteration
165
189
  }
166
190
  catch (e) {
167
191
  console.error(e);
168
192
  // something failed when actually uploading or when updating the API, what do to about pending file?
169
- this.fileUpload.emit({ success: false, file });
193
+ this.FileUpload.emit({ success: false, file });
170
194
  }
171
195
  }
172
196
  static ɵfac = function FileUploadComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FileUploadComponent)(); };
173
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { disabled: "disabled", CategoryID: "CategoryID" }, outputs: { uploadStarted: "uploadStarted", fileUpload: "fileUpload" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], 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) {
197
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { Disabled: "Disabled", disabled: "disabled", CategoryID: "CategoryID" }, outputs: { UploadStarted: "UploadStarted", uploadStarted: "uploadStarted", FileUpload: "FileUpload", fileUpload: "fileUpload" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], 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) {
174
198
  i0.ɵɵelementStart(0, "div")(1, "label", 0);
175
199
  i0.ɵɵelement(2, "i", 1);
176
200
  i0.ɵɵelementStart(3, "span");
@@ -204,12 +228,18 @@ export class FileUploadComponent extends BaseAngularComponent {
204
228
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FileUploadComponent, [{
205
229
  type: Component,
206
230
  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"] }]
207
- }], () => [], { disabled: [{
231
+ }], () => [], { Disabled: [{
232
+ type: Input
233
+ }], disabled: [{
208
234
  type: Input
209
235
  }], CategoryID: [{
210
236
  type: Input
237
+ }], UploadStarted: [{
238
+ type: Output
211
239
  }], uploadStarted: [{
212
240
  type: Output
241
+ }], FileUpload: [{
242
+ type: Output
213
243
  }], fileUpload: [{
214
244
  type: Output
215
245
  }] }); })();
@@ -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 { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity, FileStorageEngineBase } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\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 CreateFile($input: CreateMJFileInput!) {\n CreateFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateFile: 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>['CreateFile']['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 extends BaseAngularComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileSelectInfo> = [];\n private defaultProviderID = '';\n private get md() { return this.ProviderToUse; }\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() { super(); }\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 await FileStorageEngineBase.Instance.Config(false);\n const activeProviders = FileStorageEngineBase.Instance.Providers\n .filter(p => p.IsActive)\n .sort((a, b) => (b.Priority ?? 0) - (a.Priority ?? 0));\n const provider: MJFileStorageProviderEntity | undefined = activeProviders[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.CreateFile;\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
+ {"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 { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity, FileStorageEngineBase } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\nimport { z } from 'zod';\n\n/**\n * Minimal file info interface replacing Kendo's FileInfo.\n */\nexport interface FileSelectInfo {\n name: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n size: number; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n rawFile: File; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n}\n\nexport type FileUploadEvent = { success: true; file: MJFileEntity } | { success: false; file: FileSelectInfo }; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\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 CreateFile($input: CreateMJFileInput!) {\n CreateFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateFile: 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>['CreateFile']['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 extends BaseAngularComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileSelectInfo> = [];\n private defaultProviderID = '';\n private get md() { return this.ProviderToUse; }\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() { super(); }\n\n @Input() Disabled = false;\n\n /** @deprecated Use {@link Disabled}. */\n @Input() set disabled(value: FileUploadComponent['Disabled']) {\n this.Disabled = value;\n }\n /** @deprecated Use {@link Disabled}. */\n get disabled(): FileUploadComponent['Disabled'] {\n return this.Disabled;\n }\n @Input() CategoryID: string | undefined = undefined;\n @Output() UploadStarted = new EventEmitter<void>();\n\n /**\n * @deprecated Use {@link UploadStarted}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (uploadStarted) keeps working. Must stay AFTER UploadStarted: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() uploadStarted = this.UploadStarted;\n @Output() FileUpload = new EventEmitter<FileUploadEvent>();\n\n /**\n * @deprecated Use {@link FileUpload}.\n *\n * The same emitter under the old binding name, so a template still binding\n * (fileUpload) keeps working. Must stay AFTER FileUpload: class fields\n * initialise in order, and the other way round this captures undefined.\n */\n @Output() fileUpload = this.FileUpload;\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async Refresh() {\n await FileStorageEngineBase.Instance.Config(false);\n const activeProviders = FileStorageEngineBase.Instance.Providers\n .filter(p => p.IsActive)\n .sort((a, b) => (b.Priority ?? 0) - (a.Priority ?? 0));\n const provider: MJFileStorageProviderEntity | undefined = activeProviders[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.CreateFile;\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"]}
@@ -7,9 +7,17 @@ import { FileUploadEvent } from '../file-upload/file-upload';
7
7
  import * as i0 from "@angular/core";
8
8
  export declare class FilesGridComponent extends BaseAngularComponent implements OnInit, OnChanges {
9
9
  private notifications;
10
- files: MJFileEntity[];
10
+ Files: MJFileEntity[];
11
+ /** @deprecated Use {@link Files}. */
12
+ get files(): MJFileEntity[];
13
+ /** @deprecated Use {@link Files}. */
14
+ set files(value: MJFileEntity[]);
11
15
  isLoading: boolean;
12
- editFile: MJFileEntity | undefined;
16
+ EditFile: MJFileEntity | undefined;
17
+ /** @deprecated Use {@link EditFile}. */
18
+ get editFile(): MJFileEntity | undefined;
19
+ /** @deprecated Use {@link EditFile}. */
20
+ set editFile(value: MJFileEntity | undefined);
13
21
  GridTheme: Theme;
14
22
  ColumnDefs: ColDef[];
15
23
  DefaultColDef: ColDef;
@@ -26,6 +34,8 @@ export declare class FilesGridComponent extends BaseAngularComponent implements
26
34
  *
27
35
  * @returns void
28
36
  */
37
+ ResetEditFile(): void;
38
+ /** @deprecated Use {@link ResetEditFile}. */
29
39
  resetEditFile(): void;
30
40
  /**
31
41
  * Saves the edited file.
@@ -35,6 +45,8 @@ export declare class FilesGridComponent extends BaseAngularComponent implements
35
45
  * @returns Promise<void> - A promise that resolves when the save operation is complete.
36
46
  * @throws Error - If there is an error during the save operation.
37
47
  */
48
+ SaveEditFile(): Promise<void>;
49
+ /** @deprecated Use {@link SaveEditFile}. */
38
50
  saveEditFile(): Promise<void>;
39
51
  /**
40
52
  * Downloads a file using the provided MJFileEntity.
@@ -43,13 +55,19 @@ export declare class FilesGridComponent extends BaseAngularComponent implements
43
55
  * @returns Promise<void> - A promise that resolves when the file download is complete.
44
56
  * @throws Error - If there is an error during the file download process.
45
57
  */
46
- downloadFile: (file: MJFileEntity) => Promise<void>;
58
+ DownloadFile: (file: MJFileEntity) => Promise<void>;
59
+ /** @deprecated Use {@link DownloadFile}. */
60
+ get downloadFile(): (file: MJFileEntity) => Promise<void>;
61
+ /** @deprecated Use {@link DownloadFile}. */
62
+ set downloadFile(value: (file: MJFileEntity) => Promise<void>);
47
63
  /**
48
64
  * Determines whether a file can be deleted based on its status and creation time.
49
65
  *
50
66
  * @param file - The MJFileEntity representing the file to be checked.
51
67
  * @returns boolean - True if the file can be deleted, false otherwise.
52
68
  */
69
+ CanBeDeleted(file: MJFileEntity): boolean;
70
+ /** @deprecated Use {@link CanBeDeleted}. */
53
71
  canBeDeleted(file: MJFileEntity): boolean;
54
72
  /**
55
73
  * Deletes a file using the provided MJFileEntity.
@@ -58,13 +76,19 @@ export declare class FilesGridComponent extends BaseAngularComponent implements
58
76
  * @returns Promise<void> - A promise that resolves when the file deletion is complete.
59
77
  * @throws Error - If there is an error during the file deletion process.
60
78
  */
61
- deleteFile: (file: MJFileEntity) => Promise<void>;
79
+ DeleteFile: (file: MJFileEntity) => Promise<void>;
80
+ /** @deprecated Use {@link DeleteFile}. */
81
+ get deleteFile(): (file: MJFileEntity) => Promise<void>;
82
+ /** @deprecated Use {@link DeleteFile}. */
83
+ set deleteFile(value: (file: MJFileEntity) => Promise<void>);
62
84
  /**
63
85
  * Handles the file upload event, sending a notification in case of failure and otherwise adding
64
86
  * the newly uploaded files to the files currently displayed.
65
87
  *
66
88
  * @param e - The file upload event.
67
89
  */
90
+ HandleFileUpload(e: FileUploadEvent): void;
91
+ /** @deprecated Use {@link HandleFileUpload}. */
68
92
  handleFileUpload(e: FileUploadEvent): void;
69
93
  /**
70
94
  * Refreshes the data by running a view and loading the files.
@@ -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;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EACL,MAAM,EACN,cAAc,EAKd,KAAK,KAAK,EAEX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;;AAmD7D,qBAMa,kBAAmB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAiB3E,OAAO,CAAC,aAAa;IAhB1B,KAAK,EAAE,YAAY,EAAE,CAAM;IAC3B,SAAS,EAAE,OAAO,CAAS;IAC3B,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAC;IAKnC,SAAS,EAAE,KAAK,CAAmD;IACnE,UAAU,EAAE,MAAM,EAAE,CAAM;IAC1B,aAAa,EAAE,MAAM,CAI1B;IACF,OAAO,CAAC,OAAO,CAAwB;gBAEnB,aAAa,EAAE,qBAAqB;IAK/C,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;yCAxNf,kBAAkB;2CAAlB,kBAAkB;CAiO9B"}
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;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EACL,MAAM,EACN,cAAc,EAKd,KAAK,KAAK,EAEX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;;AAmD7D,qBAMa,kBAAmB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAmC3E,OAAO,CAAC,aAAa;IAlC1B,KAAK,EAAE,YAAY,EAAE,CAAM;IAElC,qCAAqC;IACrC,IAAW,KAAK,IAAI,YAAY,EAAE,CAEjC;IACD,qCAAqC;IACrC,IAAW,KAAK,CAAC,KAAK,EAAE,YAAY,EAAE,EAErC;IACM,SAAS,EAAE,OAAO,CAAS;IAC3B,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAC;IAE1C,wCAAwC;IACxC,IAAW,QAAQ,IAAI,YAAY,GAAG,SAAS,CAE9C;IACD,wCAAwC;IACxC,IAAW,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,EAElD;IAKM,SAAS,EAAE,KAAK,CAAmD;IACnE,UAAU,EAAE,MAAM,EAAE,CAAM;IAC1B,aAAa,EAAE,MAAM,CAI1B;IACF,OAAO,CAAC,OAAO,CAAwB;gBAEnB,aAAa,EAAE,qBAAqB;IAK/C,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,6CAA6C;IACtC,aAAa;IAIpB;;;;;;;OAOG;IACU,YAAY;IAmBzB,4CAA4C;IAC/B,YAAY;IAIzB;;;;;;OAMG;IACI,YAAY,GAAU,MAAM,YAAY,mBAkB7C;IAEF,4CAA4C;IAC5C,IAAW,YAAY,WArBY,YAAY,mBAuB9C;IACD,4CAA4C;IAC5C,IAAW,YAAY,CAAC,KAAK,SAzBM,YAAY,kBAyBlB,EAE5B;IAED;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAMhD,4CAA4C;IACrC,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAIhD;;;;;;OAMG;IACI,UAAU,GAAU,MAAM,YAAY,mBAY3C;IAEF,0CAA0C;IAC1C,IAAW,UAAU,WAfY,YAAY,mBAiB5C;IACD,0CAA0C;IAC1C,IAAW,UAAU,CAAC,KAAK,SAnBM,YAAY,kBAmBlB,EAE1B;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,CAAC,EAAE,eAAe;IAW1C,gDAAgD;IACzC,gBAAgB,CAAC,CAAC,EAAE,eAAe;IAI1C;;;OAGG;IACG,OAAO;IAiBb;;OAEG;IACH,OAAO,CAAC,eAAe;IAmCvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;yCAhRf,kBAAkB;2CAAlB,kBAAkB;CAyR9B"}
@@ -85,9 +85,25 @@ const FileDownloadQuerySchema = z.object({
85
85
  });
86
86
  export class FilesGridComponent extends BaseAngularComponent {
87
87
  notifications;
88
- files = [];
88
+ Files = [];
89
+ /** @deprecated Use {@link Files}. */
90
+ get files() {
91
+ return this.Files;
92
+ }
93
+ /** @deprecated Use {@link Files}. */
94
+ set files(value) {
95
+ this.Files = value;
96
+ }
89
97
  isLoading = false;
90
- editFile;
98
+ EditFile;
99
+ /** @deprecated Use {@link EditFile}. */
100
+ get editFile() {
101
+ return this.EditFile;
102
+ }
103
+ /** @deprecated Use {@link EditFile}. */
104
+ set editFile(value) {
105
+ this.EditFile = value;
106
+ }
91
107
  // AG Grid configuration
92
108
  // Themed from the shared --mj-* token params so this grid follows light/dark and
93
109
  // the org brand overlay, matching the main entity/query grids.
@@ -123,9 +139,13 @@ export class FilesGridComponent extends BaseAngularComponent {
123
139
  *
124
140
  * @returns void
125
141
  */
142
+ ResetEditFile() {
143
+ this.EditFile?.Revert();
144
+ this.EditFile = undefined;
145
+ }
146
+ /** @deprecated Use {@link ResetEditFile}. */
126
147
  resetEditFile() {
127
- this.editFile?.Revert();
128
- this.editFile = undefined;
148
+ return this.ResetEditFile();
129
149
  }
130
150
  /**
131
151
  * Saves the edited file.
@@ -135,25 +155,29 @@ export class FilesGridComponent extends BaseAngularComponent {
135
155
  * @returns Promise<void> - A promise that resolves when the save operation is complete.
136
156
  * @throws Error - If there is an error during the save operation.
137
157
  */
138
- async saveEditFile() {
139
- if (this.editFile) {
158
+ async SaveEditFile() {
159
+ if (this.EditFile) {
140
160
  this.isLoading = true;
141
161
  //
142
- const success = await this.editFile.Save();
162
+ const success = await this.EditFile.Save();
143
163
  if (success) {
144
- this.notifications.CreateSimpleNotification(`Successfully saved file ${this.editFile.ID} ${this.editFile.Name}`, 'success');
145
- this.editFile = undefined;
164
+ this.notifications.CreateSimpleNotification(`Successfully saved file ${this.EditFile.ID} ${this.EditFile.Name}`, 'success');
165
+ this.EditFile = undefined;
146
166
  // Refresh the grid to show the updated data
147
167
  if (this.gridApi) {
148
- this.gridApi.setGridOption('rowData', this.files);
168
+ this.gridApi.setGridOption('rowData', this.Files);
149
169
  }
150
170
  }
151
171
  else {
152
- this.notifications.CreateSimpleNotification(`Unable to save file ${this.editFile.ID} ${this.editFile.Name}`, 'error');
172
+ this.notifications.CreateSimpleNotification(`Unable to save file ${this.EditFile.ID} ${this.EditFile.Name}`, 'error');
153
173
  }
154
174
  this.isLoading = false;
155
175
  }
156
176
  }
177
+ /** @deprecated Use {@link SaveEditFile}. */
178
+ async saveEditFile() {
179
+ return this.SaveEditFile();
180
+ }
157
181
  /**
158
182
  * Downloads a file using the provided MJFileEntity.
159
183
  *
@@ -161,7 +185,7 @@ export class FilesGridComponent extends BaseAngularComponent {
161
185
  * @returns Promise<void> - A promise that resolves when the file download is complete.
162
186
  * @throws Error - If there is an error during the file download process.
163
187
  */
164
- downloadFile = async (file) => {
188
+ DownloadFile = async (file) => {
165
189
  this.isLoading = true;
166
190
  const result = await GraphQLDataProvider.ExecuteGQL(FileDownloadQuery, {
167
191
  FileID: file.ID,
@@ -180,17 +204,29 @@ export class FilesGridComponent extends BaseAngularComponent {
180
204
  }
181
205
  this.isLoading = false;
182
206
  };
207
+ /** @deprecated Use {@link DownloadFile}. */
208
+ get downloadFile() {
209
+ return this.DownloadFile;
210
+ }
211
+ /** @deprecated Use {@link DownloadFile}. */
212
+ set downloadFile(value) {
213
+ this.DownloadFile = value;
214
+ }
183
215
  /**
184
216
  * Determines whether a file can be deleted based on its status and creation time.
185
217
  *
186
218
  * @param file - The MJFileEntity representing the file to be checked.
187
219
  * @returns boolean - True if the file can be deleted, false otherwise.
188
220
  */
189
- canBeDeleted(file) {
221
+ CanBeDeleted(file) {
190
222
  const status = file.Status;
191
223
  const deletable = status === 'Uploaded' || Date.now() - +file.__mj_CreatedAt > 10 * 60 * 60;
192
224
  return deletable;
193
225
  }
226
+ /** @deprecated Use {@link CanBeDeleted}. */
227
+ canBeDeleted(file) {
228
+ return this.CanBeDeleted(file);
229
+ }
194
230
  /**
195
231
  * Deletes a file using the provided MJFileEntity.
196
232
  *
@@ -198,35 +234,47 @@ export class FilesGridComponent extends BaseAngularComponent {
198
234
  * @returns Promise<void> - A promise that resolves when the file deletion is complete.
199
235
  * @throws Error - If there is an error during the file deletion process.
200
236
  */
201
- deleteFile = async (file) => {
237
+ DeleteFile = async (file) => {
202
238
  this.isLoading = true;
203
239
  const ID = file.ID;
204
240
  const Name = file.Name;
205
241
  const deleteResult = await file.Delete();
206
242
  if (deleteResult) {
207
243
  this.notifications.CreateSimpleNotification(`Successfully deleted file ${ID} ${Name}`, 'info');
208
- this.files = this.files.filter((f) => typeof f.ID === 'string' && f.ID !== ID);
244
+ this.Files = this.Files.filter((f) => typeof f.ID === 'string' && f.ID !== ID);
209
245
  }
210
246
  else {
211
247
  this.notifications.CreateSimpleNotification(`Unable to delete file ${ID} ${Name}`, 'error');
212
248
  }
213
249
  this.isLoading = false;
214
250
  };
251
+ /** @deprecated Use {@link DeleteFile}. */
252
+ get deleteFile() {
253
+ return this.DeleteFile;
254
+ }
255
+ /** @deprecated Use {@link DeleteFile}. */
256
+ set deleteFile(value) {
257
+ this.DeleteFile = value;
258
+ }
215
259
  /**
216
260
  * Handles the file upload event, sending a notification in case of failure and otherwise adding
217
261
  * the newly uploaded files to the files currently displayed.
218
262
  *
219
263
  * @param e - The file upload event.
220
264
  */
221
- handleFileUpload(e) {
265
+ HandleFileUpload(e) {
222
266
  if (!e.success) {
223
267
  this.notifications.CreateSimpleNotification(`Unable to upload file '${e.file.name}'`, 'error');
224
268
  return;
225
269
  }
226
- this.files.push(e.file);
227
- this.files = [...this.files]; // trigger AG Grid row data change
270
+ this.Files.push(e.file);
271
+ this.Files = [...this.Files]; // trigger AG Grid row data change
228
272
  this.isLoading = false;
229
273
  }
274
+ /** @deprecated Use {@link HandleFileUpload}. */
275
+ handleFileUpload(e) {
276
+ return this.HandleFileUpload(e);
277
+ }
230
278
  /**
231
279
  * Refreshes the data by running a view and loading the files.
232
280
  * @returns {Promise<void>} - A promise that resolves when the data is refreshed.
@@ -240,7 +288,7 @@ export class FilesGridComponent extends BaseAngularComponent {
240
288
  ...(this.CategoryID !== undefined && { ExtraFilter: `CategoryID='${this.CategoryID}'` }),
241
289
  });
242
290
  if (result.Success) {
243
- this.files = result.Results ?? [];
291
+ this.Files = result.Results ?? [];
244
292
  }
245
293
  else {
246
294
  throw new Error('Error loading files: ' + result.ErrorMessage);
@@ -266,11 +314,11 @@ export class FilesGridComponent extends BaseAngularComponent {
266
314
  const container = document.createElement('div');
267
315
  container.className = 'action-buttons';
268
316
  const downloadBtn = this.createActionButton('fa-download', params.data?.Status !== 'Uploaded');
269
- downloadBtn.addEventListener('click', () => this.downloadFile(params.data));
270
- const deleteBtn = this.createActionButton('fa-trash-can', !this.canBeDeleted(params.data));
271
- deleteBtn.addEventListener('click', () => this.deleteFile(params.data));
317
+ downloadBtn.addEventListener('click', () => this.DownloadFile(params.data));
318
+ const deleteBtn = this.createActionButton('fa-trash-can', !this.CanBeDeleted(params.data));
319
+ deleteBtn.addEventListener('click', () => this.DeleteFile(params.data));
272
320
  const editBtn = this.createActionButton('fa-pen-to-square', params.data?.Status !== 'Uploaded');
273
- editBtn.addEventListener('click', () => { this.editFile = params.data; });
321
+ editBtn.addEventListener('click', () => { this.EditFile = params.data; });
274
322
  container.appendChild(downloadBtn);
275
323
  container.appendChild(deleteBtn);
276
324
  container.appendChild(editBtn);