@memberjunction/ng-explorer-settings 6.1.3 → 6.2.0-edge.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +1 -0
  2. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
  3. package/dist/lib/application-management/application-dialog/application-dialog.component.js +12 -6
  4. package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
  5. package/dist/lib/application-management/application-management.component.d.ts +2 -1
  6. package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
  7. package/dist/lib/application-management/application-management.component.js +2 -2
  8. package/dist/lib/application-management/application-management.component.js.map +1 -1
  9. package/dist/lib/user-management/transaction-group-refusals.d.ts +43 -0
  10. package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -0
  11. package/dist/lib/user-management/transaction-group-refusals.js +45 -0
  12. package/dist/lib/user-management/transaction-group-refusals.js.map +1 -0
  13. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
  14. package/dist/lib/user-management/user-dialog/user-dialog.component.js +17 -2
  15. package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
  16. package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
  17. package/dist/lib/user-management/user-management.component.js +24 -9
  18. package/dist/lib/user-management/user-management.component.js.map +1 -1
  19. package/package.json +20 -20
@@ -61,6 +61,7 @@ export declare class ApplicationDialogComponent extends BaseAngularComponent imp
61
61
  onDefaultForNewUserChange(config: ApplicationEntityConfig): void;
62
62
  get hasEntityChanges(): boolean;
63
63
  get filteredAvailableEntities(): MJEntityEntity[];
64
+ getEntityDisplayName(entity: MJEntityEntity): string;
64
65
  onEntitySearchChange(event: Event): void;
65
66
  clearEntitySearch(): void;
66
67
  toggleSection(section: 'basicInfo' | 'entities' | 'systemInfo'): void;
@@ -1 +1 @@
1
- {"version":3,"file":"application-dialog.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/application-management/application-dialog/application-dialog.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"application-dialog.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/application-management/application-dialog/application-dialog.component.ts"],"names":[],"mappings":"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"}
@@ -94,9 +94,10 @@ function ApplicationDialogComponent_Conditional_0_Conditional_36_For_5_Template(
94
94
  i0.ɵɵelementEnd()()();
95
95
  } if (rf & 2) {
96
96
  const config_r5 = ctx.$implicit;
97
+ const ctx_r1 = i0.ɵɵnextContext(3);
97
98
  i0.ɵɵclassProp("is-new", config_r5.isNew)("has-changes", config_r5.hasChanges);
98
99
  i0.ɵɵadvance(7);
99
- i0.ɵɵtextInterpolate1(" ", config_r5.entity.Name, " ");
100
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getEntityDisplayName(config_r5.entity), " ");
100
101
  i0.ɵɵadvance();
101
102
  i0.ɵɵconditional(config_r5.entity.Description ? 8 : -1);
102
103
  i0.ɵɵadvance(4);
@@ -107,7 +108,7 @@ function ApplicationDialogComponent_Conditional_0_Conditional_36_For_5_Template(
107
108
  i0.ɵɵadvance();
108
109
  i0.ɵɵtextInterpolate(config_r5.sequence);
109
110
  i0.ɵɵadvance(2);
110
- i0.ɵɵattribute("aria-label", "Remove " + config_r5.entity.Name);
111
+ i0.ɵɵattribute("aria-label", "Remove " + ctx_r1.getEntityDisplayName(config_r5.entity));
111
112
  } }
112
113
  function ApplicationDialogComponent_Conditional_0_Conditional_36_Template(rf, ctx) { if (rf & 1) {
113
114
  const _r3 = i0.ɵɵgetCurrentView();
@@ -153,9 +154,10 @@ function ApplicationDialogComponent_Conditional_0_Conditional_38_Conditional_8_F
153
154
  i0.ɵɵelementEnd()()();
154
155
  } if (rf & 2) {
155
156
  const entity_r9 = ctx.$implicit;
156
- i0.ɵɵattribute("aria-label", "Add " + entity_r9.Name);
157
+ const ctx_r1 = i0.ɵɵnextContext(4);
158
+ i0.ɵɵattribute("aria-label", "Add " + ctx_r1.getEntityDisplayName(entity_r9));
157
159
  i0.ɵɵadvance(4);
158
- i0.ɵɵtextInterpolate(entity_r9.Name);
160
+ i0.ɵɵtextInterpolate(ctx_r1.getEntityDisplayName(entity_r9));
159
161
  } }
160
162
  function ApplicationDialogComponent_Conditional_0_Conditional_38_Conditional_8_Template(rf, ctx) { if (rf & 1) {
161
163
  i0.ɵɵelementStart(0, "div", 66);
@@ -585,9 +587,13 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
585
587
  return this.availableEntities;
586
588
  }
587
589
  const searchLower = this.entitySearchTerm.toLowerCase().trim();
588
- return this.availableEntities.filter(entity => (entity.Name || '').toLowerCase().includes(searchLower) ||
590
+ return this.availableEntities.filter(entity => (entity.DisplayName || '').toLowerCase().includes(searchLower) ||
591
+ (entity.Name || '').toLowerCase().includes(searchLower) ||
589
592
  (entity.Description || '').toLowerCase().includes(searchLower));
590
593
  }
594
+ getEntityDisplayName(entity) {
595
+ return entity.DisplayName || entity.Name;
596
+ }
591
597
  onEntitySearchChange(event) {
592
598
  const value = event.target.value;
593
599
  this.entitySearchTerm = value;
@@ -702,7 +708,7 @@ export class ApplicationDialogComponent extends BaseAngularComponent {
702
708
  }
703
709
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ApplicationDialogComponent, [{
704
710
  type: Component,
705
- args: [{ standalone: false, selector: 'mj-application-dialog', template: "@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\" role=\"presentation\">\n <div\n class=\"modal-dialog\"\n [class.fullscreen]=\"isFullscreen\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"application-dialog-title\"\n aria-describedby=\"application-dialog-description\"\n >\n <!-- Modal Header -->\n <div class=\"modal-header\" [class.create-mode]=\"!isEditMode\" [class.edit-mode]=\"isEditMode\">\n <div class=\"modal-header-content\">\n <h2 class=\"modal-title\" id=\"application-dialog-title\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!isEditMode\" [class.fa-layer-group]=\"isEditMode\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Edit Application' : 'Create New Application' }}\n </h2>\n <p class=\"modal-subtitle\" id=\"application-dialog-description\">\n {{ isEditMode ? 'Update application information and settings' : 'Add a new application to the system' }}\n </p>\n </div>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleFullscreen()\"\n [attr.aria-label]=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isFullscreen\" [class.fa-expand]=\"!isFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"modal-close\"\n (click)=\"onCancel()\"\n aria-label=\"Close dialog\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"applicationForm\" (ngSubmit)=\"onSubmit()\">\n <!-- Error Alert -->\n @if (error) {\n <div class=\"form-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n\n <!-- Basic Information Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.basicInfo\" (ExpandedChange)=\"toggleSection('basicInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n Application Information\n </span>\n <span class=\"section-description\">Define the application's basic properties</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"app-name\">Application Name</label>\n <input\n id=\"app-name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"My Application\"\n [class.error]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n [attr.aria-invalid]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n aria-describedby=\"app-name-error\"\n />\n @if (applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched) {\n <div class=\"field-error\" id=\"app-name-error\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-circle\" aria-hidden=\"true\"></i>\n @if (applicationForm.get('name')?.errors?.['required']) {\n Application name is required\n }\n @if (applicationForm.get('name')?.errors?.['maxlength']) {\n Application name cannot exceed 100 characters\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"app-description\">Description</label>\n <textarea\n id=\"app-description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the application's purpose and functionality...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this application does and its main features.\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- Entity Management Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.entities\" (ExpandedChange)=\"toggleSection('entities')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Application Entities\n </span>\n <span class=\"section-description\">Manage which entities are included in this application</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <!-- Assigned Entities -->\n @if (applicationEntities.length > 0) {\n <div class=\"assigned-entities\">\n <h4 class=\"subsection-title\">Assigned Entities ({{ applicationEntities.length }})</h4>\n <div class=\"entities-list\"\n role=\"list\"\n cdkDropList\n (cdkDropListDropped)=\"onEntityDrop($event)\">\n @for (config of applicationEntities; track config.entity.ID; let i = $index) {\n <div\n class=\"entity-item\"\n [class.is-new]=\"config.isNew\"\n [class.has-changes]=\"config.hasChanges\"\n role=\"listitem\"\n cdkDrag\n >\n <i class=\"fa-solid fa-grip-vertical drag-handle\" aria-hidden=\"true\"></i>\n <div class=\"entity-info\">\n <div class=\"entity-icon\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"entity-details\">\n <div class=\"entity-name\">\n {{ config.entity.Name }}\n @if (config.entity.Description) {\n <i\n class=\"fa-solid fa-info-circle entity-info-icon\"\n [title]=\"config.entity.Description\"\n [attr.aria-label]=\"'Entity description: ' + config.entity.Description\"\n ></i>\n }\n </div>\n </div>\n </div>\n\n <div class=\"entity-config\">\n <div class=\"config-item\">\n <label class=\"config-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"config.defaultForNewUser\"\n [ngModelOptions]=\"{standalone: true}\"\n (change)=\"onDefaultForNewUserChange(config)\"\n class=\"config-checkbox\"\n />\n <span class=\"checkbox-text\">Default for new users</span>\n </label>\n </div>\n <div class=\"sequence-badge\" [attr.aria-label]=\"'Sequence ' + config.sequence\">{{ config.sequence }}</div>\n </div>\n\n <div class=\"entity-actions\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeEntity(config)\"\n title=\"Remove entity\"\n [attr.aria-label]=\"'Remove ' + config.entity.Name\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"no-entities\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n <p>No entities assigned to this application</p>\n <p class=\"empty-subtext\">Add entities from the available list below</p>\n </div>\n }\n\n <!-- Available Entities -->\n @if (availableEntities.length > 0) {\n <div class=\"available-entities\">\n <div class=\"available-entities-header\">\n <h4 class=\"subsection-title\">Available Entities ({{ filteredAvailableEntities.length }} of {{ availableEntities.length }})</h4>\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search entity-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"entity-search-input\"\n placeholder=\"Search entities...\"\n [value]=\"entitySearchTerm\"\n (input)=\"onEntitySearchChange($event)\"\n aria-label=\"Search available entities\"\n />\n @if (entitySearchTerm) {\n <button\n type=\"button\"\n class=\"entity-search-clear\"\n (click)=\"clearEntitySearch()\"\n aria-label=\"Clear search\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n @if (filteredAvailableEntities.length > 0) {\n <div class=\"entities-grid\" role=\"list\">\n @for (entity of filteredAvailableEntities; track entity.ID) {\n <button\n type=\"button\"\n class=\"entity-chip\"\n (click)=\"addEntity(entity)\"\n role=\"listitem\"\n [attr.aria-label]=\"'Add ' + entity.Name\"\n >\n <div class=\"chip-content\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"chip-name\">{{ entity.Name }}</span>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"no-search-results\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <p>No entities match \"{{ entitySearchTerm }}\"</p>\n </div>\n }\n </div>\n } @else {\n <div class=\"all-assigned\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <p>All entities have been assigned to this application</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- System Information Section (Edit Mode Only) -->\n @if (isEditMode) {\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.systemInfo\" (ExpandedChange)=\"toggleSection('systemInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n System Information\n </span>\n <span class=\"section-description\">Application metadata and audit information</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{ data?.application?.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Updated</span>\n <span class=\"info-value\">{{ data?.application?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Application ID</span>\n <span class=\"info-value\">{{ data?.application?.ID }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Total Entities</span>\n <span class=\"info-value\">{{ applicationEntities.length }}</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </form>\n </div>\n\n <!-- Modal Footer - Primary and Cancel buttons on RIGHT -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n mjButton variant=\"primary\"\n [disabled]=\"applicationForm.invalid || isLoading\"\n (click)=\"onSubmit()\"\n [attr.aria-busy]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Update Application' : 'Create Application' }}\n }\n </button>\n <button type=\"button\" mjButton (click)=\"onCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: ["/* =============================================================================\n Application Dialog Component\n Uses MJ Design Tokens (--mj-*)\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Modal Backdrop & Container\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0, 0, 0.2, 1);\n padding: 1rem;\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 900px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Fullscreen mode */\n.modal-dialog.fullscreen {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Header\n ----------------------------------------------------------------------------- */\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 1.5rem 1.5rem 1rem 1.5rem;\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n flex-shrink: 0;\n}\n\n.modal-header-content {\n flex: 1;\n min-width: 0;\n}\n\n.modal-header .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-brand-on-primary);\n margin: 0;\n}\n\n.modal-header .modal-title i {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.2);\n border-radius: var(--mj-radius-lg);\n font-size: 1.125rem;\n flex-shrink: 0;\n}\n\n/* Create mode - Plus icon with inverted styling */\n.modal-header.create-mode .modal-title i {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n/* Edit mode - Grid icon with semi-transparent background */\n.modal-header.edit-mode .modal-title i {\n background: rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Header Actions */\n.modal-header-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n.modal-header .modal-subtitle {\n margin: 0.375rem 0 0 0;\n font-size: 0.8125rem;\n color: var(--mj-brand-on-primary);\n opacity: 0.85;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-header .modal-close:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-header .modal-close:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Body\n ----------------------------------------------------------------------------- */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n padding: 0;\n background: var(--mj-bg-page);\n}\n\n/* -----------------------------------------------------------------------------\n Modal Footer - Primary and Cancel buttons on RIGHT\n ----------------------------------------------------------------------------- */\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Form Sections (Fieldset)\n ----------------------------------------------------------------------------- */\n.form-section {\n border: none;\n margin: 0;\n padding: 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.form-section:last-of-type {\n border-bottom: none;\n}\n\n/* -----------------------------------------------------------------------------\n Collapsible Sections \u2014 now <mj-accordion-panel>. The bespoke fieldset/legend\n chrome (.section-header / .section-title-row / .chevron-icon) was removed; the\n title (icon + title + description) is projected into the accordion title slot.\n ----------------------------------------------------------------------------- */\n.app-dialog-section-title {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n min-width: 0;\n}\n\n.app-dialog-section-title .section-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.app-dialog-section-title .section-title i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.app-dialog-section-title .section-description {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n font-weight: normal;\n}\n\n.section-content {\n animation: expandSection 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes expandSection {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Form Grid Layout\n ----------------------------------------------------------------------------- */\n.form-grid {\n display: grid;\n gap: 1.25rem;\n}\n\n.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Form Fields\n ----------------------------------------------------------------------------- */\n.form-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.form-field .field-label {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.form-field .field-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-field .field-input,\n.form-field .field-select,\n.form-field .field-textarea {\n width: 100%;\n min-height: 44px;\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n font-size: 0.9375rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n}\n\n.form-field .field-input:focus,\n.form-field .field-select:focus,\n.form-field .field-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-field .field-input.error,\n.form-field .field-select.error,\n.form-field .field-textarea.error {\n border-color: var(--mj-status-error);\n}\n\n.form-field .field-input.error:focus,\n.form-field .field-select.error:focus,\n.form-field .field-textarea.error:focus {\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.form-field .field-input::placeholder,\n.form-field .field-textarea::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.form-field .field-textarea {\n min-height: 100px;\n resize: vertical;\n line-height: 1.5;\n}\n\n.form-field .field-error {\n margin-top: 0.25rem;\n font-size: 0.8125rem;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.form-field .field-error i {\n font-size: 0.625rem;\n}\n\n.form-field .field-hint {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Entity Management Styles\n ----------------------------------------------------------------------------- */\n.subsection-title {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 1rem 0;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.assigned-entities {\n margin-bottom: 1.5rem;\n}\n\n.assigned-entities .entities-list {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.entity-item {\n display: flex;\n align-items: center;\n padding: 1rem 1.25rem;\n border-bottom: 1px solid var(--mj-bg-surface);\n transition: all 0.15s ease;\n}\n\n.entity-item:last-child {\n border-bottom: none;\n}\n\n.entity-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.is-new {\n background: color-mix(in srgb, var(--mj-status-success) 8%, transparent);\n border-left: 3px solid var(--mj-status-success);\n}\n\n.entity-item.has-changes {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, transparent);\n border-left: 3px solid var(--mj-status-warning);\n}\n\n.entity-item .entity-info {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-icon {\n width: 40px;\n height: 40px;\n background: var(--mj-brand-accent-subtle);\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.entity-item .entity-info .entity-details {\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-details .entity-name {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 0.125rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon {\n color: var(--mj-status-warning);\n font-size: 0.875rem;\n cursor: help;\n opacity: 0.7;\n transition: all 0.15s ease;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon:hover {\n opacity: 1;\n transform: scale(1.1);\n}\n\n.entity-item .entity-config {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n margin: 0 1.5rem;\n}\n\n.entity-item .entity-config .config-item .config-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.entity-item .entity-config .config-item .config-label .config-checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.entity-item .entity-config .sequence-badge {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n padding: 0.25rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.75rem;\n font-weight: 600;\n min-width: 24px;\n text-align: center;\n}\n\n.entity-item .entity-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Drag and Drop Styles\n ----------------------------------------------------------------------------- */\n.drag-handle {\n color: var(--mj-text-secondary);\n cursor: grab;\n margin-right: 0.75rem;\n font-size: 1rem;\n transition: color 0.2s ease;\n flex-shrink: 0;\n}\n\n.drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.entity-item.cdk-drag-preview {\n box-shadow: var(--mj-shadow-xl);\n transform: rotate(1deg);\n opacity: 0.9;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-page);\n}\n\n.entity-item.cdk-drag-placeholder {\n opacity: 0.4;\n border-style: dashed;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.entities-list.cdk-drop-list-dragging .entity-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty States\n ----------------------------------------------------------------------------- */\n.no-entities,\n.all-assigned {\n text-align: center;\n padding: 2rem;\n color: var(--mj-text-secondary);\n}\n\n.no-entities i,\n.all-assigned i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 1rem;\n display: block;\n}\n\n.no-entities p,\n.all-assigned p {\n margin: 0 0 0.25rem 0;\n font-size: 0.9375rem;\n}\n\n.no-entities .empty-subtext,\n.all-assigned .empty-subtext {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Section\n ----------------------------------------------------------------------------- */\n.available-entities-header {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n margin-bottom: 1rem;\n}\n\n@media (min-width: 640px) {\n .available-entities-header {\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n }\n}\n\n.available-entities-header .subsection-title {\n margin: 0;\n}\n\n/* Entity Search Bar - Enhanced prominent search */\n.entity-search {\n position: relative;\n min-width: 200px;\n max-width: 100%;\n width: 100%;\n}\n\n@media (min-width: 640px) {\n .entity-search {\n min-width: 280px;\n max-width: 400px;\n width: auto;\n }\n}\n\n@media (min-width: 768px) {\n .entity-search {\n min-width: 320px;\n max-width: 450px;\n }\n}\n\n.entity-search .entity-search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-icon {\n left: 1.125rem;\n font-size: 1.125rem;\n }\n}\n\n.entity-search .entity-search-input {\n width: 100%;\n padding: 0.875rem 2.75rem 0.875rem 2.75rem;\n border: 2px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;\n min-height: 48px;\n box-shadow: var(--mj-shadow-sm);\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-input {\n padding: 1rem 3rem 1rem 3rem;\n min-height: 52px;\n font-size: 1.0625rem;\n border-radius: var(--mj-radius-full);\n }\n}\n\n.entity-search .entity-search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.entity-search .entity-search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-search .entity-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md), 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-page);\n}\n\n.entity-search:focus-within .entity-search-icon {\n color: var(--mj-brand-primary);\n}\n\n.entity-search .entity-search-clear {\n position: absolute;\n right: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n min-height: 28px;\n transition: all 0.15s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-clear {\n right: 0.875rem;\n min-width: 32px;\n min-height: 32px;\n }\n}\n\n.entity-search .entity-search-clear:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n/* No Search Results State */\n.no-search-results {\n text-align: center;\n padding: 1.5rem;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n}\n\n.no-search-results i {\n font-size: 1.5rem;\n color: var(--mj-border-default);\n margin-bottom: 0.5rem;\n display: block;\n}\n\n.no-search-results p {\n margin: 0;\n font-size: 0.8125rem;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Grid\n ----------------------------------------------------------------------------- */\n.available-entities .entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 0.5rem;\n}\n\n.entity-chip {\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-chip .chip-content {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-chip .chip-content i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.entity-chip .chip-content .chip-name {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.entity-chip:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* -----------------------------------------------------------------------------\n Info Grid for System Information\n ----------------------------------------------------------------------------- */\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 1rem;\n}\n\n.info-grid .info-item {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.info-grid .info-item .info-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-grid .info-item .info-value {\n font-size: 0.9375rem;\n color: var(--mj-text-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Button Icon Styles\n ----------------------------------------------------------------------------- */\n.btn-icon {\n width: 36px;\n height: 36px;\n border: none;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n}\n\n.btn-icon:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-neutral {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n}\n\n.btn-icon.btn-neutral:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover:not(:disabled) {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Add/Create Icon Button */\n.btn-icon.btn-add {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-icon.btn-add:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-icon.btn-add:active:not(:disabled) {\n background: var(--mj-brand-primary-light);\n transform: scale(0.95);\n}\n\n/* -----------------------------------------------------------------------------\n Icon Wrapper - Prominent display icons\n ----------------------------------------------------------------------------- */\n.icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.icon-wrapper-sm {\n width: 32px;\n height: 32px;\n border-radius: var(--mj-radius-md);\n font-size: 0.875rem;\n}\n\n.icon-wrapper-md {\n width: 40px;\n height: 40px;\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n}\n\n.icon-wrapper-lg {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.25rem;\n}\n\n.icon-wrapper-xl {\n width: 56px;\n height: 56px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.5rem;\n}\n\n/* Icon wrapper color variants */\n.icon-wrapper-primary {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.icon-wrapper-secondary {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.icon-wrapper-tertiary {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.icon-wrapper-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Inverted icon wrapper (for dark backgrounds) */\n.icon-wrapper-inverted {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Buttons use the global `mjButton` directive (variant/size inputs) \u2014 no\n component-scoped `.mj-btn` overrides (they would collide with the directive). */\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Focus Indicators - Accessibility\n ----------------------------------------------------------------------------- */\n.field-input:focus-visible,\n.field-select:focus-visible,\n.field-textarea:focus-visible,\n.btn-icon:focus-visible,\n.entity-chip:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Reduced Motion Support\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile (< 640px)\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .modal-backdrop {\n padding: 0.5rem;\n }\n\n .modal-dialog {\n border-radius: var(--mj-radius-2xl);\n max-height: 95vh;\n }\n\n /* Fullscreen mode on mobile */\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n\n .modal-header {\n padding: 1.25rem 1rem 1rem 1rem;\n }\n\n .modal-header .modal-title {\n font-size: 1.125rem;\n }\n\n .modal-header .modal-close {\n border-radius: var(--mj-radius-full);\n }\n\n /* Modal title icon on mobile */\n .modal-header .modal-title i {\n width: 36px;\n height: 36px;\n font-size: 1rem;\n }\n\n /* Icon wrappers on mobile - slightly smaller */\n .icon-wrapper-lg {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .icon-wrapper-xl {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n\n /* Add button on mobile */\n .btn-icon.btn-add {\n border-radius: var(--mj-radius-full);\n }\n\n .form-section {\n padding: 1.25rem 1rem;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .modal-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n /* Full-width footer buttons on mobile \u2014 wrapper-scoped layout only, so the\n global mjButton directive still owns each button's appearance/shape. */\n .modal-footer button {\n width: 100%;\n justify-content: center;\n }\n\n /* Entity item mobile layout */\n .entity-item {\n flex-direction: column;\n align-items: stretch;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n position: relative;\n }\n\n /* Drag handle on mobile - Keep visible and touch-friendly */\n .drag-handle {\n position: static;\n margin-right: 0.75rem;\n margin-bottom: 0.5rem;\n font-size: 1.25rem;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: 0.5rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n cursor: grab;\n }\n\n .drag-handle:active {\n cursor: grabbing;\n background: var(--mj-brand-accent-subtle);\n }\n\n .entity-item .entity-info {\n gap: 0.75rem;\n }\n\n .entity-item .entity-info .entity-icon {\n width: 36px;\n height: 36px;\n font-size: 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-item .entity-info .entity-details .entity-name {\n font-size: 0.875rem;\n word-break: break-word;\n overflow-wrap: break-word;\n line-height: 1.3;\n flex-wrap: wrap;\n }\n\n .entity-item .entity-config {\n margin: 0;\n width: 100%;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .entity-item .entity-config .config-item .config-label {\n font-size: 0.8125rem;\n }\n\n .entity-item .entity-actions {\n width: 100%;\n justify-content: flex-end;\n gap: 0.5rem;\n }\n\n /* Entity chips in mobile */\n .available-entities .entities-grid {\n grid-template-columns: 1fr;\n }\n\n .entity-chip {\n padding: 0.625rem 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-chip .chip-content .chip-name {\n font-size: 0.75rem;\n word-break: break-word;\n }\n\n /* Entity search on mobile - still prominent */\n .entity-search {\n max-width: none;\n width: 100%;\n }\n\n .entity-search .entity-search-input {\n padding: 0.75rem 2.5rem 0.75rem 2.5rem;\n min-height: 44px;\n font-size: 0.9375rem;\n border-radius: var(--mj-radius-full);\n }\n\n .entity-search .entity-search-icon {\n left: 0.875rem;\n font-size: 0.875rem;\n }\n\n .entity-search .entity-search-clear {\n right: 0.625rem;\n border-radius: var(--mj-radius-full);\n }\n\n .info-grid {\n grid-template-columns: 1fr 1fr;\n }\n\n /* Icon buttons on mobile - keep rounded */\n .btn-icon {\n border-radius: var(--mj-radius-full);\n }\n}\n\n/* Tablet Portrait (640px - 767px) */\n@media (min-width: 640px) {\n .modal-dialog {\n max-width: 650px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n}\n\n/* Tablet Landscape (768px - 1023px) */\n@media (min-width: 768px) {\n .modal-dialog {\n max-width: 800px;\n }\n\n .modal-header {\n padding: 1.5rem 2rem 1.25rem 2rem;\n }\n\n .form-section {\n padding: 1.75rem 2rem;\n }\n\n .modal-footer {\n padding: 1.25rem 2rem;\n }\n}\n\n/* Laptop (1024px+) */\n@media (min-width: 1024px) {\n .modal-dialog {\n max-width: 900px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n }\n}\n"] }]
711
+ args: [{ standalone: false, selector: 'mj-application-dialog', template: "@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\" role=\"presentation\">\n <div\n class=\"modal-dialog\"\n [class.fullscreen]=\"isFullscreen\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"application-dialog-title\"\n aria-describedby=\"application-dialog-description\"\n >\n <!-- Modal Header -->\n <div class=\"modal-header\" [class.create-mode]=\"!isEditMode\" [class.edit-mode]=\"isEditMode\">\n <div class=\"modal-header-content\">\n <h2 class=\"modal-title\" id=\"application-dialog-title\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!isEditMode\" [class.fa-layer-group]=\"isEditMode\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Edit Application' : 'Create New Application' }}\n </h2>\n <p class=\"modal-subtitle\" id=\"application-dialog-description\">\n {{ isEditMode ? 'Update application information and settings' : 'Add a new application to the system' }}\n </p>\n </div>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleFullscreen()\"\n [attr.aria-label]=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isFullscreen\" [class.fa-expand]=\"!isFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"modal-close\"\n (click)=\"onCancel()\"\n aria-label=\"Close dialog\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"applicationForm\" (ngSubmit)=\"onSubmit()\">\n <!-- Error Alert -->\n @if (error) {\n <div class=\"form-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n\n <!-- Basic Information Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.basicInfo\" (ExpandedChange)=\"toggleSection('basicInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n Application Information\n </span>\n <span class=\"section-description\">Define the application's basic properties</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"app-name\">Application Name</label>\n <input\n id=\"app-name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"My Application\"\n [class.error]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n [attr.aria-invalid]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n aria-describedby=\"app-name-error\"\n />\n @if (applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched) {\n <div class=\"field-error\" id=\"app-name-error\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-circle\" aria-hidden=\"true\"></i>\n @if (applicationForm.get('name')?.errors?.['required']) {\n Application name is required\n }\n @if (applicationForm.get('name')?.errors?.['maxlength']) {\n Application name cannot exceed 100 characters\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"app-description\">Description</label>\n <textarea\n id=\"app-description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the application's purpose and functionality...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this application does and its main features.\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- Entity Management Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.entities\" (ExpandedChange)=\"toggleSection('entities')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Application Entities\n </span>\n <span class=\"section-description\">Manage which entities are included in this application</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <!-- Assigned Entities -->\n @if (applicationEntities.length > 0) {\n <div class=\"assigned-entities\">\n <h4 class=\"subsection-title\">Assigned Entities ({{ applicationEntities.length }})</h4>\n <div class=\"entities-list\"\n role=\"list\"\n cdkDropList\n (cdkDropListDropped)=\"onEntityDrop($event)\">\n @for (config of applicationEntities; track config.entity.ID; let i = $index) {\n <div\n class=\"entity-item\"\n [class.is-new]=\"config.isNew\"\n [class.has-changes]=\"config.hasChanges\"\n role=\"listitem\"\n cdkDrag\n >\n <i class=\"fa-solid fa-grip-vertical drag-handle\" aria-hidden=\"true\"></i>\n <div class=\"entity-info\">\n <div class=\"entity-icon\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"entity-details\">\n <div class=\"entity-name\">\n {{ getEntityDisplayName(config.entity) }}\n @if (config.entity.Description) {\n <i\n class=\"fa-solid fa-info-circle entity-info-icon\"\n [title]=\"config.entity.Description\"\n [attr.aria-label]=\"'Entity description: ' + config.entity.Description\"\n ></i>\n }\n </div>\n </div>\n </div>\n\n <div class=\"entity-config\">\n <div class=\"config-item\">\n <label class=\"config-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"config.defaultForNewUser\"\n [ngModelOptions]=\"{standalone: true}\"\n (change)=\"onDefaultForNewUserChange(config)\"\n class=\"config-checkbox\"\n />\n <span class=\"checkbox-text\">Default for new users</span>\n </label>\n </div>\n <div class=\"sequence-badge\" [attr.aria-label]=\"'Sequence ' + config.sequence\">{{ config.sequence }}</div>\n </div>\n\n <div class=\"entity-actions\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeEntity(config)\"\n title=\"Remove entity\"\n [attr.aria-label]=\"'Remove ' + getEntityDisplayName(config.entity)\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"no-entities\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n <p>No entities assigned to this application</p>\n <p class=\"empty-subtext\">Add entities from the available list below</p>\n </div>\n }\n\n <!-- Available Entities -->\n @if (availableEntities.length > 0) {\n <div class=\"available-entities\">\n <div class=\"available-entities-header\">\n <h4 class=\"subsection-title\">Available Entities ({{ filteredAvailableEntities.length }} of {{ availableEntities.length }})</h4>\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search entity-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"entity-search-input\"\n placeholder=\"Search entities...\"\n [value]=\"entitySearchTerm\"\n (input)=\"onEntitySearchChange($event)\"\n aria-label=\"Search available entities\"\n />\n @if (entitySearchTerm) {\n <button\n type=\"button\"\n class=\"entity-search-clear\"\n (click)=\"clearEntitySearch()\"\n aria-label=\"Clear search\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n @if (filteredAvailableEntities.length > 0) {\n <div class=\"entities-grid\" role=\"list\">\n @for (entity of filteredAvailableEntities; track entity.ID) {\n <button\n type=\"button\"\n class=\"entity-chip\"\n (click)=\"addEntity(entity)\"\n role=\"listitem\"\n [attr.aria-label]=\"'Add ' + getEntityDisplayName(entity)\"\n >\n <div class=\"chip-content\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"chip-name\">{{ getEntityDisplayName(entity) }}</span>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"no-search-results\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <p>No entities match \"{{ entitySearchTerm }}\"</p>\n </div>\n }\n </div>\n } @else {\n <div class=\"all-assigned\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <p>All entities have been assigned to this application</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- System Information Section (Edit Mode Only) -->\n @if (isEditMode) {\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.systemInfo\" (ExpandedChange)=\"toggleSection('systemInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n System Information\n </span>\n <span class=\"section-description\">Application metadata and audit information</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{ data?.application?.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Updated</span>\n <span class=\"info-value\">{{ data?.application?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Application ID</span>\n <span class=\"info-value\">{{ data?.application?.ID }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Total Entities</span>\n <span class=\"info-value\">{{ applicationEntities.length }}</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </form>\n </div>\n\n <!-- Modal Footer - Primary and Cancel buttons on RIGHT -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n mjButton variant=\"primary\"\n [disabled]=\"applicationForm.invalid || isLoading\"\n (click)=\"onSubmit()\"\n [attr.aria-busy]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Update Application' : 'Create Application' }}\n }\n </button>\n <button type=\"button\" mjButton (click)=\"onCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n", styles: ["/* =============================================================================\n Application Dialog Component\n Uses MJ Design Tokens (--mj-*)\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Modal Backdrop & Container\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0, 0, 0.2, 1);\n padding: 1rem;\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 900px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Fullscreen mode */\n.modal-dialog.fullscreen {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Header\n ----------------------------------------------------------------------------- */\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 1.5rem 1.5rem 1rem 1.5rem;\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n flex-shrink: 0;\n}\n\n.modal-header-content {\n flex: 1;\n min-width: 0;\n}\n\n.modal-header .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-brand-on-primary);\n margin: 0;\n}\n\n.modal-header .modal-title i {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.2);\n border-radius: var(--mj-radius-lg);\n font-size: 1.125rem;\n flex-shrink: 0;\n}\n\n/* Create mode - Plus icon with inverted styling */\n.modal-header.create-mode .modal-title i {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n/* Edit mode - Grid icon with semi-transparent background */\n.modal-header.edit-mode .modal-title i {\n background: rgba(255, 255, 255, 0.2);\n color: var(--mj-brand-on-primary);\n}\n\n/* Modal Header Actions */\n.modal-header-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n.modal-header .modal-subtitle {\n margin: 0.375rem 0 0 0;\n font-size: 0.8125rem;\n color: var(--mj-brand-on-primary);\n opacity: 0.85;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-brand-on-primary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-left: 0.5rem;\n}\n\n.modal-header .modal-close:hover {\n background: rgba(255, 255, 255, 0.15);\n}\n\n.modal-header .modal-close:focus-visible {\n outline: 2px solid var(--mj-brand-on-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Body\n ----------------------------------------------------------------------------- */\n.modal-body {\n flex: 1;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n padding: 0;\n background: var(--mj-bg-page);\n}\n\n/* -----------------------------------------------------------------------------\n Modal Footer - Primary and Cancel buttons on RIGHT\n ----------------------------------------------------------------------------- */\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Form Sections (Fieldset)\n ----------------------------------------------------------------------------- */\n.form-section {\n border: none;\n margin: 0;\n padding: 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.form-section:last-of-type {\n border-bottom: none;\n}\n\n/* -----------------------------------------------------------------------------\n Collapsible Sections \u2014 now <mj-accordion-panel>. The bespoke fieldset/legend\n chrome (.section-header / .section-title-row / .chevron-icon) was removed; the\n title (icon + title + description) is projected into the accordion title slot.\n ----------------------------------------------------------------------------- */\n.app-dialog-section-title {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n min-width: 0;\n}\n\n.app-dialog-section-title .section-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.app-dialog-section-title .section-title i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.app-dialog-section-title .section-description {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n font-weight: normal;\n}\n\n.section-content {\n animation: expandSection 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@keyframes expandSection {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Form Grid Layout\n ----------------------------------------------------------------------------- */\n.form-grid {\n display: grid;\n gap: 1.25rem;\n}\n\n.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Form Fields\n ----------------------------------------------------------------------------- */\n.form-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.form-field .field-label {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.form-field .field-label.required::after {\n content: ' *';\n color: var(--mj-status-error);\n}\n\n.form-field .field-input,\n.form-field .field-select,\n.form-field .field-textarea {\n width: 100%;\n min-height: 44px;\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n font-size: 0.9375rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease;\n}\n\n.form-field .field-input:focus,\n.form-field .field-select:focus,\n.form-field .field-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.form-field .field-input.error,\n.form-field .field-select.error,\n.form-field .field-textarea.error {\n border-color: var(--mj-status-error);\n}\n\n.form-field .field-input.error:focus,\n.form-field .field-select.error:focus,\n.form-field .field-textarea.error:focus {\n border-color: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n}\n\n.form-field .field-input::placeholder,\n.form-field .field-textarea::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.form-field .field-textarea {\n min-height: 100px;\n resize: vertical;\n line-height: 1.5;\n}\n\n.form-field .field-error {\n margin-top: 0.25rem;\n font-size: 0.8125rem;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.form-field .field-error i {\n font-size: 0.625rem;\n}\n\n.form-field .field-hint {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Entity Management Styles\n ----------------------------------------------------------------------------- */\n.subsection-title {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 1rem 0;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.assigned-entities {\n margin-bottom: 1.5rem;\n}\n\n.assigned-entities .entities-list {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n.entity-item {\n display: flex;\n align-items: center;\n padding: 1rem 1.25rem;\n border-bottom: 1px solid var(--mj-bg-surface);\n transition: all 0.15s ease;\n}\n\n.entity-item:last-child {\n border-bottom: none;\n}\n\n.entity-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.is-new {\n background: color-mix(in srgb, var(--mj-status-success) 8%, transparent);\n border-left: 3px solid var(--mj-status-success);\n}\n\n.entity-item.has-changes {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, transparent);\n border-left: 3px solid var(--mj-status-warning);\n}\n\n.entity-item .entity-info {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-icon {\n width: 40px;\n height: 40px;\n background: var(--mj-brand-accent-subtle);\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.entity-item .entity-info .entity-details {\n flex: 1;\n min-width: 0;\n}\n\n.entity-item .entity-info .entity-details .entity-name {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 0.125rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon {\n color: var(--mj-status-warning);\n font-size: 0.875rem;\n cursor: help;\n opacity: 0.7;\n transition: all 0.15s ease;\n}\n\n.entity-item .entity-info .entity-details .entity-name .entity-info-icon:hover {\n opacity: 1;\n transform: scale(1.1);\n}\n\n.entity-item .entity-config {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n margin: 0 1.5rem;\n}\n\n.entity-item .entity-config .config-item .config-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.entity-item .entity-config .config-item .config-label .config-checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n}\n\n.entity-item .entity-config .sequence-badge {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n padding: 0.25rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.75rem;\n font-weight: 600;\n min-width: 24px;\n text-align: center;\n}\n\n.entity-item .entity-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Drag and Drop Styles\n ----------------------------------------------------------------------------- */\n.drag-handle {\n color: var(--mj-text-secondary);\n cursor: grab;\n margin-right: 0.75rem;\n font-size: 1rem;\n transition: color 0.2s ease;\n flex-shrink: 0;\n}\n\n.drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.entity-item.cdk-drag-preview {\n box-shadow: var(--mj-shadow-xl);\n transform: rotate(1deg);\n opacity: 0.9;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-page);\n}\n\n.entity-item.cdk-drag-placeholder {\n opacity: 0.4;\n border-style: dashed;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-item.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.entities-list.cdk-drop-list-dragging .entity-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty States\n ----------------------------------------------------------------------------- */\n.no-entities,\n.all-assigned {\n text-align: center;\n padding: 2rem;\n color: var(--mj-text-secondary);\n}\n\n.no-entities i,\n.all-assigned i {\n font-size: 2rem;\n color: var(--mj-border-default);\n margin-bottom: 1rem;\n display: block;\n}\n\n.no-entities p,\n.all-assigned p {\n margin: 0 0 0.25rem 0;\n font-size: 0.9375rem;\n}\n\n.no-entities .empty-subtext,\n.all-assigned .empty-subtext {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Section\n ----------------------------------------------------------------------------- */\n.available-entities-header {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n margin-bottom: 1rem;\n}\n\n@media (min-width: 640px) {\n .available-entities-header {\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n }\n}\n\n.available-entities-header .subsection-title {\n margin: 0;\n}\n\n/* Entity Search Bar - Enhanced prominent search */\n.entity-search {\n position: relative;\n min-width: 200px;\n max-width: 100%;\n width: 100%;\n}\n\n@media (min-width: 640px) {\n .entity-search {\n min-width: 280px;\n max-width: 400px;\n width: auto;\n }\n}\n\n@media (min-width: 768px) {\n .entity-search {\n min-width: 320px;\n max-width: 450px;\n }\n}\n\n.entity-search .entity-search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-icon {\n left: 1.125rem;\n font-size: 1.125rem;\n }\n}\n\n.entity-search .entity-search-input {\n width: 100%;\n padding: 0.875rem 2.75rem 0.875rem 2.75rem;\n border: 2px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;\n min-height: 48px;\n box-shadow: var(--mj-shadow-sm);\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-input {\n padding: 1rem 3rem 1rem 3rem;\n min-height: 52px;\n font-size: 1.0625rem;\n border-radius: var(--mj-radius-full);\n }\n}\n\n.entity-search .entity-search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.entity-search .entity-search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.entity-search .entity-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md), 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-page);\n}\n\n.entity-search:focus-within .entity-search-icon {\n color: var(--mj-brand-primary);\n}\n\n.entity-search .entity-search-clear {\n position: absolute;\n right: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n min-height: 28px;\n transition: all 0.15s ease;\n}\n\n@media (min-width: 768px) {\n .entity-search .entity-search-clear {\n right: 0.875rem;\n min-width: 32px;\n min-height: 32px;\n }\n}\n\n.entity-search .entity-search-clear:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n/* No Search Results State */\n.no-search-results {\n text-align: center;\n padding: 1.5rem;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n}\n\n.no-search-results i {\n font-size: 1.5rem;\n color: var(--mj-border-default);\n margin-bottom: 0.5rem;\n display: block;\n}\n\n.no-search-results p {\n margin: 0;\n font-size: 0.8125rem;\n}\n\n/* -----------------------------------------------------------------------------\n Available Entities Grid\n ----------------------------------------------------------------------------- */\n.available-entities .entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 0.5rem;\n}\n\n.entity-chip {\n padding: 0.75rem 1rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-page);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-chip .chip-content {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.entity-chip .chip-content i {\n color: var(--mj-brand-primary);\n font-size: 0.875rem;\n}\n\n.entity-chip .chip-content .chip-name {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.entity-chip:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* -----------------------------------------------------------------------------\n Info Grid for System Information\n ----------------------------------------------------------------------------- */\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 1rem;\n}\n\n.info-grid .info-item {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.info-grid .info-item .info-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-grid .info-item .info-value {\n font-size: 0.9375rem;\n color: var(--mj-text-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Button Icon Styles\n ----------------------------------------------------------------------------- */\n.btn-icon {\n width: 36px;\n height: 36px;\n border: none;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n}\n\n.btn-icon:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-neutral {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n}\n\n.btn-icon.btn-neutral:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.btn-icon.btn-danger {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n.btn-icon.btn-danger:hover:not(:disabled) {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* Add/Create Icon Button */\n.btn-icon.btn-add {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-icon.btn-add:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-icon.btn-add:active:not(:disabled) {\n background: var(--mj-brand-primary-light);\n transform: scale(0.95);\n}\n\n/* -----------------------------------------------------------------------------\n Icon Wrapper - Prominent display icons\n ----------------------------------------------------------------------------- */\n.icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.icon-wrapper-sm {\n width: 32px;\n height: 32px;\n border-radius: var(--mj-radius-md);\n font-size: 0.875rem;\n}\n\n.icon-wrapper-md {\n width: 40px;\n height: 40px;\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n}\n\n.icon-wrapper-lg {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.25rem;\n}\n\n.icon-wrapper-xl {\n width: 56px;\n height: 56px;\n border-radius: var(--mj-radius-lg);\n font-size: 1.5rem;\n}\n\n/* Icon wrapper color variants */\n.icon-wrapper-primary {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.icon-wrapper-secondary {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning);\n}\n\n.icon-wrapper-tertiary {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.icon-wrapper-error {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Inverted icon wrapper (for dark backgrounds) */\n.icon-wrapper-inverted {\n background: var(--mj-brand-on-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Buttons use the global `mjButton` directive (variant/size inputs) \u2014 no\n component-scoped `.mj-btn` overrides (they would collide with the directive). */\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Focus Indicators - Accessibility\n ----------------------------------------------------------------------------- */\n.field-input:focus-visible,\n.field-select:focus-visible,\n.field-textarea:focus-visible,\n.btn-icon:focus-visible,\n.entity-chip:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Reduced Motion Support\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile (< 640px)\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .modal-backdrop {\n padding: 0.5rem;\n }\n\n .modal-dialog {\n border-radius: var(--mj-radius-2xl);\n max-height: 95vh;\n }\n\n /* Fullscreen mode on mobile */\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n\n .modal-header {\n padding: 1.25rem 1rem 1rem 1rem;\n }\n\n .modal-header .modal-title {\n font-size: 1.125rem;\n }\n\n .modal-header .modal-close {\n border-radius: var(--mj-radius-full);\n }\n\n /* Modal title icon on mobile */\n .modal-header .modal-title i {\n width: 36px;\n height: 36px;\n font-size: 1rem;\n }\n\n /* Icon wrappers on mobile - slightly smaller */\n .icon-wrapper-lg {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .icon-wrapper-xl {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n\n /* Add button on mobile */\n .btn-icon.btn-add {\n border-radius: var(--mj-radius-full);\n }\n\n .form-section {\n padding: 1.25rem 1rem;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .modal-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n /* Full-width footer buttons on mobile \u2014 wrapper-scoped layout only, so the\n global mjButton directive still owns each button's appearance/shape. */\n .modal-footer button {\n width: 100%;\n justify-content: center;\n }\n\n /* Entity item mobile layout */\n .entity-item {\n flex-direction: column;\n align-items: stretch;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n position: relative;\n }\n\n /* Drag handle on mobile - Keep visible and touch-friendly */\n .drag-handle {\n position: static;\n margin-right: 0.75rem;\n margin-bottom: 0.5rem;\n font-size: 1.25rem;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: 0.5rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n cursor: grab;\n }\n\n .drag-handle:active {\n cursor: grabbing;\n background: var(--mj-brand-accent-subtle);\n }\n\n .entity-item .entity-info {\n gap: 0.75rem;\n }\n\n .entity-item .entity-info .entity-icon {\n width: 36px;\n height: 36px;\n font-size: 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-item .entity-info .entity-details .entity-name {\n font-size: 0.875rem;\n word-break: break-word;\n overflow-wrap: break-word;\n line-height: 1.3;\n flex-wrap: wrap;\n }\n\n .entity-item .entity-config {\n margin: 0;\n width: 100%;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .entity-item .entity-config .config-item .config-label {\n font-size: 0.8125rem;\n }\n\n .entity-item .entity-actions {\n width: 100%;\n justify-content: flex-end;\n gap: 0.5rem;\n }\n\n /* Entity chips in mobile */\n .available-entities .entities-grid {\n grid-template-columns: 1fr;\n }\n\n .entity-chip {\n padding: 0.625rem 0.875rem;\n border-radius: var(--mj-radius-md);\n }\n\n .entity-chip .chip-content .chip-name {\n font-size: 0.75rem;\n word-break: break-word;\n }\n\n /* Entity search on mobile - still prominent */\n .entity-search {\n max-width: none;\n width: 100%;\n }\n\n .entity-search .entity-search-input {\n padding: 0.75rem 2.5rem 0.75rem 2.5rem;\n min-height: 44px;\n font-size: 0.9375rem;\n border-radius: var(--mj-radius-full);\n }\n\n .entity-search .entity-search-icon {\n left: 0.875rem;\n font-size: 0.875rem;\n }\n\n .entity-search .entity-search-clear {\n right: 0.625rem;\n border-radius: var(--mj-radius-full);\n }\n\n .info-grid {\n grid-template-columns: 1fr 1fr;\n }\n\n /* Icon buttons on mobile - keep rounded */\n .btn-icon {\n border-radius: var(--mj-radius-full);\n }\n}\n\n/* Tablet Portrait (640px - 767px) */\n@media (min-width: 640px) {\n .modal-dialog {\n max-width: 650px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n}\n\n/* Tablet Landscape (768px - 1023px) */\n@media (min-width: 768px) {\n .modal-dialog {\n max-width: 800px;\n }\n\n .modal-header {\n padding: 1.5rem 2rem 1.25rem 2rem;\n }\n\n .form-section {\n padding: 1.75rem 2rem;\n }\n\n .modal-footer {\n padding: 1.25rem 2rem;\n }\n}\n\n/* Laptop (1024px+) */\n@media (min-width: 1024px) {\n .modal-dialog {\n max-width: 900px;\n }\n\n .available-entities .entities-grid {\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n }\n}\n"] }]
706
712
  }], () => [], { data: [{
707
713
  type: Input
708
714
  }], visible: [{
@@ -1 +1 @@
1
- {"version":3,"file":"application-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/application-management/application-dialog/application-dialog.component.ts","../../../../src/lib/application-management/application-dialog/application-dialog.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ChangeDetectorRef, NgZone } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';\nimport { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJApplicationEntity, MJApplicationEntityEntity, MJEntityEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nexport interface ApplicationDialogData {\n application?: MJApplicationEntity;\n mode: 'create' | 'edit';\n}\n\ninterface ApplicationEntityConfig {\n entity: MJEntityEntity;\n applicationEntity?: MJApplicationEntityEntity;\n sequence: number;\n defaultForNewUser: boolean;\n isNew: boolean;\n hasChanges: boolean;\n}\n\nexport interface ApplicationDialogResult {\n action: 'save' | 'cancel';\n application?: MJApplicationEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-application-dialog',\n templateUrl: './application-dialog.component.html',\n styleUrls: ['./application-dialog.component.css']\n})\nexport class ApplicationDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: ApplicationDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<ApplicationDialogResult>();\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private get metadata() { return this.ProviderToUse; }\n public applicationForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n\n // Entity management\n public applicationEntities: ApplicationEntityConfig[] = [];\n public availableEntities: MJEntityEntity[] = [];\n public allEntities: MJEntityEntity[] = [];\n\n // Search filter for available entities\n public entitySearchTerm = '';\n\n // Section expansion state\n public sectionExpanded = {\n basicInfo: true,\n entities: true,\n systemInfo: false\n };\n\n // Fullscreen state\n public isFullscreen = false;\n\n constructor() {\n super();\n this.applicationForm = this.fb.group({\n name: ['', [Validators.required, Validators.maxLength(100)]],\n description: ['']\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['visible'] && this.visible) {\n this.initializeDialog();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private async initializeDialog(): Promise<void> {\n if (!this.visible) return;\n \n try {\n this.isLoading = true;\n this.error = null;\n \n // Load all entities first\n await this.loadAllEntities();\n \n if (this.data?.application && this.isEditMode) {\n await this.loadApplicationData();\n } else {\n this.resetForm();\n }\n } catch (error: unknown) {\n console.error('Error initializing dialog:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'Failed to load dialog data';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async loadAllEntities(): Promise<void> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJEntityEntity>({\n EntityName: 'MJ: Entities',\n ResultType: 'entity_object',\n OrderBy: 'Name ASC'\n });\n \n this.allEntities = result.Success ? result.Results : [];\n }\n\n private resetForm(): void {\n this.applicationForm.reset({\n name: '',\n description: ''\n });\n this.applicationEntities = [];\n this.availableEntities = [...this.allEntities];\n this.entitySearchTerm = '';\n this.error = null;\n }\n\n @HostListener('document:keydown.escape')\n onEscapeKey(): void {\n if (this.visible) {\n this.onCancel();\n }\n }\n\n public get windowTitle(): string {\n return this.isEditMode ? 'Edit Application' : 'Create New Application';\n }\n\n public get isEditMode(): boolean {\n return this.data?.mode === 'edit';\n }\n\n private async loadApplicationData(): Promise<void> {\n if (!this.data?.application) return;\n\n const app = this.data.application;\n this.applicationForm.patchValue({\n name: app.Name,\n description: app.Description\n });\n\n // Load existing MJApplicationEntity records\n await this.loadApplicationEntities(app.ID);\n }\n\n private async loadApplicationEntities(applicationId: string): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJApplicationEntityEntity>({\n EntityName: 'MJ: Application Entities',\n ExtraFilter: `ApplicationID='${applicationId}'`,\n ResultType: 'entity_object',\n OrderBy: 'Sequence ASC'\n });\n\n if (result.Success && result.Results) {\n this.applicationEntities = [];\n const usedEntityIds = new Set<string>();\n\n for (const appEntity of result.Results) {\n const entity = this.allEntities.find(e => UUIDsEqual(e.ID, appEntity.EntityID));\n if (entity) {\n this.applicationEntities.push({\n entity,\n applicationEntity: appEntity,\n sequence: appEntity.Sequence || 0,\n defaultForNewUser: appEntity.DefaultForNewUser || false,\n isNew: false,\n hasChanges: false\n });\n usedEntityIds.add(entity.ID);\n }\n }\n\n // Set available entities (excluding already assigned ones)\n this.availableEntities = this.allEntities.filter(e => !usedEntityIds.has(e.ID));\n }\n } catch (error) {\n console.warn('Failed to load application entities:', error);\n this.availableEntities = [...this.allEntities];\n }\n }\n\n public addEntity(entity: MJEntityEntity): void {\n // Add entity to application\n this.applicationEntities.push({\n entity,\n sequence: this.applicationEntities.length + 1,\n defaultForNewUser: false,\n isNew: true,\n hasChanges: false\n });\n\n // Update all sequences to be consecutive\n this.updateSequences();\n\n // Remove from available entities\n this.availableEntities = this.availableEntities.filter(e => !UUIDsEqual(e.ID, entity.ID));\n }\n\n public removeEntity(config: ApplicationEntityConfig): void {\n // Remove from application entities\n this.applicationEntities = this.applicationEntities.filter(ae => !UUIDsEqual(ae.entity.ID, config.entity.ID));\n \n // Update all sequences to be consecutive\n this.updateSequences();\n \n // Add back to available entities if not already there\n if (!this.availableEntities.find(e => UUIDsEqual(e.ID, config.entity.ID))) {\n this.availableEntities.push(config.entity);\n this.availableEntities.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n }\n\n public moveEntityUp(index: number): void {\n if (index > 0) {\n const temp = this.applicationEntities[index];\n this.applicationEntities[index] = this.applicationEntities[index - 1];\n this.applicationEntities[index - 1] = temp;\n this.updateSequences();\n }\n }\n\n public moveEntityDown(index: number): void {\n if (index < this.applicationEntities.length - 1) {\n const temp = this.applicationEntities[index];\n this.applicationEntities[index] = this.applicationEntities[index + 1];\n this.applicationEntities[index + 1] = temp;\n this.updateSequences();\n }\n }\n\n private updateSequences(): void {\n this.applicationEntities.forEach((config, index) => {\n config.sequence = index + 1;\n if (!config.isNew) {\n config.hasChanges = true;\n }\n });\n }\n\n public onDefaultForNewUserChange(config: ApplicationEntityConfig): void {\n if (!config.isNew) {\n config.hasChanges = true;\n }\n }\n\n public get hasEntityChanges(): boolean {\n return this.applicationEntities.some(ae => ae.isNew || ae.hasChanges);\n }\n\n // Filtered available entities based on search term\n public get filteredAvailableEntities(): MJEntityEntity[] {\n if (!this.entitySearchTerm || !this.entitySearchTerm.trim()) {\n return this.availableEntities;\n }\n const searchLower = this.entitySearchTerm.toLowerCase().trim();\n return this.availableEntities.filter(entity =>\n (entity.Name || '').toLowerCase().includes(searchLower) ||\n (entity.Description || '').toLowerCase().includes(searchLower)\n );\n }\n\n public onEntitySearchChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.entitySearchTerm = value;\n }\n\n public clearEntitySearch(): void {\n this.entitySearchTerm = '';\n }\n\n public toggleSection(section: 'basicInfo' | 'entities' | 'systemInfo'): void {\n this.sectionExpanded[section] = !this.sectionExpanded[section];\n }\n\n public toggleFullscreen(): void {\n this.isFullscreen = !this.isFullscreen;\n }\n\n public onEntityDrop(event: CdkDragDrop<ApplicationEntityConfig[]>): void {\n if (event.previousIndex !== event.currentIndex) {\n moveItemInArray(this.applicationEntities, event.previousIndex, event.currentIndex);\n this.updateSequences();\n }\n }\n\n public async onSubmit(): Promise<void> {\n if (this.applicationForm.invalid) {\n this.markFormGroupTouched(this.applicationForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let application: MJApplicationEntity;\n\n if (this.isEditMode && this.data?.application) {\n // Edit existing application\n application = this.data.application;\n } else {\n // Create new application\n application = await this.metadata.GetEntityObject<MJApplicationEntity>('MJ: Applications');\n application.NewRecord();\n }\n\n // Update application properties\n const formValue = this.applicationForm.value;\n application.Name = formValue.name;\n application.Description = formValue.description || null;\n\n // Save application\n const saveResult = await application.Save();\n if (!saveResult) {\n throw new Error(application.LatestResult?.Message || 'Failed to save application');\n }\n\n // Save application entities if there are changes\n if (this.hasEntityChanges) {\n await this.saveApplicationEntities(application.ID);\n }\n\n this.result.emit({ action: 'save', application });\n\n } catch (error: unknown) {\n console.error('Error saving application:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async saveApplicationEntities(applicationId: string): Promise<void> {\n // Save or update each MJApplicationEntity record\n for (const config of this.applicationEntities) {\n if (config.isNew || config.hasChanges) {\n let appEntity: MJApplicationEntityEntity;\n\n if (config.isNew) {\n // Create new MJApplicationEntity\n appEntity = await this.metadata.GetEntityObject<MJApplicationEntityEntity>('MJ: Application Entities');\n appEntity.NewRecord();\n appEntity.ApplicationID = applicationId;\n appEntity.EntityID = config.entity.ID;\n } else if (config.applicationEntity) {\n // Update existing MJApplicationEntity\n appEntity = config.applicationEntity;\n } else {\n continue;\n }\n\n appEntity.Sequence = config.sequence;\n appEntity.DefaultForNewUser = config.defaultForNewUser;\n\n const saveResult = await appEntity.Save();\n if (!saveResult) {\n console.warn(`Failed to save MJApplicationEntity for ${config.entity.Name}:`, appEntity.LatestResult?.Message);\n }\n }\n }\n }\n\n public onCancel(): void {\n this.result.emit({ action: 'cancel' });\n }\n\n private markFormGroupTouched(formGroup: FormGroup): void {\n Object.keys(formGroup.controls).forEach(key => {\n const control = formGroup.get(key);\n control?.markAsTouched();\n });\n }\n}","@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\" role=\"presentation\">\n <div\n class=\"modal-dialog\"\n [class.fullscreen]=\"isFullscreen\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"application-dialog-title\"\n aria-describedby=\"application-dialog-description\"\n >\n <!-- Modal Header -->\n <div class=\"modal-header\" [class.create-mode]=\"!isEditMode\" [class.edit-mode]=\"isEditMode\">\n <div class=\"modal-header-content\">\n <h2 class=\"modal-title\" id=\"application-dialog-title\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!isEditMode\" [class.fa-layer-group]=\"isEditMode\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Edit Application' : 'Create New Application' }}\n </h2>\n <p class=\"modal-subtitle\" id=\"application-dialog-description\">\n {{ isEditMode ? 'Update application information and settings' : 'Add a new application to the system' }}\n </p>\n </div>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleFullscreen()\"\n [attr.aria-label]=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isFullscreen\" [class.fa-expand]=\"!isFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"modal-close\"\n (click)=\"onCancel()\"\n aria-label=\"Close dialog\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"applicationForm\" (ngSubmit)=\"onSubmit()\">\n <!-- Error Alert -->\n @if (error) {\n <div class=\"form-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n\n <!-- Basic Information Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.basicInfo\" (ExpandedChange)=\"toggleSection('basicInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n Application Information\n </span>\n <span class=\"section-description\">Define the application's basic properties</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"app-name\">Application Name</label>\n <input\n id=\"app-name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"My Application\"\n [class.error]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n [attr.aria-invalid]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n aria-describedby=\"app-name-error\"\n />\n @if (applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched) {\n <div class=\"field-error\" id=\"app-name-error\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-circle\" aria-hidden=\"true\"></i>\n @if (applicationForm.get('name')?.errors?.['required']) {\n Application name is required\n }\n @if (applicationForm.get('name')?.errors?.['maxlength']) {\n Application name cannot exceed 100 characters\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"app-description\">Description</label>\n <textarea\n id=\"app-description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the application's purpose and functionality...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this application does and its main features.\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- Entity Management Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.entities\" (ExpandedChange)=\"toggleSection('entities')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Application Entities\n </span>\n <span class=\"section-description\">Manage which entities are included in this application</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <!-- Assigned Entities -->\n @if (applicationEntities.length > 0) {\n <div class=\"assigned-entities\">\n <h4 class=\"subsection-title\">Assigned Entities ({{ applicationEntities.length }})</h4>\n <div class=\"entities-list\"\n role=\"list\"\n cdkDropList\n (cdkDropListDropped)=\"onEntityDrop($event)\">\n @for (config of applicationEntities; track config.entity.ID; let i = $index) {\n <div\n class=\"entity-item\"\n [class.is-new]=\"config.isNew\"\n [class.has-changes]=\"config.hasChanges\"\n role=\"listitem\"\n cdkDrag\n >\n <i class=\"fa-solid fa-grip-vertical drag-handle\" aria-hidden=\"true\"></i>\n <div class=\"entity-info\">\n <div class=\"entity-icon\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"entity-details\">\n <div class=\"entity-name\">\n {{ config.entity.Name }}\n @if (config.entity.Description) {\n <i\n class=\"fa-solid fa-info-circle entity-info-icon\"\n [title]=\"config.entity.Description\"\n [attr.aria-label]=\"'Entity description: ' + config.entity.Description\"\n ></i>\n }\n </div>\n </div>\n </div>\n\n <div class=\"entity-config\">\n <div class=\"config-item\">\n <label class=\"config-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"config.defaultForNewUser\"\n [ngModelOptions]=\"{standalone: true}\"\n (change)=\"onDefaultForNewUserChange(config)\"\n class=\"config-checkbox\"\n />\n <span class=\"checkbox-text\">Default for new users</span>\n </label>\n </div>\n <div class=\"sequence-badge\" [attr.aria-label]=\"'Sequence ' + config.sequence\">{{ config.sequence }}</div>\n </div>\n\n <div class=\"entity-actions\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeEntity(config)\"\n title=\"Remove entity\"\n [attr.aria-label]=\"'Remove ' + config.entity.Name\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"no-entities\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n <p>No entities assigned to this application</p>\n <p class=\"empty-subtext\">Add entities from the available list below</p>\n </div>\n }\n\n <!-- Available Entities -->\n @if (availableEntities.length > 0) {\n <div class=\"available-entities\">\n <div class=\"available-entities-header\">\n <h4 class=\"subsection-title\">Available Entities ({{ filteredAvailableEntities.length }} of {{ availableEntities.length }})</h4>\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search entity-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"entity-search-input\"\n placeholder=\"Search entities...\"\n [value]=\"entitySearchTerm\"\n (input)=\"onEntitySearchChange($event)\"\n aria-label=\"Search available entities\"\n />\n @if (entitySearchTerm) {\n <button\n type=\"button\"\n class=\"entity-search-clear\"\n (click)=\"clearEntitySearch()\"\n aria-label=\"Clear search\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n @if (filteredAvailableEntities.length > 0) {\n <div class=\"entities-grid\" role=\"list\">\n @for (entity of filteredAvailableEntities; track entity.ID) {\n <button\n type=\"button\"\n class=\"entity-chip\"\n (click)=\"addEntity(entity)\"\n role=\"listitem\"\n [attr.aria-label]=\"'Add ' + entity.Name\"\n >\n <div class=\"chip-content\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"chip-name\">{{ entity.Name }}</span>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"no-search-results\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <p>No entities match \"{{ entitySearchTerm }}\"</p>\n </div>\n }\n </div>\n } @else {\n <div class=\"all-assigned\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <p>All entities have been assigned to this application</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- System Information Section (Edit Mode Only) -->\n @if (isEditMode) {\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.systemInfo\" (ExpandedChange)=\"toggleSection('systemInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n System Information\n </span>\n <span class=\"section-description\">Application metadata and audit information</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{ data?.application?.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Updated</span>\n <span class=\"info-value\">{{ data?.application?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Application ID</span>\n <span class=\"info-value\">{{ data?.application?.ID }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Total Entities</span>\n <span class=\"info-value\">{{ applicationEntities.length }}</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </form>\n </div>\n\n <!-- Modal Footer - Primary and Cancel buttons on RIGHT -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n mjButton variant=\"primary\"\n [disabled]=\"applicationForm.invalid || isLoading\"\n (click)=\"onSubmit()\"\n [attr.aria-busy]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Update Application' : 'Create Application' }}\n }\n </button>\n <button type=\"button\" mjButton (click)=\"onCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"application-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/application-management/application-dialog/application-dialog.component.ts","../../../../src/lib/application-management/application-dialog/application-dialog.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ChangeDetectorRef, NgZone } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';\nimport { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJApplicationEntity, MJApplicationEntityEntity, MJEntityEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nexport interface ApplicationDialogData {\n application?: MJApplicationEntity;\n mode: 'create' | 'edit';\n}\n\ninterface ApplicationEntityConfig {\n entity: MJEntityEntity;\n applicationEntity?: MJApplicationEntityEntity;\n sequence: number;\n defaultForNewUser: boolean;\n isNew: boolean;\n hasChanges: boolean;\n}\n\nexport interface ApplicationDialogResult {\n action: 'save' | 'cancel';\n application?: MJApplicationEntity;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-application-dialog',\n templateUrl: './application-dialog.component.html',\n styleUrls: ['./application-dialog.component.css']\n})\nexport class ApplicationDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: ApplicationDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<ApplicationDialogResult>();\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private get metadata() { return this.ProviderToUse; }\n public applicationForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n\n // Entity management\n public applicationEntities: ApplicationEntityConfig[] = [];\n public availableEntities: MJEntityEntity[] = [];\n public allEntities: MJEntityEntity[] = [];\n\n // Search filter for available entities\n public entitySearchTerm = '';\n\n // Section expansion state\n public sectionExpanded = {\n basicInfo: true,\n entities: true,\n systemInfo: false\n };\n\n // Fullscreen state\n public isFullscreen = false;\n\n constructor() {\n super();\n this.applicationForm = this.fb.group({\n name: ['', [Validators.required, Validators.maxLength(100)]],\n description: ['']\n });\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['visible'] && this.visible) {\n this.initializeDialog();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private async initializeDialog(): Promise<void> {\n if (!this.visible) return;\n \n try {\n this.isLoading = true;\n this.error = null;\n \n // Load all entities first\n await this.loadAllEntities();\n \n if (this.data?.application && this.isEditMode) {\n await this.loadApplicationData();\n } else {\n this.resetForm();\n }\n } catch (error: unknown) {\n console.error('Error initializing dialog:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'Failed to load dialog data';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async loadAllEntities(): Promise<void> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJEntityEntity>({\n EntityName: 'MJ: Entities',\n ResultType: 'entity_object',\n OrderBy: 'Name ASC'\n });\n \n this.allEntities = result.Success ? result.Results : [];\n }\n\n private resetForm(): void {\n this.applicationForm.reset({\n name: '',\n description: ''\n });\n this.applicationEntities = [];\n this.availableEntities = [...this.allEntities];\n this.entitySearchTerm = '';\n this.error = null;\n }\n\n @HostListener('document:keydown.escape')\n onEscapeKey(): void {\n if (this.visible) {\n this.onCancel();\n }\n }\n\n public get windowTitle(): string {\n return this.isEditMode ? 'Edit Application' : 'Create New Application';\n }\n\n public get isEditMode(): boolean {\n return this.data?.mode === 'edit';\n }\n\n private async loadApplicationData(): Promise<void> {\n if (!this.data?.application) return;\n\n const app = this.data.application;\n this.applicationForm.patchValue({\n name: app.Name,\n description: app.Description\n });\n\n // Load existing MJApplicationEntity records\n await this.loadApplicationEntities(app.ID);\n }\n\n private async loadApplicationEntities(applicationId: string): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJApplicationEntityEntity>({\n EntityName: 'MJ: Application Entities',\n ExtraFilter: `ApplicationID='${applicationId}'`,\n ResultType: 'entity_object',\n OrderBy: 'Sequence ASC'\n });\n\n if (result.Success && result.Results) {\n this.applicationEntities = [];\n const usedEntityIds = new Set<string>();\n\n for (const appEntity of result.Results) {\n const entity = this.allEntities.find(e => UUIDsEqual(e.ID, appEntity.EntityID));\n if (entity) {\n this.applicationEntities.push({\n entity,\n applicationEntity: appEntity,\n sequence: appEntity.Sequence || 0,\n defaultForNewUser: appEntity.DefaultForNewUser || false,\n isNew: false,\n hasChanges: false\n });\n usedEntityIds.add(entity.ID);\n }\n }\n\n // Set available entities (excluding already assigned ones)\n this.availableEntities = this.allEntities.filter(e => !usedEntityIds.has(e.ID));\n }\n } catch (error) {\n console.warn('Failed to load application entities:', error);\n this.availableEntities = [...this.allEntities];\n }\n }\n\n public addEntity(entity: MJEntityEntity): void {\n // Add entity to application\n this.applicationEntities.push({\n entity,\n sequence: this.applicationEntities.length + 1,\n defaultForNewUser: false,\n isNew: true,\n hasChanges: false\n });\n\n // Update all sequences to be consecutive\n this.updateSequences();\n\n // Remove from available entities\n this.availableEntities = this.availableEntities.filter(e => !UUIDsEqual(e.ID, entity.ID));\n }\n\n public removeEntity(config: ApplicationEntityConfig): void {\n // Remove from application entities\n this.applicationEntities = this.applicationEntities.filter(ae => !UUIDsEqual(ae.entity.ID, config.entity.ID));\n \n // Update all sequences to be consecutive\n this.updateSequences();\n \n // Add back to available entities if not already there\n if (!this.availableEntities.find(e => UUIDsEqual(e.ID, config.entity.ID))) {\n this.availableEntities.push(config.entity);\n this.availableEntities.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n }\n\n public moveEntityUp(index: number): void {\n if (index > 0) {\n const temp = this.applicationEntities[index];\n this.applicationEntities[index] = this.applicationEntities[index - 1];\n this.applicationEntities[index - 1] = temp;\n this.updateSequences();\n }\n }\n\n public moveEntityDown(index: number): void {\n if (index < this.applicationEntities.length - 1) {\n const temp = this.applicationEntities[index];\n this.applicationEntities[index] = this.applicationEntities[index + 1];\n this.applicationEntities[index + 1] = temp;\n this.updateSequences();\n }\n }\n\n private updateSequences(): void {\n this.applicationEntities.forEach((config, index) => {\n config.sequence = index + 1;\n if (!config.isNew) {\n config.hasChanges = true;\n }\n });\n }\n\n public onDefaultForNewUserChange(config: ApplicationEntityConfig): void {\n if (!config.isNew) {\n config.hasChanges = true;\n }\n }\n\n public get hasEntityChanges(): boolean {\n return this.applicationEntities.some(ae => ae.isNew || ae.hasChanges);\n }\n\n // Filtered available entities based on search term\n public get filteredAvailableEntities(): MJEntityEntity[] {\n if (!this.entitySearchTerm || !this.entitySearchTerm.trim()) {\n return this.availableEntities;\n }\n const searchLower = this.entitySearchTerm.toLowerCase().trim();\n return this.availableEntities.filter(entity =>\n (entity.DisplayName || '').toLowerCase().includes(searchLower) ||\n (entity.Name || '').toLowerCase().includes(searchLower) ||\n (entity.Description || '').toLowerCase().includes(searchLower)\n );\n }\n\n public getEntityDisplayName(entity: MJEntityEntity): string {\n return entity.DisplayName || entity.Name;\n }\n\n public onEntitySearchChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.entitySearchTerm = value;\n }\n\n public clearEntitySearch(): void {\n this.entitySearchTerm = '';\n }\n\n public toggleSection(section: 'basicInfo' | 'entities' | 'systemInfo'): void {\n this.sectionExpanded[section] = !this.sectionExpanded[section];\n }\n\n public toggleFullscreen(): void {\n this.isFullscreen = !this.isFullscreen;\n }\n\n public onEntityDrop(event: CdkDragDrop<ApplicationEntityConfig[]>): void {\n if (event.previousIndex !== event.currentIndex) {\n moveItemInArray(this.applicationEntities, event.previousIndex, event.currentIndex);\n this.updateSequences();\n }\n }\n\n public async onSubmit(): Promise<void> {\n if (this.applicationForm.invalid) {\n this.markFormGroupTouched(this.applicationForm);\n return;\n }\n\n this.isLoading = true;\n this.error = null;\n\n try {\n let application: MJApplicationEntity;\n\n if (this.isEditMode && this.data?.application) {\n // Edit existing application\n application = this.data.application;\n } else {\n // Create new application\n application = await this.metadata.GetEntityObject<MJApplicationEntity>('MJ: Applications');\n application.NewRecord();\n }\n\n // Update application properties\n const formValue = this.applicationForm.value;\n application.Name = formValue.name;\n application.Description = formValue.description || null;\n\n // Save application\n const saveResult = await application.Save();\n if (!saveResult) {\n throw new Error(application.LatestResult?.Message || 'Failed to save application');\n }\n\n // Save application entities if there are changes\n if (this.hasEntityChanges) {\n await this.saveApplicationEntities(application.ID);\n }\n\n this.result.emit({ action: 'save', application });\n\n } catch (error: unknown) {\n console.error('Error saving application:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async saveApplicationEntities(applicationId: string): Promise<void> {\n // Save or update each MJApplicationEntity record\n for (const config of this.applicationEntities) {\n if (config.isNew || config.hasChanges) {\n let appEntity: MJApplicationEntityEntity;\n\n if (config.isNew) {\n // Create new MJApplicationEntity\n appEntity = await this.metadata.GetEntityObject<MJApplicationEntityEntity>('MJ: Application Entities');\n appEntity.NewRecord();\n appEntity.ApplicationID = applicationId;\n appEntity.EntityID = config.entity.ID;\n } else if (config.applicationEntity) {\n // Update existing MJApplicationEntity\n appEntity = config.applicationEntity;\n } else {\n continue;\n }\n\n appEntity.Sequence = config.sequence;\n appEntity.DefaultForNewUser = config.defaultForNewUser;\n\n const saveResult = await appEntity.Save();\n if (!saveResult) {\n console.warn(`Failed to save MJApplicationEntity for ${config.entity.Name}:`, appEntity.LatestResult?.Message);\n }\n }\n }\n }\n\n public onCancel(): void {\n this.result.emit({ action: 'cancel' });\n }\n\n private markFormGroupTouched(formGroup: FormGroup): void {\n Object.keys(formGroup.controls).forEach(key => {\n const control = formGroup.get(key);\n control?.markAsTouched();\n });\n }\n}","@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\" role=\"presentation\">\n <div\n class=\"modal-dialog\"\n [class.fullscreen]=\"isFullscreen\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"application-dialog-title\"\n aria-describedby=\"application-dialog-description\"\n >\n <!-- Modal Header -->\n <div class=\"modal-header\" [class.create-mode]=\"!isEditMode\" [class.edit-mode]=\"isEditMode\">\n <div class=\"modal-header-content\">\n <h2 class=\"modal-title\" id=\"application-dialog-title\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!isEditMode\" [class.fa-layer-group]=\"isEditMode\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Edit Application' : 'Create New Application' }}\n </h2>\n <p class=\"modal-subtitle\" id=\"application-dialog-description\">\n {{ isEditMode ? 'Update application information and settings' : 'Add a new application to the system' }}\n </p>\n </div>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleFullscreen()\"\n [attr.aria-label]=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isFullscreen\" [class.fa-expand]=\"!isFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"modal-close\"\n (click)=\"onCancel()\"\n aria-label=\"Close dialog\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"applicationForm\" (ngSubmit)=\"onSubmit()\">\n <!-- Error Alert -->\n @if (error) {\n <div class=\"form-section\">\n <mj-alert Variant=\"error\" [Message]=\"error\" />\n </div>\n }\n\n <!-- Basic Information Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.basicInfo\" (ExpandedChange)=\"toggleSection('basicInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n Application Information\n </span>\n <span class=\"section-description\">Define the application's basic properties</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"form-field\">\n <label class=\"field-label required\" for=\"app-name\">Application Name</label>\n <input\n id=\"app-name\"\n type=\"text\"\n class=\"field-input\"\n formControlName=\"name\"\n placeholder=\"My Application\"\n [class.error]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n [attr.aria-invalid]=\"applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched\"\n aria-describedby=\"app-name-error\"\n />\n @if (applicationForm.get('name')?.invalid && applicationForm.get('name')?.touched) {\n <div class=\"field-error\" id=\"app-name-error\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-circle\" aria-hidden=\"true\"></i>\n @if (applicationForm.get('name')?.errors?.['required']) {\n Application name is required\n }\n @if (applicationForm.get('name')?.errors?.['maxlength']) {\n Application name cannot exceed 100 characters\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"app-description\">Description</label>\n <textarea\n id=\"app-description\"\n class=\"field-textarea\"\n formControlName=\"description\"\n placeholder=\"Describe the application's purpose and functionality...\"\n rows=\"4\"\n ></textarea>\n <div class=\"field-hint\">\n Provide a clear description of what this application does and its main features.\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- Entity Management Section -->\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.entities\" (ExpandedChange)=\"toggleSection('entities')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Application Entities\n </span>\n <span class=\"section-description\">Manage which entities are included in this application</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <!-- Assigned Entities -->\n @if (applicationEntities.length > 0) {\n <div class=\"assigned-entities\">\n <h4 class=\"subsection-title\">Assigned Entities ({{ applicationEntities.length }})</h4>\n <div class=\"entities-list\"\n role=\"list\"\n cdkDropList\n (cdkDropListDropped)=\"onEntityDrop($event)\">\n @for (config of applicationEntities; track config.entity.ID; let i = $index) {\n <div\n class=\"entity-item\"\n [class.is-new]=\"config.isNew\"\n [class.has-changes]=\"config.hasChanges\"\n role=\"listitem\"\n cdkDrag\n >\n <i class=\"fa-solid fa-grip-vertical drag-handle\" aria-hidden=\"true\"></i>\n <div class=\"entity-info\">\n <div class=\"entity-icon\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"entity-details\">\n <div class=\"entity-name\">\n {{ getEntityDisplayName(config.entity) }}\n @if (config.entity.Description) {\n <i\n class=\"fa-solid fa-info-circle entity-info-icon\"\n [title]=\"config.entity.Description\"\n [attr.aria-label]=\"'Entity description: ' + config.entity.Description\"\n ></i>\n }\n </div>\n </div>\n </div>\n\n <div class=\"entity-config\">\n <div class=\"config-item\">\n <label class=\"config-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"config.defaultForNewUser\"\n [ngModelOptions]=\"{standalone: true}\"\n (change)=\"onDefaultForNewUserChange(config)\"\n class=\"config-checkbox\"\n />\n <span class=\"checkbox-text\">Default for new users</span>\n </label>\n </div>\n <div class=\"sequence-badge\" [attr.aria-label]=\"'Sequence ' + config.sequence\">{{ config.sequence }}</div>\n </div>\n\n <div class=\"entity-actions\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeEntity(config)\"\n title=\"Remove entity\"\n [attr.aria-label]=\"'Remove ' + getEntityDisplayName(config.entity)\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else {\n <div class=\"no-entities\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n <p>No entities assigned to this application</p>\n <p class=\"empty-subtext\">Add entities from the available list below</p>\n </div>\n }\n\n <!-- Available Entities -->\n @if (availableEntities.length > 0) {\n <div class=\"available-entities\">\n <div class=\"available-entities-header\">\n <h4 class=\"subsection-title\">Available Entities ({{ filteredAvailableEntities.length }} of {{ availableEntities.length }})</h4>\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search entity-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"entity-search-input\"\n placeholder=\"Search entities...\"\n [value]=\"entitySearchTerm\"\n (input)=\"onEntitySearchChange($event)\"\n aria-label=\"Search available entities\"\n />\n @if (entitySearchTerm) {\n <button\n type=\"button\"\n class=\"entity-search-clear\"\n (click)=\"clearEntitySearch()\"\n aria-label=\"Clear search\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n @if (filteredAvailableEntities.length > 0) {\n <div class=\"entities-grid\" role=\"list\">\n @for (entity of filteredAvailableEntities; track entity.ID) {\n <button\n type=\"button\"\n class=\"entity-chip\"\n (click)=\"addEntity(entity)\"\n role=\"listitem\"\n [attr.aria-label]=\"'Add ' + getEntityDisplayName(entity)\"\n >\n <div class=\"chip-content\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"chip-name\">{{ getEntityDisplayName(entity) }}</span>\n </div>\n </button>\n }\n </div>\n } @else {\n <div class=\"no-search-results\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <p>No entities match \"{{ entitySearchTerm }}\"</p>\n </div>\n }\n </div>\n } @else {\n <div class=\"all-assigned\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <p>All entities have been assigned to this application</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n\n <!-- System Information Section (Edit Mode Only) -->\n @if (isEditMode) {\n <mj-accordion-panel class=\"app-dialog-section\" [Expanded]=\"sectionExpanded.systemInfo\" (ExpandedChange)=\"toggleSection('systemInfo')\">\n <ng-template mjAccordionTitle>\n <span class=\"app-dialog-section-title\">\n <span class=\"section-title\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n System Information\n </span>\n <span class=\"section-description\">Application metadata and audit information</span>\n </span>\n </ng-template>\n\n <div class=\"section-content\">\n <div class=\"form-grid\">\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Created</span>\n <span class=\"info-value\">{{ data?.application?.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Last Updated</span>\n <span class=\"info-value\">{{ data?.application?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Application ID</span>\n <span class=\"info-value\">{{ data?.application?.ID }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Total Entities</span>\n <span class=\"info-value\">{{ applicationEntities.length }}</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </form>\n </div>\n\n <!-- Modal Footer - Primary and Cancel buttons on RIGHT -->\n <div class=\"modal-footer\">\n <button\n type=\"submit\"\n mjButton variant=\"primary\"\n [disabled]=\"applicationForm.invalid || isLoading\"\n (click)=\"onSubmit()\"\n [attr.aria-busy]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n {{ isEditMode ? 'Update Application' : 'Create Application' }}\n }\n </button>\n <button type=\"button\" mjButton (click)=\"onCancel()\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { ChangeDetectorRef, NgZone, OnDestroy } from '@angular/core';
2
2
  import { Subject, BehaviorSubject } from 'rxjs';
3
+ import { EntityInfo } from '@memberjunction/core';
3
4
  import { MJApplicationEntity, MJApplicationEntityEntity, ResourceData } from '@memberjunction/core-entities';
4
5
  import { BaseDashboard } from '@memberjunction/ng-shared';
5
6
  import { FilterFieldConfig } from '@memberjunction/ng-ui-components';
@@ -63,7 +64,7 @@ export declare class ApplicationManagementComponent extends BaseDashboard implem
63
64
  toggleAppExpansion(appId: string): void;
64
65
  isAppExpanded(appId: string): boolean;
65
66
  getAppEntities(appId: string): MJApplicationEntityEntity[];
66
- getEntityInfo(entityId: string): any;
67
+ getEntityInfo(entityId: string): EntityInfo | undefined;
67
68
  createNewApplication(): void;
68
69
  editApplication(app: MJApplicationEntity): void;
69
70
  confirmDeleteApplication(app: MJApplicationEntity): void;
@@ -1 +1 @@
1
- {"version":3,"file":"application-management.component.d.ts","sourceRoot":"","sources":["../../../src/lib/application-management/application-management.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAa,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAGhD,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;;AAEnH,UAAU,QAAQ;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAOa,8BAA+B,SAAQ,aAAc,YAAW,SAAS;IAiCxE,OAAO,CAAC,GAAG;IAAqB,OAAO,CAAC,MAAM;IA/BnD,YAAY,EAAE,mBAAmB,EAAE,CAAM;IACzC,oBAAoB,EAAE,mBAAmB,EAAE,CAAM;IACjD,WAAW,EAAE,mBAAmB,GAAG,IAAI,CAAQ;IAC/C,SAAS,UAAS;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,yBAAyB,EAAE,CAAC,CAAa;IAGlE,KAAK,EAAE,QAAQ,CAKpB;IAGK,QAAQ,iCAGZ;IAGI,qBAAqB,UAAS;IAC9B,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAQ;IAC3D,iBAAiB,UAAS;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C,UAAmB,QAAQ,gBAAuB;IAClD,OAAO,KAAK,QAAQ,GAAiC;gBACjC,GAAG,EAAE,iBAAiB,EAAU,MAAM,EAAE,MAAM;IAI5D,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjE,SAAS,CAAC,aAAa,IAAI,IAAI;IAI/B,SAAS,CAAC,QAAQ,IAAI,IAAI;IAIjB,WAAW,IAAI,IAAI;IAMf,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;YA2B/B,gBAAgB;YAWhB,uBAAuB;IAWrC,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,cAAc;IAoBf,oBAAoB,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI;IAIjE,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAe1D,IAAW,YAAY,IAAI,iBAAiB,EAAE,CAa7C;IAED,IAAW,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjD;IAED,sEAAsE;IACtE,IAAW,sBAAsB,IAAI,MAAM,CAE1C;IAEM,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMjE,mDAAmD;IAC5C,sBAAsB,IAAI,IAAI;IAIrC;sDACkD;IAClD,IAAW,cAAc,IAAI,OAAO,CAEnC;IAED;;qEAEiE;IAC1D,wBAAwB,IAAI,IAAI;IAMhC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIrC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,yBAAyB,EAAE;IAI1D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;IAIpC,oBAAoB,IAAI,IAAI;IAO5B,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI;IAQ/C,wBAAwB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI;IAKlD,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxC,yBAAyB,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAUhE,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM;IAoD5C,iBAAiB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM;IAKnD,iBAAiB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM;IAKnD,WAAW,IAAI,IAAI;yCA3Xf,8BAA8B;2CAA9B,8BAA8B;CA8X1C"}
1
+ {"version":3,"file":"application-management.component.d.ts","sourceRoot":"","sources":["../../../src/lib/application-management/application-management.component.ts"],"names":[],"mappings":"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"}