@memberjunction/ng-artifacts 5.37.0 → 5.39.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.
- package/README.md +31 -0
- package/dist/__tests__/image-artifact-viewer.test.d.ts +2 -0
- package/dist/__tests__/image-artifact-viewer.test.d.ts.map +1 -0
- package/dist/__tests__/image-artifact-viewer.test.js +62 -0
- package/dist/__tests__/image-artifact-viewer.test.js.map +1 -0
- package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts +2 -0
- package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts.map +1 -0
- package/dist/lib/__tests__/interactive-form-apply.service.test.js +206 -0
- package/dist/lib/__tests__/interactive-form-apply.service.test.js.map +1 -0
- package/dist/lib/artifacts.module.d.ts +14 -12
- package/dist/lib/artifacts.module.d.ts.map +1 -1
- package/dist/lib/artifacts.module.js +14 -2
- package/dist/lib/artifacts.module.js.map +1 -1
- package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts +11 -1
- package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/artifact-type-plugin-viewer.component.js +18 -1
- package/dist/lib/components/artifact-type-plugin-viewer.component.js.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.d.ts +10 -1
- package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.js +11 -3
- package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +60 -2
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.js +373 -24
- package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.js +0 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts +129 -0
- package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts.map +1 -0
- package/dist/lib/components/plugins/image-artifact-viewer.component.js +413 -0
- package/dist/lib/components/plugins/image-artifact-viewer.component.js.map +1 -0
- package/dist/lib/components/plugins/save-query-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/save-query-dialog.component.js +0 -2
- package/dist/lib/components/plugins/save-query-dialog.component.js.map +1 -1
- package/dist/lib/services/interactive-form-apply.service.d.ts +46 -0
- package/dist/lib/services/interactive-form-apply.service.d.ts.map +1 -0
- package/dist/lib/services/interactive-form-apply.service.js +219 -0
- package/dist/lib/services/interactive-form-apply.service.js.map +1 -0
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +18 -16
|
@@ -217,8 +217,6 @@ export class SaveQueryPanelComponent extends BaseAngularComponent {
|
|
|
217
217
|
const saved = await category.Save();
|
|
218
218
|
if (saved) {
|
|
219
219
|
MJNotificationService.Instance.CreateSimpleNotification(`Category "${name}" created`, 'success', 2500);
|
|
220
|
-
// Refresh core metadata so Metadata.QueryCategories is up to date
|
|
221
|
-
await md.Refresh();
|
|
222
220
|
// Refresh tree to pick up the new category
|
|
223
221
|
await this.categoryTree.Refresh();
|
|
224
222
|
// Auto-select the newly created category.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"save-query-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/save-query-dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef, HostListener } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { Metadata, CompositeKey, KeyValuePair, BaseEntity } from '@memberjunction/core';\nimport { MJQueryEntity, MJQueryCategoryEntity } from '@memberjunction/core-entities';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { TreeBranchConfig, TreeNode } from '@memberjunction/ng-trees';\nimport { TreeDropdownComponent } from '@memberjunction/ng-trees';\n\n/**\n * Result emitted when a query is successfully saved\n */\nexport interface SaveQueryResult {\n queryId: string;\n queryName: string;\n}\n\n/**\n * Slide-in panel for saving an ad-hoc SQL query as a reusable MJ Query record.\n * Pre-populates name from the artifact title and provides a tree dropdown\n * for selecting a query category, with inline category creation.\n *\n * Follows the CreateAgentSlideInComponent pattern for slide-in UX.\n */\n@Component({\n standalone: false,\n selector: 'mj-save-query-panel',\n template: `\n <!-- Backdrop -->\n <div class=\"sqp-backdrop\" [class.sqp-visible]=\"IsVisible\" (click)=\"OnCancel()\"></div>\n\n <!-- Slide panel -->\n <div class=\"sqp-panel\" [class.sqp-visible]=\"IsVisible\">\n <!-- Header -->\n <div class=\"sqp-header\">\n <div class=\"sqp-title-group\">\n <i class=\"fa-solid fa-save sqp-title-icon\"></i>\n <h2 class=\"sqp-title\">Save Query</h2>\n </div>\n <button class=\"sqp-close-btn\" (click)=\"OnCancel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"sqp-body\">\n <!-- Name -->\n <div class=\"sqp-field\">\n <label class=\"sqp-label\">\n Name <span class=\"sqp-required\">*</span>\n </label>\n <input\n type=\"text\"\n class=\"sqp-input\"\n [(ngModel)]=\"Name\"\n placeholder=\"Query name\"\n (keydown.enter)=\"OnSave()\">\n </div>\n\n <!-- Category -->\n <div class=\"sqp-field\">\n <div class=\"sqp-label-row\">\n <label class=\"sqp-label\">Category</label>\n @if (!IsCreatingCategory) {\n <button class=\"sqp-add-btn\" (click)=\"StartCreateCategory()\" title=\"Create new category\">\n <i class=\"fa-solid fa-plus\"></i> New\n </button>\n }\n </div>\n\n <mj-tree-dropdown\n #categoryTree\n [BranchConfig]=\"CategoryBranchConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'branch'\"\n [Placeholder]=\"'Select a category (optional)'\"\n [Value]=\"SelectedCategoryKey\"\n (SelectionChange)=\"OnCategoryChanged($event)\">\n </mj-tree-dropdown>\n\n <!-- Inline create category form -->\n @if (IsCreatingCategory) {\n <div class=\"sqp-create-category\">\n <div class=\"sqp-create-header\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n <span>New Category</span>\n </div>\n <div class=\"sqp-create-fields\">\n <input\n type=\"text\"\n class=\"sqp-input\"\n [(ngModel)]=\"NewCategoryName\"\n placeholder=\"Category name\"\n (keydown.enter)=\"CreateCategory()\"\n (keydown.escape)=\"CancelCreateCategory()\">\n <div class=\"sqp-create-parent\">\n <label class=\"sqp-sublabel\">Parent (optional)</label>\n <mj-tree-dropdown\n [BranchConfig]=\"CategoryBranchConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'branch'\"\n [Placeholder]=\"'None (top level)'\"\n (SelectionChange)=\"OnNewCategoryParentChanged($event)\">\n </mj-tree-dropdown>\n </div>\n </div>\n <div class=\"sqp-create-actions\">\n <button class=\"sqp-btn sqp-btn-create\"\n (click)=\"CreateCategory()\"\n [disabled]=\"!NewCategoryName.trim() || IsCreatingCategorySaving\">\n @if (IsCreatingCategorySaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n {{ IsCreatingCategorySaving ? 'Creating...' : 'Create' }}\n </button>\n <button class=\"sqp-btn sqp-btn-cancel-create\"\n (click)=\"CancelCreateCategory()\"\n [disabled]=\"IsCreatingCategorySaving\">\n Cancel\n </button>\n </div>\n @if (CreateCategoryError) {\n <div class=\"sqp-inline-error\">{{ CreateCategoryError }}</div>\n }\n </div>\n }\n </div>\n\n <!-- Description -->\n <div class=\"sqp-field\">\n <label class=\"sqp-label\">Description</label>\n <textarea\n class=\"sqp-textarea\"\n [(ngModel)]=\"Description\"\n placeholder=\"Optional description\"\n rows=\"3\">\n </textarea>\n </div>\n\n @if (ErrorMessage) {\n <div class=\"sqp-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ ErrorMessage }}\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"sqp-footer\">\n <button class=\"sqp-btn sqp-btn-save\"\n (click)=\"OnSave()\"\n [disabled]=\"!CanSave || IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i> Save Query\n }\n </button>\n <button class=\"sqp-btn sqp-btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n </div>\n `,\n styles: [`\n /* Backdrop */\n .sqp-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n z-index: 1000;\n transition: background 0.3s ease;\n pointer-events: none;\n }\n .sqp-backdrop.sqp-visible {\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.3));\n pointer-events: auto;\n }\n\n /* Panel — uses right offset instead of transform to avoid creating\n a new containing block that breaks position:fixed children\n (e.g., the tree-dropdown popup). */\n .sqp-panel {\n position: fixed;\n top: 0;\n right: -440px;\n height: 100vh;\n width: 440px;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px rgba(0, 0, 0, 0.12);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transition: right 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n }\n .sqp-panel.sqp-visible {\n right: 0;\n }\n\n /* Header */\n .sqp-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n .sqp-title-group {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n .sqp-title-icon {\n font-size: 20px;\n color: var(--mj-brand-primary);\n }\n .sqp-title {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n .sqp-close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: none;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 16px;\n flex-shrink: 0;\n }\n .sqp-close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n /* Body */\n .sqp-body {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n /* Fields */\n .sqp-field {\n margin-bottom: 20px;\n }\n .sqp-label-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n }\n .sqp-label {\n display: block;\n margin-bottom: 6px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n .sqp-label-row .sqp-label {\n margin-bottom: 0;\n }\n .sqp-sublabel {\n display: block;\n margin-bottom: 4px;\n font-weight: 500;\n font-size: 12px;\n color: var(--mj-text-secondary);\n }\n .sqp-required {\n color: var(--mj-status-error);\n }\n .sqp-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n .sqp-input:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .sqp-input::placeholder {\n color: var(--mj-text-disabled);\n }\n .sqp-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n resize: vertical;\n font-family: inherit;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n .sqp-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .sqp-textarea::placeholder {\n color: var(--mj-text-disabled);\n }\n\n /* Add category button */\n .sqp-add-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n background: none;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 12px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .sqp-add-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n }\n\n /* Inline create category */\n .sqp-create-category {\n margin-top: 12px;\n padding: 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n }\n .sqp-create-header {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 10px;\n }\n .sqp-create-header i {\n color: var(--mj-brand-primary);\n }\n .sqp-create-fields {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n .sqp-create-parent {\n margin-top: 2px;\n }\n .sqp-create-actions {\n display: flex;\n gap: 8px;\n margin-top: 12px;\n }\n .sqp-inline-error {\n margin-top: 8px;\n font-size: 12px;\n color: var(--mj-status-error-text);\n }\n\n /* Buttons */\n .sqp-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .sqp-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n .sqp-btn-save {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 10px 20px;\n font-size: 14px;\n }\n .sqp-btn-save:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n .sqp-btn-cancel {\n background: none;\n border: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n padding: 10px 20px;\n font-size: 14px;\n }\n .sqp-btn-cancel:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n .sqp-btn-create {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n }\n .sqp-btn-create:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-success) 85%, black);\n }\n .sqp-btn-cancel-create {\n background: none;\n color: var(--mj-text-secondary);\n }\n .sqp-btn-cancel-create:hover:not(:disabled) {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n }\n\n /* Footer */\n .sqp-footer {\n display: flex;\n gap: 10px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n\n /* Error */\n .sqp-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 6px;\n color: var(--mj-status-error-text);\n font-size: 13px;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .sqp-panel {\n width: 100% !important;\n right: -100%;\n }\n .sqp-panel.sqp-visible {\n right: 0;\n }\n .sqp-header {\n padding: 16px 20px 12px;\n }\n .sqp-body {\n padding: 16px;\n }\n .sqp-footer {\n padding: 12px 16px;\n }\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SaveQueryPanelComponent extends BaseAngularComponent {\n @Input() QueryName = '';\n @Input() QueryDescription = '';\n @Input() SQL = '';\n @Input() Plan = '';\n\n @Output() Saved = new EventEmitter<SaveQueryResult>();\n @Output() Cancelled = new EventEmitter<void>();\n\n @ViewChild('categoryTree') categoryTree!: TreeDropdownComponent;\n\n // Form state\n public Name = '';\n public Description = '';\n public IsSaving = false;\n public ErrorMessage = '';\n public IsVisible = false;\n\n // Category selection\n private selectedCategoryId: string | null = null;\n public SelectedCategoryKey: CompositeKey | null = null;\n\n // Inline category creation\n public IsCreatingCategory = false;\n public IsCreatingCategorySaving = false;\n public NewCategoryName = '';\n public CreateCategoryError = '';\n private newCategoryParentId: string | null = null;\n\n /** Tree config for query category hierarchy */\n public CategoryBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: Query Categories',\n DisplayField: 'Name',\n IDField: 'ID',\n ParentIDField: 'ParentID',\n DefaultIcon: 'fa-solid fa-folder',\n OrderBy: 'Name ASC'\n };\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n public get CanSave(): boolean {\n return !!this.Name?.trim();\n }\n\n ngOnInit(): void {\n // Sync input values\n this.Name = this.QueryName;\n this.Description = this.QueryDescription;\n\n // Trigger slide-in on next microtask (ensures DOM is ready)\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (this.IsCreatingCategory) {\n this.CancelCreateCategory();\n } else if (!this.IsSaving) {\n this.OnCancel();\n }\n }\n\n // =========================================================================\n // Category Selection\n // =========================================================================\n\n public OnCategoryChanged(selection: TreeNode | TreeNode[] | null): void {\n if (!selection) {\n this.selectedCategoryId = null;\n } else if (Array.isArray(selection)) {\n this.selectedCategoryId = selection.length > 0 ? selection[0].ID : null;\n } else {\n this.selectedCategoryId = selection.ID;\n }\n }\n\n // =========================================================================\n // Inline Category Creation\n // =========================================================================\n\n public StartCreateCategory(): void {\n this.IsCreatingCategory = true;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n }\n\n public CancelCreateCategory(): void {\n this.IsCreatingCategory = false;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n }\n\n public OnNewCategoryParentChanged(selection: TreeNode | TreeNode[] | null): void {\n if (!selection) {\n this.newCategoryParentId = null;\n } else if (Array.isArray(selection)) {\n this.newCategoryParentId = selection.length > 0 ? selection[0].ID : null;\n } else {\n this.newCategoryParentId = selection.ID;\n }\n }\n\n public async CreateCategory(): Promise<void> {\n const name = this.NewCategoryName.trim();\n if (!name || this.IsCreatingCategorySaving) return;\n\n this.IsCreatingCategorySaving = true;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n\n try {\n const md = this.ProviderToUse;\n const category = await md.GetEntityObject<MJQueryCategoryEntity>('MJ: Query Categories');\n\n category.Name = name;\n category.UserID = md.CurrentUser.ID;\n if (this.newCategoryParentId) {\n category.ParentID = this.newCategoryParentId;\n }\n\n const saved = await category.Save();\n if (saved) {\n MJNotificationService.Instance.CreateSimpleNotification(`Category \"${name}\" created`, 'success', 2500);\n\n // Refresh core metadata so Metadata.QueryCategories is up to date\n await md.Refresh();\n\n // Refresh tree to pick up the new category\n await this.categoryTree.Refresh();\n\n // Auto-select the newly created category.\n // Must use detectChanges() (not markForCheck) to immediately propagate\n // the new Value input to the tree dropdown, since this panel uses OnPush.\n const newKey = new CompositeKey([new KeyValuePair('ID', category.ID)]);\n this.SelectedCategoryKey = newKey;\n this.selectedCategoryId = category.ID;\n this.cdr.detectChanges();\n\n // Collapse the create form\n this.IsCreatingCategory = false;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n } else {\n const errorMsg = this.getEntityErrorMessage(category, 'create category');\n this.CreateCategoryError = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Failed to create category:', category.LatestResult);\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : 'Failed to create category';\n this.CreateCategoryError = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Error creating category:', error);\n } finally {\n this.IsCreatingCategorySaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // =========================================================================\n // Save / Cancel\n // =========================================================================\n\n public async OnSave(): Promise<void> {\n if (!this.CanSave || this.IsSaving) return;\n\n this.IsSaving = true;\n this.ErrorMessage = '';\n this.cdr.markForCheck();\n\n try {\n const md = this.ProviderToUse;\n const query = await md.GetEntityObject<MJQueryEntity>('MJ: Queries');\n\n query.Name = this.Name.trim();\n query.SQL = this.SQL;\n query.Status = 'Approved';\n\n if (this.Description?.trim()) {\n query.Description = this.Description.trim();\n }\n if (this.Plan?.trim()) {\n query.TechnicalDescription = this.Plan.trim();\n }\n if (this.selectedCategoryId) {\n query.CategoryID = this.selectedCategoryId;\n }\n\n const saved = await query.Save();\n if (saved) {\n MJNotificationService.Instance.CreateSimpleNotification(`Query \"${query.Name}\" saved`, 'success', 2500);\n\n // Animate out, then emit\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => {\n this.Saved.emit({\n queryId: query.ID,\n queryName: query.Name\n });\n }, 300);\n } else {\n const errorMsg = this.getEntityErrorMessage(query, 'save query');\n this.ErrorMessage = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Failed to save query:', query.LatestResult);\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.ErrorMessage = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Error saving query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n public OnCancel(): void {\n if (this.IsSaving) return;\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => this.Cancelled.emit(), 300);\n }\n\n // =========================================================================\n // Helpers\n // =========================================================================\n\n private getEntityErrorMessage(entity: BaseEntity, operation: string): string {\n const result = entity.LatestResult;\n if (result?.Message) {\n return result.Message;\n }\n return `Failed to ${operation}. Please try again.`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"save-query-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/save-query-dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef, HostListener } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { Metadata, CompositeKey, KeyValuePair, BaseEntity } from '@memberjunction/core';\nimport { MJQueryEntity, MJQueryCategoryEntity } from '@memberjunction/core-entities';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { TreeBranchConfig, TreeNode } from '@memberjunction/ng-trees';\nimport { TreeDropdownComponent } from '@memberjunction/ng-trees';\n\n/**\n * Result emitted when a query is successfully saved\n */\nexport interface SaveQueryResult {\n queryId: string;\n queryName: string;\n}\n\n/**\n * Slide-in panel for saving an ad-hoc SQL query as a reusable MJ Query record.\n * Pre-populates name from the artifact title and provides a tree dropdown\n * for selecting a query category, with inline category creation.\n *\n * Follows the CreateAgentSlideInComponent pattern for slide-in UX.\n */\n@Component({\n standalone: false,\n selector: 'mj-save-query-panel',\n template: `\n <!-- Backdrop -->\n <div class=\"sqp-backdrop\" [class.sqp-visible]=\"IsVisible\" (click)=\"OnCancel()\"></div>\n\n <!-- Slide panel -->\n <div class=\"sqp-panel\" [class.sqp-visible]=\"IsVisible\">\n <!-- Header -->\n <div class=\"sqp-header\">\n <div class=\"sqp-title-group\">\n <i class=\"fa-solid fa-save sqp-title-icon\"></i>\n <h2 class=\"sqp-title\">Save Query</h2>\n </div>\n <button class=\"sqp-close-btn\" (click)=\"OnCancel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"sqp-body\">\n <!-- Name -->\n <div class=\"sqp-field\">\n <label class=\"sqp-label\">\n Name <span class=\"sqp-required\">*</span>\n </label>\n <input\n type=\"text\"\n class=\"sqp-input\"\n [(ngModel)]=\"Name\"\n placeholder=\"Query name\"\n (keydown.enter)=\"OnSave()\">\n </div>\n\n <!-- Category -->\n <div class=\"sqp-field\">\n <div class=\"sqp-label-row\">\n <label class=\"sqp-label\">Category</label>\n @if (!IsCreatingCategory) {\n <button class=\"sqp-add-btn\" (click)=\"StartCreateCategory()\" title=\"Create new category\">\n <i class=\"fa-solid fa-plus\"></i> New\n </button>\n }\n </div>\n\n <mj-tree-dropdown\n #categoryTree\n [BranchConfig]=\"CategoryBranchConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'branch'\"\n [Placeholder]=\"'Select a category (optional)'\"\n [Value]=\"SelectedCategoryKey\"\n (SelectionChange)=\"OnCategoryChanged($event)\">\n </mj-tree-dropdown>\n\n <!-- Inline create category form -->\n @if (IsCreatingCategory) {\n <div class=\"sqp-create-category\">\n <div class=\"sqp-create-header\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n <span>New Category</span>\n </div>\n <div class=\"sqp-create-fields\">\n <input\n type=\"text\"\n class=\"sqp-input\"\n [(ngModel)]=\"NewCategoryName\"\n placeholder=\"Category name\"\n (keydown.enter)=\"CreateCategory()\"\n (keydown.escape)=\"CancelCreateCategory()\">\n <div class=\"sqp-create-parent\">\n <label class=\"sqp-sublabel\">Parent (optional)</label>\n <mj-tree-dropdown\n [BranchConfig]=\"CategoryBranchConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'branch'\"\n [Placeholder]=\"'None (top level)'\"\n (SelectionChange)=\"OnNewCategoryParentChanged($event)\">\n </mj-tree-dropdown>\n </div>\n </div>\n <div class=\"sqp-create-actions\">\n <button class=\"sqp-btn sqp-btn-create\"\n (click)=\"CreateCategory()\"\n [disabled]=\"!NewCategoryName.trim() || IsCreatingCategorySaving\">\n @if (IsCreatingCategorySaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n {{ IsCreatingCategorySaving ? 'Creating...' : 'Create' }}\n </button>\n <button class=\"sqp-btn sqp-btn-cancel-create\"\n (click)=\"CancelCreateCategory()\"\n [disabled]=\"IsCreatingCategorySaving\">\n Cancel\n </button>\n </div>\n @if (CreateCategoryError) {\n <div class=\"sqp-inline-error\">{{ CreateCategoryError }}</div>\n }\n </div>\n }\n </div>\n\n <!-- Description -->\n <div class=\"sqp-field\">\n <label class=\"sqp-label\">Description</label>\n <textarea\n class=\"sqp-textarea\"\n [(ngModel)]=\"Description\"\n placeholder=\"Optional description\"\n rows=\"3\">\n </textarea>\n </div>\n\n @if (ErrorMessage) {\n <div class=\"sqp-error\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n {{ ErrorMessage }}\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"sqp-footer\">\n <button class=\"sqp-btn sqp-btn-save\"\n (click)=\"OnSave()\"\n [disabled]=\"!CanSave || IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i> Save Query\n }\n </button>\n <button class=\"sqp-btn sqp-btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n </div>\n `,\n styles: [`\n /* Backdrop */\n .sqp-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n z-index: 1000;\n transition: background 0.3s ease;\n pointer-events: none;\n }\n .sqp-backdrop.sqp-visible {\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.3));\n pointer-events: auto;\n }\n\n /* Panel — uses right offset instead of transform to avoid creating\n a new containing block that breaks position:fixed children\n (e.g., the tree-dropdown popup). */\n .sqp-panel {\n position: fixed;\n top: 0;\n right: -440px;\n height: 100vh;\n width: 440px;\n background: var(--mj-bg-surface);\n box-shadow: -8px 0 32px rgba(0, 0, 0, 0.12);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transition: right 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n }\n .sqp-panel.sqp-visible {\n right: 0;\n }\n\n /* Header */\n .sqp-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n .sqp-title-group {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n .sqp-title-icon {\n font-size: 20px;\n color: var(--mj-brand-primary);\n }\n .sqp-title {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n .sqp-close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: none;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 16px;\n flex-shrink: 0;\n }\n .sqp-close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n /* Body */\n .sqp-body {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n /* Fields */\n .sqp-field {\n margin-bottom: 20px;\n }\n .sqp-label-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 6px;\n }\n .sqp-label {\n display: block;\n margin-bottom: 6px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n .sqp-label-row .sqp-label {\n margin-bottom: 0;\n }\n .sqp-sublabel {\n display: block;\n margin-bottom: 4px;\n font-weight: 500;\n font-size: 12px;\n color: var(--mj-text-secondary);\n }\n .sqp-required {\n color: var(--mj-status-error);\n }\n .sqp-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n .sqp-input:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .sqp-input::placeholder {\n color: var(--mj-text-disabled);\n }\n .sqp-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n resize: vertical;\n font-family: inherit;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n .sqp-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .sqp-textarea::placeholder {\n color: var(--mj-text-disabled);\n }\n\n /* Add category button */\n .sqp-add-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n background: none;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 12px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .sqp-add-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n }\n\n /* Inline create category */\n .sqp-create-category {\n margin-top: 12px;\n padding: 14px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n }\n .sqp-create-header {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 10px;\n }\n .sqp-create-header i {\n color: var(--mj-brand-primary);\n }\n .sqp-create-fields {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n .sqp-create-parent {\n margin-top: 2px;\n }\n .sqp-create-actions {\n display: flex;\n gap: 8px;\n margin-top: 12px;\n }\n .sqp-inline-error {\n margin-top: 8px;\n font-size: 12px;\n color: var(--mj-status-error-text);\n }\n\n /* Buttons */\n .sqp-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .sqp-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n .sqp-btn-save {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 10px 20px;\n font-size: 14px;\n }\n .sqp-btn-save:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n }\n .sqp-btn-cancel {\n background: none;\n border: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n padding: 10px 20px;\n font-size: 14px;\n }\n .sqp-btn-cancel:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n .sqp-btn-create {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n }\n .sqp-btn-create:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-success) 85%, black);\n }\n .sqp-btn-cancel-create {\n background: none;\n color: var(--mj-text-secondary);\n }\n .sqp-btn-cancel-create:hover:not(:disabled) {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n }\n\n /* Footer */\n .sqp-footer {\n display: flex;\n gap: 10px;\n padding: 16px 24px;\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n }\n\n /* Error */\n .sqp-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: 6px;\n color: var(--mj-status-error-text);\n font-size: 13px;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .sqp-panel {\n width: 100% !important;\n right: -100%;\n }\n .sqp-panel.sqp-visible {\n right: 0;\n }\n .sqp-header {\n padding: 16px 20px 12px;\n }\n .sqp-body {\n padding: 16px;\n }\n .sqp-footer {\n padding: 12px 16px;\n }\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SaveQueryPanelComponent extends BaseAngularComponent {\n @Input() QueryName = '';\n @Input() QueryDescription = '';\n @Input() SQL = '';\n @Input() Plan = '';\n\n @Output() Saved = new EventEmitter<SaveQueryResult>();\n @Output() Cancelled = new EventEmitter<void>();\n\n @ViewChild('categoryTree') categoryTree!: TreeDropdownComponent;\n\n // Form state\n public Name = '';\n public Description = '';\n public IsSaving = false;\n public ErrorMessage = '';\n public IsVisible = false;\n\n // Category selection\n private selectedCategoryId: string | null = null;\n public SelectedCategoryKey: CompositeKey | null = null;\n\n // Inline category creation\n public IsCreatingCategory = false;\n public IsCreatingCategorySaving = false;\n public NewCategoryName = '';\n public CreateCategoryError = '';\n private newCategoryParentId: string | null = null;\n\n /** Tree config for query category hierarchy */\n public CategoryBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: Query Categories',\n DisplayField: 'Name',\n IDField: 'ID',\n ParentIDField: 'ParentID',\n DefaultIcon: 'fa-solid fa-folder',\n OrderBy: 'Name ASC'\n };\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n public get CanSave(): boolean {\n return !!this.Name?.trim();\n }\n\n ngOnInit(): void {\n // Sync input values\n this.Name = this.QueryName;\n this.Description = this.QueryDescription;\n\n // Trigger slide-in on next microtask (ensures DOM is ready)\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (this.IsCreatingCategory) {\n this.CancelCreateCategory();\n } else if (!this.IsSaving) {\n this.OnCancel();\n }\n }\n\n // =========================================================================\n // Category Selection\n // =========================================================================\n\n public OnCategoryChanged(selection: TreeNode | TreeNode[] | null): void {\n if (!selection) {\n this.selectedCategoryId = null;\n } else if (Array.isArray(selection)) {\n this.selectedCategoryId = selection.length > 0 ? selection[0].ID : null;\n } else {\n this.selectedCategoryId = selection.ID;\n }\n }\n\n // =========================================================================\n // Inline Category Creation\n // =========================================================================\n\n public StartCreateCategory(): void {\n this.IsCreatingCategory = true;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n }\n\n public CancelCreateCategory(): void {\n this.IsCreatingCategory = false;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n }\n\n public OnNewCategoryParentChanged(selection: TreeNode | TreeNode[] | null): void {\n if (!selection) {\n this.newCategoryParentId = null;\n } else if (Array.isArray(selection)) {\n this.newCategoryParentId = selection.length > 0 ? selection[0].ID : null;\n } else {\n this.newCategoryParentId = selection.ID;\n }\n }\n\n public async CreateCategory(): Promise<void> {\n const name = this.NewCategoryName.trim();\n if (!name || this.IsCreatingCategorySaving) return;\n\n this.IsCreatingCategorySaving = true;\n this.CreateCategoryError = '';\n this.cdr.markForCheck();\n\n try {\n const md = this.ProviderToUse;\n const category = await md.GetEntityObject<MJQueryCategoryEntity>('MJ: Query Categories');\n\n category.Name = name;\n category.UserID = md.CurrentUser.ID;\n if (this.newCategoryParentId) {\n category.ParentID = this.newCategoryParentId;\n }\n\n const saved = await category.Save();\n if (saved) {\n MJNotificationService.Instance.CreateSimpleNotification(`Category \"${name}\" created`, 'success', 2500);\n\n // Refresh tree to pick up the new category\n await this.categoryTree.Refresh();\n\n // Auto-select the newly created category.\n // Must use detectChanges() (not markForCheck) to immediately propagate\n // the new Value input to the tree dropdown, since this panel uses OnPush.\n const newKey = new CompositeKey([new KeyValuePair('ID', category.ID)]);\n this.SelectedCategoryKey = newKey;\n this.selectedCategoryId = category.ID;\n this.cdr.detectChanges();\n\n // Collapse the create form\n this.IsCreatingCategory = false;\n this.NewCategoryName = '';\n this.newCategoryParentId = null;\n } else {\n const errorMsg = this.getEntityErrorMessage(category, 'create category');\n this.CreateCategoryError = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Failed to create category:', category.LatestResult);\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : 'Failed to create category';\n this.CreateCategoryError = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Error creating category:', error);\n } finally {\n this.IsCreatingCategorySaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // =========================================================================\n // Save / Cancel\n // =========================================================================\n\n public async OnSave(): Promise<void> {\n if (!this.CanSave || this.IsSaving) return;\n\n this.IsSaving = true;\n this.ErrorMessage = '';\n this.cdr.markForCheck();\n\n try {\n const md = this.ProviderToUse;\n const query = await md.GetEntityObject<MJQueryEntity>('MJ: Queries');\n\n query.Name = this.Name.trim();\n query.SQL = this.SQL;\n query.Status = 'Approved';\n\n if (this.Description?.trim()) {\n query.Description = this.Description.trim();\n }\n if (this.Plan?.trim()) {\n query.TechnicalDescription = this.Plan.trim();\n }\n if (this.selectedCategoryId) {\n query.CategoryID = this.selectedCategoryId;\n }\n\n const saved = await query.Save();\n if (saved) {\n MJNotificationService.Instance.CreateSimpleNotification(`Query \"${query.Name}\" saved`, 'success', 2500);\n\n // Animate out, then emit\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => {\n this.Saved.emit({\n queryId: query.ID,\n queryName: query.Name\n });\n }, 300);\n } else {\n const errorMsg = this.getEntityErrorMessage(query, 'save query');\n this.ErrorMessage = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Failed to save query:', query.LatestResult);\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.ErrorMessage = errorMsg;\n MJNotificationService.Instance.CreateSimpleNotification(errorMsg, 'error', 5000);\n console.error('Error saving query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n public OnCancel(): void {\n if (this.IsSaving) return;\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => this.Cancelled.emit(), 300);\n }\n\n // =========================================================================\n // Helpers\n // =========================================================================\n\n private getEntityErrorMessage(entity: BaseEntity, operation: string): string {\n const result = entity.LatestResult;\n if (result?.Message) {\n return result.Message;\n }\n return `Failed to ${operation}. Please try again.`;\n }\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type IMetadataProvider } from '@memberjunction/core';
|
|
2
|
+
import type { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/** Result of an apply attempt — surfaced to the caller for any post-apply UI. */
|
|
5
|
+
export interface InteractiveFormApplyResult {
|
|
6
|
+
Success: boolean;
|
|
7
|
+
/** Mode the server ran: 'create' / 'modify-new-version' / 'modify-in-place'. */
|
|
8
|
+
Mode?: 'create' | 'modify-new-version' | 'modify-in-place';
|
|
9
|
+
/** OverrideID the user can now reference. */
|
|
10
|
+
OverrideID?: string;
|
|
11
|
+
/** ComponentID that now holds the spec. */
|
|
12
|
+
ComponentID?: string;
|
|
13
|
+
/** Version string (e.g. '1.0.0' for create, '1.1.0' for modify-new). */
|
|
14
|
+
Version?: string;
|
|
15
|
+
Message?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class InteractiveFormApplyService {
|
|
18
|
+
private readonly dialog;
|
|
19
|
+
private readonly notifications;
|
|
20
|
+
/**
|
|
21
|
+
* Confirm with the user and apply the spec. Routes to Create / Modify
|
|
22
|
+
* automatically based on whether an Active override already exists.
|
|
23
|
+
*/
|
|
24
|
+
ConfirmAndApply(spec: ComponentSpec, entityName: string, provider?: IMetadataProvider): Promise<InteractiveFormApplyResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Look up an action by name and run it. The actions module ships with
|
|
27
|
+
* `__CreateInteractiveForm` / `__ModifyInteractiveForm` / etc. as their
|
|
28
|
+
* DriverClass names but registers under the human-readable form name.
|
|
29
|
+
* GraphQLActionClient.RunAction() takes the action ID; we fetch it by
|
|
30
|
+
* name from the action metadata loaded on the provider.
|
|
31
|
+
*/
|
|
32
|
+
private runActionByName;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve an action ID by Name. Falls back to a direct RunView against
|
|
35
|
+
* the Action entity when ActionEngine isn't loaded.
|
|
36
|
+
*/
|
|
37
|
+
private resolveActionIdByName;
|
|
38
|
+
/** Show a confirmation dialog explaining what's about to happen. */
|
|
39
|
+
private confirm;
|
|
40
|
+
private parseActiveResult;
|
|
41
|
+
private summarize;
|
|
42
|
+
private fail;
|
|
43
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<InteractiveFormApplyService, never>;
|
|
44
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<InteractiveFormApplyService>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=interactive-form-apply.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-form-apply.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/interactive-form-apply.service.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAsB,KAAK,iBAAiB,EAAiB,MAAM,sBAAsB,CAAC;AAIjG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;;AAEjF,iFAAiF;AACjF,MAAM,WAAW,0BAA0B;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,IAAI,CAAC,EAAE,QAAQ,GAAG,oBAAoB,GAAG,iBAAiB,CAAC;IAC3D,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBACa,2BAA2B;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAE/D;;;OAGG;IACU,eAAe,CACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,0BAA0B,CAAC;IAwDtC;;;;;;OAMG;YACW,eAAe;IA+B7B;;;OAGG;YACW,qBAAqB;IAmBnC,oEAAoE;YACtD,OAAO;IA6BrB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,SAAS;IAiCjB,OAAO,CAAC,IAAI;yCA3MH,2BAA2B;6CAA3B,2BAA2B;CA+MvC"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply-to-my-form service.
|
|
3
|
+
*
|
|
4
|
+
* When the form-aware artifact viewer's "Apply to my form" button fires
|
|
5
|
+
* `applyFormRequested`, the host calls this service. It:
|
|
6
|
+
* 1. Looks up the entity to confirm it's registered.
|
|
7
|
+
* 2. Reads the current Active override for the (entity, user) pair via
|
|
8
|
+
* the `Get Active Form For Entity` action.
|
|
9
|
+
* 3. Shows a confirmation dialog explaining what's about to happen
|
|
10
|
+
* (Create new vs. Modify existing → Pending).
|
|
11
|
+
* 4. On confirmation, runs `Create Interactive Form` or
|
|
12
|
+
* `Modify Interactive Form` accordingly.
|
|
13
|
+
* 5. Surfaces success / failure via the notification service.
|
|
14
|
+
*
|
|
15
|
+
* The service centralizes the Create-vs-Modify decision so every host
|
|
16
|
+
* (standalone artifact viewer in Explorer, chat conversation surfaces,
|
|
17
|
+
* eventually the cockpit's chat-pane Apply flow) follows the same rules.
|
|
18
|
+
*/
|
|
19
|
+
import { Injectable, inject } from '@angular/core';
|
|
20
|
+
import { Metadata, LogError } from '@memberjunction/core';
|
|
21
|
+
import { GraphQLActionClient } from '@memberjunction/graphql-dataprovider';
|
|
22
|
+
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
23
|
+
import { MJDialogService } from '@memberjunction/ng-ui-components';
|
|
24
|
+
import * as i0 from "@angular/core";
|
|
25
|
+
export class InteractiveFormApplyService {
|
|
26
|
+
dialog = inject(MJDialogService);
|
|
27
|
+
notifications = inject(MJNotificationService);
|
|
28
|
+
/**
|
|
29
|
+
* Confirm with the user and apply the spec. Routes to Create / Modify
|
|
30
|
+
* automatically based on whether an Active override already exists.
|
|
31
|
+
*/
|
|
32
|
+
async ConfirmAndApply(spec, entityName, provider) {
|
|
33
|
+
const p = provider ?? Metadata.Provider;
|
|
34
|
+
if (!p) {
|
|
35
|
+
return this.fail('No metadata provider configured.');
|
|
36
|
+
}
|
|
37
|
+
const entity = p.EntityByName(entityName);
|
|
38
|
+
if (!entity) {
|
|
39
|
+
return this.fail(`Entity '${entityName}' is not registered.`);
|
|
40
|
+
}
|
|
41
|
+
const user = p.CurrentUser;
|
|
42
|
+
if (!user) {
|
|
43
|
+
return this.fail('No current user.');
|
|
44
|
+
}
|
|
45
|
+
const gqlProvider = p;
|
|
46
|
+
if (!gqlProvider || typeof gqlProvider.ExecuteGQL !== 'function') {
|
|
47
|
+
return this.fail('Action invocation requires a GraphQL provider.');
|
|
48
|
+
}
|
|
49
|
+
const client = new GraphQLActionClient(gqlProvider);
|
|
50
|
+
// Step 1: detect existing state via Get Active Form For Entity.
|
|
51
|
+
const activeResult = await this.runActionByName(client, 'Get Active Form For Entity', [
|
|
52
|
+
{ Name: 'EntityName', Value: entityName, Type: 'Input' },
|
|
53
|
+
]);
|
|
54
|
+
if (!activeResult.Success) {
|
|
55
|
+
return this.fail(`Could not check for existing override: ${activeResult.Message ?? 'unknown error'}`);
|
|
56
|
+
}
|
|
57
|
+
const payload = this.parseActiveResult(activeResult.Message);
|
|
58
|
+
const hasExistingActive = !!payload?.Active?.OverrideID;
|
|
59
|
+
// Step 2: confirm with the user.
|
|
60
|
+
const proceed = await this.confirm(hasExistingActive, entityName, payload?.Active?.ComponentVersion);
|
|
61
|
+
if (!proceed) {
|
|
62
|
+
return { Success: false, Message: 'Cancelled by user.' };
|
|
63
|
+
}
|
|
64
|
+
// Step 3: run Create or Modify.
|
|
65
|
+
const formName = spec.name ?? 'Custom Form';
|
|
66
|
+
if (hasExistingActive) {
|
|
67
|
+
const modifyResult = await this.runActionByName(client, 'Modify Interactive Form', [
|
|
68
|
+
{ Name: 'OverrideID', Value: payload.Active.OverrideID, Type: 'Input' },
|
|
69
|
+
{ Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },
|
|
70
|
+
{ Name: 'Notes', Value: `Applied from chat artifact at ${new Date().toISOString()}`, Type: 'Input' },
|
|
71
|
+
]);
|
|
72
|
+
return this.summarize(modifyResult, 'modify', user);
|
|
73
|
+
}
|
|
74
|
+
const createResult = await this.runActionByName(client, 'Create Interactive Form', [
|
|
75
|
+
{ Name: 'EntityName', Value: entityName, Type: 'Input' },
|
|
76
|
+
{ Name: 'Name', Value: formName, Type: 'Input' },
|
|
77
|
+
{ Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },
|
|
78
|
+
]);
|
|
79
|
+
return this.summarize(createResult, 'create', user);
|
|
80
|
+
}
|
|
81
|
+
// ── internals ────────────────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Look up an action by name and run it. The actions module ships with
|
|
84
|
+
* `__CreateInteractiveForm` / `__ModifyInteractiveForm` / etc. as their
|
|
85
|
+
* DriverClass names but registers under the human-readable form name.
|
|
86
|
+
* GraphQLActionClient.RunAction() takes the action ID; we fetch it by
|
|
87
|
+
* name from the action metadata loaded on the provider.
|
|
88
|
+
*/
|
|
89
|
+
async runActionByName(client, actionName, params) {
|
|
90
|
+
try {
|
|
91
|
+
// The action ID is required by RunAction. We look it up from the
|
|
92
|
+
// action engine's cached metadata if available; otherwise we ask
|
|
93
|
+
// the GraphQL provider directly.
|
|
94
|
+
const actionId = await this.resolveActionIdByName(actionName);
|
|
95
|
+
if (!actionId) {
|
|
96
|
+
return { Success: false, Message: `Action '${actionName}' not found.` };
|
|
97
|
+
}
|
|
98
|
+
const result = await client.RunAction(actionId, params);
|
|
99
|
+
// ActionResult.Result is the MJActionResultCodeEntity carrying
|
|
100
|
+
// the string ResultCode; surface it on the failure path for
|
|
101
|
+
// diagnostic messaging. ActionResult itself doesn't expose
|
|
102
|
+
// ResultCode directly.
|
|
103
|
+
const resultCode = result?.Result?.ResultCode;
|
|
104
|
+
return {
|
|
105
|
+
Success: !!result.Success,
|
|
106
|
+
Message: result.Message ?? undefined,
|
|
107
|
+
ResultCode: resultCode ?? undefined,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
112
|
+
LogError(`InteractiveFormApplyService.runActionByName(${actionName}): ${message}`);
|
|
113
|
+
return { Success: false, Message: message };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Resolve an action ID by Name. Falls back to a direct RunView against
|
|
118
|
+
* the Action entity when ActionEngine isn't loaded.
|
|
119
|
+
*/
|
|
120
|
+
async resolveActionIdByName(name) {
|
|
121
|
+
try {
|
|
122
|
+
// ActionEngine may not be initialised in the chat surface — query directly.
|
|
123
|
+
const { RunView } = await import('@memberjunction/core');
|
|
124
|
+
const rv = new RunView();
|
|
125
|
+
const result = await rv.RunView({
|
|
126
|
+
EntityName: 'Actions',
|
|
127
|
+
ExtraFilter: `Name='${name.replace(/'/g, "''")}'`,
|
|
128
|
+
Fields: ['ID'],
|
|
129
|
+
MaxRows: 1,
|
|
130
|
+
ResultType: 'simple',
|
|
131
|
+
});
|
|
132
|
+
return result.Success ? (result.Results?.[0]?.ID ?? null) : null;
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
LogError(`InteractiveFormApplyService.resolveActionIdByName(${name}): ${err instanceof Error ? err.message : String(err)}`);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Show a confirmation dialog explaining what's about to happen. */
|
|
140
|
+
async confirm(hasExistingActive, entityName, currentVersion) {
|
|
141
|
+
const content = hasExistingActive
|
|
142
|
+
? `You already have an active custom form for <strong>${escape(entityName)}</strong> (v${escape(currentVersion ?? '?')}). Applying this artifact will create a <strong>new Pending version</strong> — your live form stays active until you explicitly activate the new version in Form Builder.`
|
|
143
|
+
: `This will create a custom form for <strong>${escape(entityName)}</strong> scoped to your user. Other users will continue to see the default form.`;
|
|
144
|
+
// MJDialogAction surface is {text, primary?, themeColor?}; the
|
|
145
|
+
// dialog's Result observable emits the entire clicked action (or
|
|
146
|
+
// undefined for backdrop/X dismissal). Detect intent via the
|
|
147
|
+
// `primary` flag — Apply / Create Pending are the primary actions;
|
|
148
|
+
// Cancel and dismissal both resolve false.
|
|
149
|
+
const ref = this.dialog.Open({
|
|
150
|
+
title: hasExistingActive ? 'Apply as new Pending version?' : 'Apply this form?',
|
|
151
|
+
content,
|
|
152
|
+
width: 540,
|
|
153
|
+
actions: [
|
|
154
|
+
{ text: hasExistingActive ? 'Create Pending' : 'Apply', primary: true, themeColor: 'primary' },
|
|
155
|
+
{ text: 'Cancel' },
|
|
156
|
+
],
|
|
157
|
+
});
|
|
158
|
+
return new Promise(resolve => {
|
|
159
|
+
ref.Result.subscribe((res) => {
|
|
160
|
+
resolve(res?.primary === true);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
parseActiveResult(message) {
|
|
165
|
+
if (!message)
|
|
166
|
+
return null;
|
|
167
|
+
try {
|
|
168
|
+
return JSON.parse(message);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
summarize(result, kind, _user) {
|
|
175
|
+
if (!result.Success) {
|
|
176
|
+
this.notifications.CreateSimpleNotification(`Apply failed: ${result.Message ?? result.ResultCode ?? 'unknown error'}`, 'error', 5000);
|
|
177
|
+
return { Success: false, Message: result.Message };
|
|
178
|
+
}
|
|
179
|
+
let payload = {};
|
|
180
|
+
try {
|
|
181
|
+
payload = JSON.parse(result.Message ?? '{}');
|
|
182
|
+
}
|
|
183
|
+
catch { /* best effort */ }
|
|
184
|
+
const mode = kind === 'create'
|
|
185
|
+
? 'create'
|
|
186
|
+
: (payload.Mode === 'in-place' ? 'modify-in-place' : 'modify-new-version');
|
|
187
|
+
const note = kind === 'create'
|
|
188
|
+
? 'Custom form is now active for your user.'
|
|
189
|
+
: (mode === 'modify-in-place'
|
|
190
|
+
? 'Pending version updated. Activate it from Form Builder when ready.'
|
|
191
|
+
: `Pending v${payload.Version ?? '?'} created. Activate it from Form Builder when ready.`);
|
|
192
|
+
this.notifications.CreateSimpleNotification(note, 'success', 4000);
|
|
193
|
+
return {
|
|
194
|
+
Success: true,
|
|
195
|
+
Mode: mode,
|
|
196
|
+
OverrideID: payload.OverrideID,
|
|
197
|
+
ComponentID: payload.ComponentID,
|
|
198
|
+
Version: payload.Version,
|
|
199
|
+
Message: result.Message,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
fail(message) {
|
|
203
|
+
this.notifications.CreateSimpleNotification(`Apply failed: ${message}`, 'error', 5000);
|
|
204
|
+
return { Success: false, Message: message };
|
|
205
|
+
}
|
|
206
|
+
static ɵfac = function InteractiveFormApplyService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || InteractiveFormApplyService)(); };
|
|
207
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: InteractiveFormApplyService, factory: InteractiveFormApplyService.ɵfac, providedIn: 'root' });
|
|
208
|
+
}
|
|
209
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InteractiveFormApplyService, [{
|
|
210
|
+
type: Injectable,
|
|
211
|
+
args: [{ providedIn: 'root' }]
|
|
212
|
+
}], null, null); })();
|
|
213
|
+
/** Minimal HTML escape — the dialog content goes through `[innerHTML]` upstream. */
|
|
214
|
+
function escape(s) {
|
|
215
|
+
return s.replace(/[&<>"']/g, c => ({
|
|
216
|
+
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
217
|
+
}[c] ?? c));
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=interactive-form-apply.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-form-apply.service.js","sourceRoot":"","sources":["../../../src/lib/services/interactive-form-apply.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Apply-to-my-form service.\n *\n * When the form-aware artifact viewer's \"Apply to my form\" button fires\n * `applyFormRequested`, the host calls this service. It:\n * 1. Looks up the entity to confirm it's registered.\n * 2. Reads the current Active override for the (entity, user) pair via\n * the `Get Active Form For Entity` action.\n * 3. Shows a confirmation dialog explaining what's about to happen\n * (Create new vs. Modify existing → Pending).\n * 4. On confirmation, runs `Create Interactive Form` or\n * `Modify Interactive Form` accordingly.\n * 5. Surfaces success / failure via the notification service.\n *\n * The service centralizes the Create-vs-Modify decision so every host\n * (standalone artifact viewer in Explorer, chat conversation surfaces,\n * eventually the cockpit's chat-pane Apply flow) follows the same rules.\n */\nimport { Injectable, inject } from '@angular/core';\nimport { Metadata, LogError, type IMetadataProvider, type UserInfo } from '@memberjunction/core';\nimport { GraphQLActionClient, GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { MJDialogService } from '@memberjunction/ng-ui-components';\nimport type { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n/** Result of an apply attempt — surfaced to the caller for any post-apply UI. */\nexport interface InteractiveFormApplyResult {\n Success: boolean;\n /** Mode the server ran: 'create' / 'modify-new-version' / 'modify-in-place'. */\n Mode?: 'create' | 'modify-new-version' | 'modify-in-place';\n /** OverrideID the user can now reference. */\n OverrideID?: string;\n /** ComponentID that now holds the spec. */\n ComponentID?: string;\n /** Version string (e.g. '1.0.0' for create, '1.1.0' for modify-new). */\n Version?: string;\n Message?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class InteractiveFormApplyService {\n private readonly dialog = inject(MJDialogService);\n private readonly notifications = inject(MJNotificationService);\n\n /**\n * Confirm with the user and apply the spec. Routes to Create / Modify\n * automatically based on whether an Active override already exists.\n */\n public async ConfirmAndApply(\n spec: ComponentSpec,\n entityName: string,\n provider?: IMetadataProvider,\n ): Promise<InteractiveFormApplyResult> {\n const p = provider ?? Metadata.Provider;\n if (!p) {\n return this.fail('No metadata provider configured.');\n }\n const entity = p.EntityByName(entityName);\n if (!entity) {\n return this.fail(`Entity '${entityName}' is not registered.`);\n }\n const user = p.CurrentUser;\n if (!user) {\n return this.fail('No current user.');\n }\n const gqlProvider = p as unknown as GraphQLDataProvider;\n if (!gqlProvider || typeof (gqlProvider as { ExecuteGQL?: unknown }).ExecuteGQL !== 'function') {\n return this.fail('Action invocation requires a GraphQL provider.');\n }\n\n const client = new GraphQLActionClient(gqlProvider);\n\n // Step 1: detect existing state via Get Active Form For Entity.\n const activeResult = await this.runActionByName(client, 'Get Active Form For Entity', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n ]);\n if (!activeResult.Success) {\n return this.fail(`Could not check for existing override: ${activeResult.Message ?? 'unknown error'}`);\n }\n const payload = this.parseActiveResult(activeResult.Message);\n const hasExistingActive = !!payload?.Active?.OverrideID;\n\n // Step 2: confirm with the user.\n const proceed = await this.confirm(hasExistingActive, entityName, payload?.Active?.ComponentVersion);\n if (!proceed) {\n return { Success: false, Message: 'Cancelled by user.' };\n }\n\n // Step 3: run Create or Modify.\n const formName = (spec as unknown as { name?: string }).name ?? 'Custom Form';\n if (hasExistingActive) {\n const modifyResult = await this.runActionByName(client, 'Modify Interactive Form', [\n { Name: 'OverrideID', Value: payload!.Active!.OverrideID!, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n { Name: 'Notes', Value: `Applied from chat artifact at ${new Date().toISOString()}`, Type: 'Input' },\n ]);\n return this.summarize(modifyResult, 'modify', user);\n }\n const createResult = await this.runActionByName(client, 'Create Interactive Form', [\n { Name: 'EntityName', Value: entityName, Type: 'Input' },\n { Name: 'Name', Value: formName, Type: 'Input' },\n { Name: 'Spec', Value: JSON.stringify(spec), Type: 'Input' },\n ]);\n return this.summarize(createResult, 'create', user);\n }\n\n // ── internals ────────────────────────────────────────────────────────\n\n /**\n * Look up an action by name and run it. The actions module ships with\n * `__CreateInteractiveForm` / `__ModifyInteractiveForm` / etc. as their\n * DriverClass names but registers under the human-readable form name.\n * GraphQLActionClient.RunAction() takes the action ID; we fetch it by\n * name from the action metadata loaded on the provider.\n */\n private async runActionByName(\n client: GraphQLActionClient,\n actionName: string,\n params: Array<{ Name: string; Value: string; Type: 'Input' }>,\n ): Promise<{ Success: boolean; Message?: string; ResultCode?: string }> {\n try {\n // The action ID is required by RunAction. We look it up from the\n // action engine's cached metadata if available; otherwise we ask\n // the GraphQL provider directly.\n const actionId = await this.resolveActionIdByName(actionName);\n if (!actionId) {\n return { Success: false, Message: `Action '${actionName}' not found.` };\n }\n const result = await client.RunAction(actionId, params);\n // ActionResult.Result is the MJActionResultCodeEntity carrying\n // the string ResultCode; surface it on the failure path for\n // diagnostic messaging. ActionResult itself doesn't expose\n // ResultCode directly.\n const resultCode = (result as { Result?: { ResultCode?: string } })?.Result?.ResultCode;\n return {\n Success: !!result.Success,\n Message: result.Message ?? undefined,\n ResultCode: resultCode ?? undefined,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n LogError(`InteractiveFormApplyService.runActionByName(${actionName}): ${message}`);\n return { Success: false, Message: message };\n }\n }\n\n /**\n * Resolve an action ID by Name. Falls back to a direct RunView against\n * the Action entity when ActionEngine isn't loaded.\n */\n private async resolveActionIdByName(name: string): Promise<string | null> {\n try {\n // ActionEngine may not be initialised in the chat surface — query directly.\n const { RunView } = await import('@memberjunction/core');\n const rv = new RunView();\n const result = await rv.RunView<{ ID: string }>({\n EntityName: 'Actions',\n ExtraFilter: `Name='${name.replace(/'/g, \"''\")}'`,\n Fields: ['ID'],\n MaxRows: 1,\n ResultType: 'simple',\n });\n return result.Success ? (result.Results?.[0]?.ID ?? null) : null;\n } catch (err) {\n LogError(`InteractiveFormApplyService.resolveActionIdByName(${name}): ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n /** Show a confirmation dialog explaining what's about to happen. */\n private async confirm(\n hasExistingActive: boolean,\n entityName: string,\n currentVersion: string | null | undefined,\n ): Promise<boolean> {\n const content = hasExistingActive\n ? `You already have an active custom form for <strong>${escape(entityName)}</strong> (v${escape(currentVersion ?? '?')}). Applying this artifact will create a <strong>new Pending version</strong> — your live form stays active until you explicitly activate the new version in Form Builder.`\n : `This will create a custom form for <strong>${escape(entityName)}</strong> scoped to your user. Other users will continue to see the default form.`;\n // MJDialogAction surface is {text, primary?, themeColor?}; the\n // dialog's Result observable emits the entire clicked action (or\n // undefined for backdrop/X dismissal). Detect intent via the\n // `primary` flag — Apply / Create Pending are the primary actions;\n // Cancel and dismissal both resolve false.\n const ref = this.dialog.Open({\n title: hasExistingActive ? 'Apply as new Pending version?' : 'Apply this form?',\n content,\n width: 540,\n actions: [\n { text: hasExistingActive ? 'Create Pending' : 'Apply', primary: true, themeColor: 'primary' },\n { text: 'Cancel' },\n ],\n });\n return new Promise<boolean>(resolve => {\n ref.Result.subscribe((res: unknown) => {\n resolve((res as { primary?: boolean })?.primary === true);\n });\n });\n }\n\n private parseActiveResult(message: string | undefined): {\n Active?: { OverrideID?: string; ComponentVersion?: string };\n } | null {\n if (!message) return null;\n try {\n return JSON.parse(message) as { Active?: { OverrideID?: string; ComponentVersion?: string } };\n } catch {\n return null;\n }\n }\n\n private summarize(\n result: { Success: boolean; Message?: string; ResultCode?: string },\n kind: 'create' | 'modify',\n _user: UserInfo,\n ): InteractiveFormApplyResult {\n if (!result.Success) {\n this.notifications.CreateSimpleNotification(\n `Apply failed: ${result.Message ?? result.ResultCode ?? 'unknown error'}`,\n 'error', 5000,\n );\n return { Success: false, Message: result.Message };\n }\n let payload: Record<string, unknown> = {};\n try { payload = JSON.parse(result.Message ?? '{}'); } catch { /* best effort */ }\n const mode: InteractiveFormApplyResult['Mode'] = kind === 'create'\n ? 'create'\n : (payload.Mode === 'in-place' ? 'modify-in-place' : 'modify-new-version');\n const note = kind === 'create'\n ? 'Custom form is now active for your user.'\n : (mode === 'modify-in-place'\n ? 'Pending version updated. Activate it from Form Builder when ready.'\n : `Pending v${payload.Version ?? '?'} created. Activate it from Form Builder when ready.`);\n this.notifications.CreateSimpleNotification(note, 'success', 4000);\n return {\n Success: true,\n Mode: mode,\n OverrideID: payload.OverrideID as string | undefined,\n ComponentID: payload.ComponentID as string | undefined,\n Version: payload.Version as string | undefined,\n Message: result.Message,\n };\n }\n\n private fail(message: string): InteractiveFormApplyResult {\n this.notifications.CreateSimpleNotification(`Apply failed: ${message}`, 'error', 5000);\n return { Success: false, Message: message };\n }\n}\n\n/** Minimal HTML escape — the dialog content goes through `[innerHTML]` upstream. */\nfunction escape(s: string): string {\n return s.replace(/[&<>\"']/g, c => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c] ?? c));\n}\n"]}
|
package/dist/public-api.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './lib/artifacts.module';
|
|
|
2
2
|
export * from './lib/services/artifact-icon.service';
|
|
3
3
|
export * from './lib/services/artifact-file.service';
|
|
4
4
|
export * from './lib/services/analyze-artifact.service';
|
|
5
|
+
export * from './lib/services/interactive-form-apply.service';
|
|
5
6
|
export * from './lib/interfaces/artifact-viewer-plugin.interface';
|
|
6
7
|
export * from './lib/components/base-artifact-viewer.component';
|
|
7
8
|
export * from './lib/snapshot-helpers';
|
|
@@ -21,4 +22,5 @@ export * from './lib/components/file-artifact-toolbar.component';
|
|
|
21
22
|
export * from './lib/components/plugins/pdf-artifact-viewer.component';
|
|
22
23
|
export * from './lib/components/plugins/xlsx-artifact-viewer.component';
|
|
23
24
|
export * from './lib/components/plugins/docx-artifact-viewer.component';
|
|
25
|
+
export * from './lib/components/plugins/image-artifact-viewer.component';
|
|
24
26
|
//# sourceMappingURL=public-api.d.ts.map
|
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAG9D,cAAc,mDAAmD,CAAC;AAGlE,cAAc,iDAAiD,CAAC;AAGhE,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wDAAwD,CAAC;AAGvE,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAGjE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,sFAAsF,CAAC;AAGrG,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC"}
|
package/dist/public-api.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './lib/artifacts.module';
|
|
|
7
7
|
export * from './lib/services/artifact-icon.service';
|
|
8
8
|
export * from './lib/services/artifact-file.service';
|
|
9
9
|
export * from './lib/services/analyze-artifact.service';
|
|
10
|
+
export * from './lib/services/interactive-form-apply.service';
|
|
10
11
|
// Interfaces
|
|
11
12
|
export * from './lib/interfaces/artifact-viewer-plugin.interface';
|
|
12
13
|
// Base component
|
|
@@ -33,4 +34,5 @@ export * from './lib/components/file-artifact-toolbar.component';
|
|
|
33
34
|
export * from './lib/components/plugins/pdf-artifact-viewer.component';
|
|
34
35
|
export * from './lib/components/plugins/xlsx-artifact-viewer.component';
|
|
35
36
|
export * from './lib/components/plugins/docx-artifact-viewer.component';
|
|
37
|
+
export * from './lib/components/plugins/image-artifact-viewer.component';
|
|
36
38
|
//# sourceMappingURL=public-api.js.map
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,wBAAwB,CAAC;AAEvC,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,wBAAwB,CAAC;AAEvC,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAE9D,aAAa;AACb,cAAc,mDAAmD,CAAC;AAElE,iBAAiB;AACjB,cAAc,iDAAiD,CAAC;AAEhE,qFAAqF;AACrF,cAAc,wBAAwB,CAAC;AAEvC,8EAA8E;AAC9E,cAAc,wDAAwD,CAAC;AAEvE,gCAAgC;AAChC,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAEjE,oBAAoB;AACpB,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,sFAAsF,CAAC;AAErG,kCAAkC;AAClC,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC","sourcesContent":["/*\n * Public API Surface of @memberjunction/ng-artifacts\n */\n\n// Module\nexport * from './lib/artifacts.module';\n\n// Services\nexport * from './lib/services/artifact-icon.service';\nexport * from './lib/services/artifact-file.service';\nexport * from './lib/services/analyze-artifact.service';\nexport * from './lib/services/interactive-form-apply.service';\n\n// Interfaces\nexport * from './lib/interfaces/artifact-viewer-plugin.interface';\n\n// Base component\nexport * from './lib/components/base-artifact-viewer.component';\n\n// Snapshot helpers (pure functions for creating DataSnapshots from artifact content)\nexport * from './lib/snapshot-helpers';\n\n// Artifact type plugin viewer (loads appropriate plugin based on DriverClass)\nexport * from './lib/components/artifact-type-plugin-viewer.component';\n\n// Artifact viewer UI components\nexport * from './lib/components/artifact-viewer-panel.component';\nexport * from './lib/components/artifact-version-history.component';\nexport * from './lib/components/artifact-message-card.component';\n\n// Plugin components\nexport * from './lib/components/plugins/json-artifact-viewer.component';\nexport * from './lib/components/plugins/code-artifact-viewer.component';\nexport * from './lib/components/plugins/markdown-artifact-viewer.component';\nexport * from './lib/components/plugins/html-artifact-viewer.component';\nexport * from './lib/components/plugins/svg-artifact-viewer.component';\nexport * from './lib/components/plugins/component-artifact-viewer.component';\nexport * from './lib/components/plugins/data-artifact-viewer.component';\nexport * from './lib/components/plugins/component-feedback-panel/component-feedback-panel.component';\n\n// File viewer toolbar and plugins\nexport * from './lib/components/file-artifact-toolbar.component';\nexport * from './lib/components/plugins/pdf-artifact-viewer.component';\nexport * from './lib/components/plugins/xlsx-artifact-viewer.component';\nexport * from './lib/components/plugins/docx-artifact-viewer.component';\nexport * from './lib/components/plugins/image-artifact-viewer.component';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-artifacts",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.39.0",
|
|
4
4
|
"description": "MemberJunction: Artifact viewer plugin system for rendering different artifact types (JSON, Code, Markdown, HTML, SVG, Components)",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -32,21 +32,23 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@angular/cdk": "21.1.3",
|
|
34
34
|
"@angular/forms": "21.1.3",
|
|
35
|
-
"@memberjunction/core": "5.
|
|
36
|
-
"@memberjunction/core-entities": "5.
|
|
37
|
-
"@memberjunction/global": "5.
|
|
38
|
-
"@memberjunction/
|
|
39
|
-
"@memberjunction/
|
|
40
|
-
"@memberjunction/ng-
|
|
41
|
-
"@memberjunction/ng-
|
|
42
|
-
"@memberjunction/ng-
|
|
43
|
-
"@memberjunction/ng-
|
|
44
|
-
"@memberjunction/ng-
|
|
45
|
-
"@memberjunction/ng-
|
|
46
|
-
"@memberjunction/ng-
|
|
47
|
-
"@memberjunction/ng-
|
|
48
|
-
"@memberjunction/ng-
|
|
49
|
-
"@memberjunction/
|
|
35
|
+
"@memberjunction/core": "5.39.0",
|
|
36
|
+
"@memberjunction/core-entities": "5.39.0",
|
|
37
|
+
"@memberjunction/global": "5.39.0",
|
|
38
|
+
"@memberjunction/graphql-dataprovider": "5.39.0",
|
|
39
|
+
"@memberjunction/interactive-component-types": "5.39.0",
|
|
40
|
+
"@memberjunction/ng-base-forms": "5.39.0",
|
|
41
|
+
"@memberjunction/ng-base-types": "5.39.0",
|
|
42
|
+
"@memberjunction/ng-code-editor": "5.39.0",
|
|
43
|
+
"@memberjunction/ng-export-service": "5.39.0",
|
|
44
|
+
"@memberjunction/ng-markdown": "5.39.0",
|
|
45
|
+
"@memberjunction/ng-notifications": "5.39.0",
|
|
46
|
+
"@memberjunction/ng-pagination": "5.39.0",
|
|
47
|
+
"@memberjunction/ng-query-viewer": "5.39.0",
|
|
48
|
+
"@memberjunction/ng-react": "5.39.0",
|
|
49
|
+
"@memberjunction/ng-shared-generic": "5.39.0",
|
|
50
|
+
"@memberjunction/ng-trees": "5.39.0",
|
|
51
|
+
"@memberjunction/ng-ui-components": "5.39.0",
|
|
50
52
|
"mammoth": "^1.8.0",
|
|
51
53
|
"pdfjs-dist": "^4.10.38",
|
|
52
54
|
"rxjs": "^7.8.2",
|