@memberjunction/ng-entity-relationship-diagram 5.30.1 → 5.32.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 (40) hide show
  1. package/dist/__tests__/compute-erd-layout.test.d.ts +2 -0
  2. package/dist/__tests__/compute-erd-layout.test.d.ts.map +1 -0
  3. package/dist/__tests__/compute-erd-layout.test.js +207 -0
  4. package/dist/__tests__/compute-erd-layout.test.js.map +1 -0
  5. package/dist/lib/components/entity-details/entity-details.component.d.ts +2 -1
  6. package/dist/lib/components/entity-details/entity-details.component.d.ts.map +1 -1
  7. package/dist/lib/components/entity-details/entity-details.component.js +7 -7
  8. package/dist/lib/components/entity-details/entity-details.component.js.map +1 -1
  9. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts +10 -4
  10. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts.map +1 -1
  11. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js +60 -72
  12. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js.map +1 -1
  13. package/dist/lib/components/erd-composite/erd-composite.component.d.ts +4 -1
  14. package/dist/lib/components/erd-composite/erd-composite.component.d.ts.map +1 -1
  15. package/dist/lib/components/erd-composite/erd-composite.component.js +22 -8
  16. package/dist/lib/components/erd-composite/erd-composite.component.js.map +1 -1
  17. package/dist/lib/components/erd-diagram.component.d.ts +169 -443
  18. package/dist/lib/components/erd-diagram.component.d.ts.map +1 -1
  19. package/dist/lib/components/erd-diagram.component.js +916 -1777
  20. package/dist/lib/components/erd-diagram.component.js.map +1 -1
  21. package/dist/lib/components/mj-entity-erd.component.d.ts +3 -2
  22. package/dist/lib/components/mj-entity-erd.component.d.ts.map +1 -1
  23. package/dist/lib/components/mj-entity-erd.component.js +6 -6
  24. package/dist/lib/components/mj-entity-erd.component.js.map +1 -1
  25. package/dist/lib/entity-relationship-diagram.module.d.ts +2 -1
  26. package/dist/lib/entity-relationship-diagram.module.d.ts.map +1 -1
  27. package/dist/lib/entity-relationship-diagram.module.js +9 -3
  28. package/dist/lib/entity-relationship-diagram.module.js.map +1 -1
  29. package/dist/lib/interfaces/erd-types.d.ts +38 -7
  30. package/dist/lib/interfaces/erd-types.d.ts.map +1 -1
  31. package/dist/lib/interfaces/erd-types.js.map +1 -1
  32. package/dist/lib/layout/compute-dagre-layout.d.ts +32 -0
  33. package/dist/lib/layout/compute-dagre-layout.d.ts.map +1 -0
  34. package/dist/lib/layout/compute-dagre-layout.js +168 -0
  35. package/dist/lib/layout/compute-dagre-layout.js.map +1 -0
  36. package/dist/lib/layout/compute-erd-layout.d.ts +103 -0
  37. package/dist/lib/layout/compute-erd-layout.d.ts.map +1 -0
  38. package/dist/lib/layout/compute-erd-layout.js +254 -0
  39. package/dist/lib/layout/compute-erd-layout.js.map +1 -0
  40. package/package.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"file":"erd-composite.component.js","sourceRoot":"","sources":["../../../../src/lib/components/erd-composite/erd-composite.component.ts","../../../../src/lib/components/erd-composite/erd-composite.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ViewChild } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport { EntityInfo, EntityFieldInfo, Metadata } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJEntityERDComponent } from '../mj-entity-erd.component';\nimport { EntitySelectedEvent, OpenEntityRecordEvent } from '../mj-entity-erd.component';\nimport { ERDConfig, ERDState } from '../../interfaces/erd-types';\nimport { EntityFilter } from '../entity-filter-panel/entity-filter-panel.component';\n\n/**\n * State object for the ERD composite component.\n * Used for state persistence and restoration.\n */\nexport interface ERDCompositeState {\n filterPanelVisible: boolean;\n filterPanelWidth: number;\n filters: EntityFilter;\n selectedEntityId: string | null;\n zoomLevel: number;\n panPosition: { x: number; y: number };\n fieldsSectionExpanded: boolean;\n relationshipsSectionExpanded: boolean;\n}\n\n/**\n * ERD Composite component that combines the ERD diagram with filter and details panels.\n *\n * This is a complete, ready-to-use ERD exploration interface that includes:\n * - Left panel: Entity filter controls (schema, name, status, etc.)\n * - Center: Interactive ERD diagram\n * - Right panel: Entity details (shown when an entity is selected)\n *\n * The component handles all internal state but emits events for:\n * - State changes (for parent to persist user preferences)\n * - Open record requests (for parent to handle navigation)\n *\n * ## Usage\n *\n * ```html\n * <mj-erd-composite\n * (stateChange)=\"onStateChange($event)\"\n * (userStateChange)=\"saveUserPreferences($event)\"\n * (openRecord)=\"navigateToRecord($event)\">\n * </mj-erd-composite>\n * ```\n *\n * ## State Persistence\n *\n * The component emits `userStateChange` events (debounced 1s) when user changes\n * any settings. The parent should save this state and restore it using `loadUserState()`:\n *\n * ```typescript\n * @ViewChild(ERDCompositeComponent) erdComposite!: ERDCompositeComponent;\n *\n * ngAfterViewInit() {\n * const savedState = await this.loadSavedState();\n * if (savedState) {\n * this.erdComposite.loadUserState(savedState);\n * }\n * }\n *\n * onUserStateChange(state: ERDCompositeState) {\n * await this.saveState(state);\n * }\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-erd-composite',\n templateUrl: './erd-composite.component.html',\n styleUrls: ['./erd-composite.component.css']\n})\nexport class ERDCompositeComponent implements OnInit, OnDestroy {\n @ViewChild(MJEntityERDComponent) mjEntityErd!: MJEntityERDComponent;\n\n /** Whether the ERD is in a refreshing state */\n @Input() isRefreshingERD = false;\n\n /**\n * Optional: Focus entities to display in the ERD.\n * When provided, only these entities will be shown (useful for single-entity views).\n * When not provided, all entities from metadata are loaded.\n */\n @Input() focusEntities: EntityInfo[] | null = null;\n\n /**\n * Whether to show the filter panel on the left.\n * Set to false for focused/single-entity views.\n */\n @Input() showFilterPanel = true;\n\n /**\n * Depth of relationships to display.\n * 1 = only direct relationships, 2 = relationships of relationships, etc.\n */\n @Input() depth = 1;\n\n /**\n * Whether to show the ERD header bar.\n */\n @Input() showHeader = true;\n\n /** All entities loaded from metadata */\n public entities: EntityInfo[] = [];\n\n /** All entity fields (flattened from all entities) */\n public allEntityFields: EntityFieldInfo[] = [];\n\n /** Emitted on any state change (debounced 50ms) */\n @Output() stateChange = new EventEmitter<ERDCompositeState>();\n\n /** Emitted on user-initiated state changes (debounced 1s) for persistence */\n @Output() userStateChange = new EventEmitter<ERDCompositeState>();\n\n /** Emitted when an entity is opened (e.g., double-clicked in details panel) */\n @Output() entityOpened = new EventEmitter<EntityInfo>();\n\n /** Emitted when requesting to open an entity record (for navigation) */\n @Output() openRecord = new EventEmitter<{EntityName: string, RecordID: string}>();\n\n // Panel visibility and configuration\n public filterPanelVisible = true;\n public fieldsSectionExpanded = true;\n public relationshipsSectionExpanded = true;\n\n /** ERD configuration - skip animation for faster rendering */\n public erdConfig: ERDConfig = { skipAnimation: true };\n\n // Entity state\n public selectedEntity: EntityInfo | null = null;\n public filteredEntities: EntityInfo[] = [];\n public isDataLoaded = false;\n\n // Filters\n public filters: EntityFilter = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n\n // State management\n private stateChangeSubject = new Subject<ERDCompositeState>();\n private userStateChangeSubject = new Subject<ERDCompositeState>();\n private filterChangeSubject = new Subject<void>();\n\n async ngOnInit(): Promise<void> {\n // Initialize filter panel visibility based on input\n this.filterPanelVisible = this.showFilterPanel;\n\n this.setupStateManagement();\n await this.loadData();\n\n // Use focusEntities if provided, otherwise use all entities\n if (this.focusEntities && this.focusEntities.length > 0) {\n this.filteredEntities = [...this.focusEntities];\n } else {\n this.filteredEntities = [...this.entities];\n this.applyFilters();\n }\n\n this.isDataLoaded = true;\n\n // Notify parent that data is loaded and ready for state loading\n this.emitStateChange();\n }\n\n ngOnDestroy(): void {\n this.stateChangeSubject.complete();\n this.userStateChangeSubject.complete();\n this.filterChangeSubject.complete();\n }\n\n private async loadData(): Promise<void> {\n // Load entities from metadata (always needed for allEntityFields and relationship lookups)\n const md = new Metadata();\n this.entities = md.Entities;\n\n // Load all entity fields from entities\n this.allEntityFields = this.entities\n .map((entity) => {\n return entity.Fields;\n })\n .flat();\n }\n\n private setupStateManagement(): void {\n // State change emissions with debouncing\n this.stateChangeSubject.pipe(\n debounceTime(50)\n ).subscribe(state => {\n this.stateChange.emit(state);\n });\n\n this.userStateChangeSubject.pipe(\n debounceTime(1000)\n ).subscribe(state => {\n this.userStateChange.emit(state);\n });\n\n // Filter changes with debouncing\n this.filterChangeSubject.pipe(\n debounceTime(300)\n ).subscribe(() => {\n this.applyFilters();\n this.emitStateChange();\n this.emitUserStateChange();\n });\n }\n\n public onFilterChange(): void {\n this.filterChangeSubject.next();\n }\n\n public onFiltersChange(newFilters: EntityFilter): void {\n this.filters = { ...newFilters };\n this.onFilterChange();\n }\n\n public onResetFilters(): void {\n this.filters = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n this.onFilterChange();\n }\n\n public onToggleFilterPanel(): void {\n this.filterPanelVisible = !this.filterPanelVisible;\n\n // Trigger ERD resize when filter panel is toggled\n if (this.mjEntityErd) {\n this.mjEntityErd.triggerResize();\n }\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n public onEntityDeselected(): void {\n this.selectedEntity = null;\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n public onEntitySelected(entity: EntityInfo): void {\n this.selectedEntity = entity;\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n /**\n * Handle entity selection from the mj-entity-erd wrapper.\n * Updates internal state.\n */\n public onERDEntitySelected(event: EntitySelectedEvent): void {\n this.selectedEntity = event.entity;\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n /**\n * Handle open record from the mj-entity-erd wrapper (double-click).\n * Opens the entity record using the entity form.\n */\n public onERDOpenRecord(event: OpenEntityRecordEvent): void {\n this.openRecord.emit({ EntityName: event.EntityName, RecordID: event.RecordID });\n }\n\n /**\n * Handle state changes from the ERD component.\n */\n public onERDStateChange(_state: ERDState): void {\n // State changes are tracked for user preference persistence\n this.emitUserStateChange();\n }\n\n public onEntityOpened(entity: EntityInfo): void {\n this.entityOpened.emit(entity);\n }\n\n public onFieldsSectionToggle(): void {\n this.fieldsSectionExpanded = !this.fieldsSectionExpanded;\n this.emitUserStateChange();\n }\n\n public onRelationshipsSectionToggle(): void {\n this.relationshipsSectionExpanded = !this.relationshipsSectionExpanded;\n this.emitUserStateChange();\n }\n\n public onOpenRecord(event: {EntityName: string, RecordID: string}): void {\n this.openRecord.emit(event);\n }\n\n public onSplitterLayoutChange(_event: unknown): void {\n // Trigger ERD diagram resize when splitter layout changes\n if (this.mjEntityErd) {\n this.mjEntityErd.triggerResize();\n }\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n private applyFilters(): void {\n this.filteredEntities = this.entities.filter(entity => {\n // Schema filter\n if (this.filters.schemaName && entity.SchemaName !== this.filters.schemaName) {\n return false;\n }\n\n // Entity name filter\n if (this.filters.entityName) {\n const searchTerm = this.filters.entityName.toLowerCase();\n const entityName = (entity.Name || entity.SchemaName || '').toLowerCase();\n if (!entityName.includes(searchTerm)) {\n return false;\n }\n }\n\n // Base table filter\n if (this.filters.baseTable) {\n const searchTerm = this.filters.baseTable.toLowerCase();\n const baseTable = (entity.BaseTable || '').toLowerCase();\n if (!baseTable.includes(searchTerm)) {\n return false;\n }\n }\n\n // Status filter\n if (this.filters.entityStatus && entity.Status !== this.filters.entityStatus) {\n return false;\n }\n\n return true;\n });\n }\n\n private emitStateChange(): void {\n const state = this.buildState();\n this.stateChangeSubject.next(state);\n }\n\n private emitUserStateChange(): void {\n const state = this.buildState();\n this.userStateChangeSubject.next(state);\n }\n\n private buildState(): ERDCompositeState {\n return {\n filterPanelVisible: this.filterPanelVisible,\n filterPanelWidth: 320,\n filters: { ...this.filters },\n selectedEntityId: this.selectedEntity?.ID || null,\n zoomLevel: 1,\n panPosition: { x: 0, y: 0 },\n fieldsSectionExpanded: this.fieldsSectionExpanded,\n relationshipsSectionExpanded: this.relationshipsSectionExpanded,\n };\n }\n\n // ============================================================================\n // PUBLIC API\n // ============================================================================\n\n /**\n * Load user state from a previously saved state object.\n * Call this after the component is initialized to restore user preferences.\n */\n public loadUserState(state: Partial<ERDCompositeState>): void {\n if (state.filterPanelVisible !== undefined) {\n this.filterPanelVisible = state.filterPanelVisible;\n }\n if (state.filters) {\n this.filters = { ...state.filters };\n }\n if (state.fieldsSectionExpanded !== undefined) {\n this.fieldsSectionExpanded = state.fieldsSectionExpanded;\n }\n if (state.relationshipsSectionExpanded !== undefined) {\n this.relationshipsSectionExpanded = state.relationshipsSectionExpanded;\n }\n if (state.selectedEntityId && this.entities.length > 0) {\n const entity = this.entities.find(e => UUIDsEqual(e.ID, state.selectedEntityId));\n if (entity) {\n this.selectedEntity = entity;\n }\n } else {\n this.selectedEntity = null;\n }\n\n this.applyFilters();\n }\n\n /**\n * Refresh the ERD diagram.\n */\n public refreshERD(): void {\n if (this.mjEntityErd) {\n this.mjEntityErd.refresh();\n }\n }\n\n /**\n * Get the current state for external use.\n */\n public getState(): ERDCompositeState {\n return this.buildState();\n }\n}\n","<div class=\"erd-composite\">\n <as-split direction=\"horizontal\" (dragEnd)=\"onSplitterLayoutChange($event)\">\n\n <!-- Filter Panel (Left) -->\n @if (filterPanelVisible) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-filter-panel\n [entities]=\"entities\"\n [filteredEntities]=\"filteredEntities\"\n [filters]=\"filters\"\n (filtersChange)=\"onFiltersChange($event)\"\n (filterChange)=\"onFilterChange()\"\n (resetFilters)=\"onResetFilters()\"\n (closePanel)=\"onToggleFilterPanel()\">\n </mj-entity-filter-panel>\n </as-split-area>\n }\n\n <!-- ERD Diagram (Center) -->\n <as-split-area [size]=\"selectedEntity ? 60 : (filterPanelVisible ? 80 : 100)\">\n <div class=\"erd-pane-container\">\n <mj-entity-erd\n [entities]=\"filteredEntities\"\n [allEntities]=\"entities\"\n [selectedEntityId]=\"selectedEntity?.ID || null\"\n [isRefreshing]=\"isRefreshingERD\"\n [depth]=\"depth\"\n [includeIncoming]=\"true\"\n [includeOutgoing]=\"true\"\n [showHeader]=\"showHeader\"\n [config]=\"erdConfig\"\n headerTitle=\"Entity Relationship Diagram\"\n (entitySelected)=\"onERDEntitySelected($event)\"\n (entityDeselected)=\"onEntityDeselected()\"\n (openRecord)=\"onERDOpenRecord($event)\"\n (stateChange)=\"onERDStateChange($event)\">\n </mj-entity-erd>\n </div>\n </as-split-area>\n\n <!-- Entity Details Panel (Right) -->\n @if (selectedEntity) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-details\n [selectedEntity]=\"selectedEntity\"\n [allEntityFields]=\"allEntityFields\"\n [fieldsSectionExpanded]=\"fieldsSectionExpanded\"\n [relationshipsSectionExpanded]=\"relationshipsSectionExpanded\"\n (openEntity)=\"onEntityOpened($event)\"\n (closePanel)=\"onEntityDeselected()\"\n (fieldsSectionToggle)=\"onFieldsSectionToggle()\"\n (relationshipsSectionToggle)=\"onRelationshipsSectionToggle()\"\n (entitySelected)=\"onEntitySelected($event)\"\n (openRecord)=\"onOpenRecord($event)\">\n </mj-entity-details>\n </as-split-area>\n }\n </as-split>\n</div>\n"]}
1
+ {"version":3,"file":"erd-composite.component.js","sourceRoot":"","sources":["../../../../src/lib/components/erd-composite/erd-composite.component.ts","../../../../src/lib/components/erd-composite/erd-composite.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ViewChild } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport { EntityInfo, EntityFieldInfo } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MJEntityERDComponent } from '../mj-entity-erd.component';\nimport { EntitySelectedEvent, OpenEntityRecordEvent } from '../mj-entity-erd.component';\nimport { ERDConfig, ERDState } from '../../interfaces/erd-types';\nimport { EntityFilter } from '../entity-filter-panel/entity-filter-panel.component';\n\n/**\n * State object for the ERD composite component.\n * Used for state persistence and restoration.\n */\nexport interface ERDCompositeState {\n filterPanelVisible: boolean;\n filterPanelWidth: number;\n filters: EntityFilter;\n selectedEntityId: string | null;\n zoomLevel: number;\n panPosition: { x: number; y: number };\n fieldsSectionExpanded: boolean;\n relationshipsSectionExpanded: boolean;\n /** User's preferred layout algorithm — 'schema-grid' (default) or 'dagre'. */\n layoutAlgorithm?: 'schema-grid' | 'dagre';\n}\n\n/**\n * ERD Composite component that combines the ERD diagram with filter and details panels.\n *\n * This is a complete, ready-to-use ERD exploration interface that includes:\n * - Left panel: Entity filter controls (schema, name, status, etc.)\n * - Center: Interactive ERD diagram\n * - Right panel: Entity details (shown when an entity is selected)\n *\n * The component handles all internal state but emits events for:\n * - State changes (for parent to persist user preferences)\n * - Open record requests (for parent to handle navigation)\n *\n * ## Usage\n *\n * ```html\n * <mj-erd-composite\n * (stateChange)=\"onStateChange($event)\"\n * (userStateChange)=\"saveUserPreferences($event)\"\n * (openRecord)=\"navigateToRecord($event)\">\n * </mj-erd-composite>\n * ```\n *\n * ## State Persistence\n *\n * The component emits `userStateChange` events (debounced 1s) when user changes\n * any settings. The parent should save this state and restore it using `loadUserState()`:\n *\n * ```typescript\n * @ViewChild(ERDCompositeComponent) erdComposite!: ERDCompositeComponent;\n *\n * ngAfterViewInit() {\n * const savedState = await this.loadSavedState();\n * if (savedState) {\n * this.erdComposite.loadUserState(savedState);\n * }\n * }\n *\n * onUserStateChange(state: ERDCompositeState) {\n * await this.saveState(state);\n * }\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-erd-composite',\n templateUrl: './erd-composite.component.html',\n styleUrls: ['./erd-composite.component.css']\n})\nexport class ERDCompositeComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @ViewChild(MJEntityERDComponent) mjEntityErd!: MJEntityERDComponent;\n\n /** Whether the ERD is in a refreshing state */\n @Input() isRefreshingERD = false;\n\n /**\n * Optional: Focus entities to display in the ERD.\n * When provided, only these entities will be shown (useful for single-entity views).\n * When not provided, all entities from metadata are loaded.\n */\n @Input() focusEntities: EntityInfo[] | null = null;\n\n /**\n * Whether to show the filter panel on the left.\n * Set to false for focused/single-entity views.\n */\n @Input() showFilterPanel = true;\n\n /**\n * Depth of relationships to display.\n * 1 = only direct relationships, 2 = relationships of relationships, etc.\n */\n @Input() depth = 1;\n\n /**\n * Whether to show the ERD header bar.\n */\n @Input() showHeader = true;\n\n /** All entities loaded from metadata */\n public entities: EntityInfo[] = [];\n\n /** All entity fields (flattened from all entities) */\n public allEntityFields: EntityFieldInfo[] = [];\n\n /** Emitted on any state change (debounced 50ms) */\n @Output() stateChange = new EventEmitter<ERDCompositeState>();\n\n /** Emitted on user-initiated state changes (debounced 1s) for persistence */\n @Output() userStateChange = new EventEmitter<ERDCompositeState>();\n\n /** Emitted when an entity is opened (e.g., double-clicked in details panel) */\n @Output() entityOpened = new EventEmitter<EntityInfo>();\n\n /** Emitted when requesting to open an entity record (for navigation) */\n @Output() openRecord = new EventEmitter<{EntityName: string, RecordID: string}>();\n\n // Panel visibility and configuration\n public filterPanelVisible = true;\n public fieldsSectionExpanded = true;\n public relationshipsSectionExpanded = true;\n\n /** ERD configuration - skip animation for faster rendering */\n public erdConfig: ERDConfig = { skipAnimation: true };\n\n // Entity state\n public selectedEntity: EntityInfo | null = null;\n public filteredEntities: EntityInfo[] = [];\n public isDataLoaded = false;\n\n // Filters\n public filters: EntityFilter = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n\n // State management\n private stateChangeSubject = new Subject<ERDCompositeState>();\n private userStateChangeSubject = new Subject<ERDCompositeState>();\n private filterChangeSubject = new Subject<void>();\n\n async ngOnInit(): Promise<void> {\n // Initialize filter panel visibility based on input\n this.filterPanelVisible = this.showFilterPanel;\n\n this.setupStateManagement();\n await this.loadData();\n\n // Use focusEntities if provided, otherwise use all entities\n if (this.focusEntities && this.focusEntities.length > 0) {\n this.filteredEntities = [...this.focusEntities];\n } else {\n this.filteredEntities = [...this.entities];\n this.applyFilters();\n }\n\n this.isDataLoaded = true;\n\n // Notify parent that data is loaded and ready for state loading\n this.emitStateChange();\n }\n\n ngOnDestroy(): void {\n this.stateChangeSubject.complete();\n this.userStateChangeSubject.complete();\n this.filterChangeSubject.complete();\n }\n\n private async loadData(): Promise<void> {\n // Load entities from metadata (always needed for allEntityFields and relationship lookups)\n const md = this.ProviderToUse;\n this.entities = md.Entities;\n\n // Load all entity fields from entities\n this.allEntityFields = this.entities\n .map((entity) => {\n return entity.Fields;\n })\n .flat();\n }\n\n private setupStateManagement(): void {\n // State change emissions with debouncing\n this.stateChangeSubject.pipe(\n debounceTime(50)\n ).subscribe(state => {\n this.stateChange.emit(state);\n });\n\n this.userStateChangeSubject.pipe(\n debounceTime(1000)\n ).subscribe(state => {\n this.userStateChange.emit(state);\n });\n\n // Filter changes with debouncing\n this.filterChangeSubject.pipe(\n debounceTime(300)\n ).subscribe(() => {\n this.applyFilters();\n this.emitStateChange();\n this.emitUserStateChange();\n });\n }\n\n public onFilterChange(): void {\n this.filterChangeSubject.next();\n }\n\n public onFiltersChange(newFilters: EntityFilter): void {\n this.filters = { ...newFilters };\n this.onFilterChange();\n }\n\n public onResetFilters(): void {\n this.filters = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n this.onFilterChange();\n }\n\n public onToggleFilterPanel(): void {\n this.filterPanelVisible = !this.filterPanelVisible;\n\n // Trigger ERD resize when filter panel is toggled\n if (this.mjEntityErd) {\n this.mjEntityErd.triggerResize();\n }\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n public onEntityDeselected(): void {\n this.selectedEntity = null;\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n public onEntitySelected(entity: EntityInfo): void {\n this.selectedEntity = entity;\n\n // Bring the entity into view in the diagram and emit nodeSelected\n // upstream so the focus + highlight logic kicks in. Done in a\n // microtask so the [focusEntityId] binding flushes first and the\n // inner diagram has the new focus state when we ask it to center.\n queueMicrotask(() => {\n this.mjEntityErd?.zoomToEntity(entity.ID);\n });\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n /**\n * Handle entity selection from the mj-entity-erd wrapper.\n * Updates internal state.\n */\n public onERDEntitySelected(event: EntitySelectedEvent): void {\n this.selectedEntity = event.entity;\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n /**\n * Handle open record from the mj-entity-erd wrapper (double-click).\n * Opens the entity record using the entity form.\n */\n public onERDOpenRecord(event: OpenEntityRecordEvent): void {\n this.openRecord.emit({ EntityName: event.EntityName, RecordID: event.RecordID });\n }\n\n /**\n * Handle state changes from the ERD component.\n */\n public onERDStateChange(_state: ERDState): void {\n // State changes are tracked for user preference persistence\n this.emitUserStateChange();\n }\n\n public onEntityOpened(entity: EntityInfo): void {\n this.entityOpened.emit(entity);\n }\n\n public onFieldsSectionToggle(): void {\n this.fieldsSectionExpanded = !this.fieldsSectionExpanded;\n this.emitUserStateChange();\n }\n\n public onRelationshipsSectionToggle(): void {\n this.relationshipsSectionExpanded = !this.relationshipsSectionExpanded;\n this.emitUserStateChange();\n }\n\n public onOpenRecord(event: {EntityName: string, RecordID: string}): void {\n this.openRecord.emit(event);\n }\n\n public onSplitterLayoutChange(_event: unknown): void {\n // Trigger ERD diagram resize when splitter layout changes\n if (this.mjEntityErd) {\n this.mjEntityErd.triggerResize();\n }\n\n this.emitStateChange();\n this.emitUserStateChange();\n }\n\n private applyFilters(): void {\n this.filteredEntities = this.entities.filter(entity => {\n // Schema filter\n if (this.filters.schemaName && entity.SchemaName !== this.filters.schemaName) {\n return false;\n }\n\n // Entity name filter\n if (this.filters.entityName) {\n const searchTerm = this.filters.entityName.toLowerCase();\n const entityName = (entity.Name || entity.SchemaName || '').toLowerCase();\n if (!entityName.includes(searchTerm)) {\n return false;\n }\n }\n\n // Base table filter\n if (this.filters.baseTable) {\n const searchTerm = this.filters.baseTable.toLowerCase();\n const baseTable = (entity.BaseTable || '').toLowerCase();\n if (!baseTable.includes(searchTerm)) {\n return false;\n }\n }\n\n // Status filter\n if (this.filters.entityStatus && entity.Status !== this.filters.entityStatus) {\n return false;\n }\n\n return true;\n });\n }\n\n private emitStateChange(): void {\n const state = this.buildState();\n this.stateChangeSubject.next(state);\n }\n\n private emitUserStateChange(): void {\n const state = this.buildState();\n this.userStateChangeSubject.next(state);\n }\n\n private buildState(): ERDCompositeState {\n return {\n filterPanelVisible: this.filterPanelVisible,\n filterPanelWidth: 320,\n filters: { ...this.filters },\n selectedEntityId: this.selectedEntity?.ID || null,\n zoomLevel: 1,\n panPosition: { x: 0, y: 0 },\n fieldsSectionExpanded: this.fieldsSectionExpanded,\n relationshipsSectionExpanded: this.relationshipsSectionExpanded,\n layoutAlgorithm: this.mjEntityErd?.erdDiagram?.activeLayout ?? 'schema-grid',\n };\n }\n\n // ============================================================================\n // PUBLIC API\n // ============================================================================\n\n /**\n * Load user state from a previously saved state object.\n * Call this after the component is initialized to restore user preferences.\n */\n public loadUserState(state: Partial<ERDCompositeState>): void {\n if (state.filterPanelVisible !== undefined) {\n this.filterPanelVisible = state.filterPanelVisible;\n }\n if (state.filters) {\n this.filters = { ...state.filters };\n }\n if (state.fieldsSectionExpanded !== undefined) {\n this.fieldsSectionExpanded = state.fieldsSectionExpanded;\n }\n if (state.relationshipsSectionExpanded !== undefined) {\n this.relationshipsSectionExpanded = state.relationshipsSectionExpanded;\n }\n if (state.selectedEntityId && this.entities.length > 0) {\n const entity = this.entities.find(e => UUIDsEqual(e.ID, state.selectedEntityId));\n if (entity) {\n this.selectedEntity = entity;\n }\n } else {\n this.selectedEntity = null;\n }\n\n // Restore preferred layout algorithm. Deferred to microtask so the\n // diagram has mounted by the time we set it.\n if (state.layoutAlgorithm) {\n const algo = state.layoutAlgorithm;\n queueMicrotask(() => this.mjEntityErd?.erdDiagram?.setLayoutAlgorithm(algo));\n }\n\n this.applyFilters();\n }\n\n /**\n * Refresh the ERD diagram.\n */\n public refreshERD(): void {\n if (this.mjEntityErd) {\n this.mjEntityErd.refresh();\n }\n }\n\n /**\n * Get the current state for external use.\n */\n public getState(): ERDCompositeState {\n return this.buildState();\n }\n}\n","<div class=\"erd-composite\">\n <as-split direction=\"horizontal\" (dragEnd)=\"onSplitterLayoutChange($event)\">\n\n <!-- Filter Panel (Left) -->\n @if (filterPanelVisible) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-filter-panel\n [entities]=\"entities\"\n [filteredEntities]=\"filteredEntities\"\n [filters]=\"filters\"\n (filtersChange)=\"onFiltersChange($event)\"\n (filterChange)=\"onFilterChange()\"\n (resetFilters)=\"onResetFilters()\"\n (closePanel)=\"onToggleFilterPanel()\">\n </mj-entity-filter-panel>\n </as-split-area>\n }\n\n <!-- ERD Diagram (Center) -->\n <as-split-area [size]=\"selectedEntity ? 60 : (filterPanelVisible ? 80 : 100)\">\n <div class=\"erd-pane-container\">\n <mj-entity-erd\n [entities]=\"filteredEntities\"\n [allEntities]=\"entities\"\n [selectedEntityId]=\"selectedEntity?.ID || null\"\n [focusEntityId]=\"selectedEntity?.ID || null\"\n [isRefreshing]=\"isRefreshingERD\"\n [depth]=\"depth\"\n [includeIncoming]=\"true\"\n [includeOutgoing]=\"true\"\n [showHeader]=\"showHeader\"\n [config]=\"erdConfig\"\n headerTitle=\"Entity Relationship Diagram\"\n (entitySelected)=\"onERDEntitySelected($event)\"\n (entityDeselected)=\"onEntityDeselected()\"\n (openRecord)=\"onERDOpenRecord($event)\"\n (stateChange)=\"onERDStateChange($event)\">\n </mj-entity-erd>\n </div>\n </as-split-area>\n\n <!-- Entity Details Panel (Right) -->\n @if (selectedEntity) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-details\n [selectedEntity]=\"selectedEntity\"\n [allEntityFields]=\"allEntityFields\"\n [fieldsSectionExpanded]=\"fieldsSectionExpanded\"\n [relationshipsSectionExpanded]=\"relationshipsSectionExpanded\"\n (openEntity)=\"onEntityOpened($event)\"\n (closePanel)=\"onEntityDeselected()\"\n (fieldsSectionToggle)=\"onFieldsSectionToggle()\"\n (relationshipsSectionToggle)=\"onRelationshipsSectionToggle()\"\n (entitySelected)=\"onEntitySelected($event)\"\n (openRecord)=\"onOpenRecord($event)\">\n </mj-entity-details>\n </as-split-area>\n }\n </as-split>\n</div>\n"]}