@memberjunction/ng-list-detail-grid 5.34.1 → 5.36.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ng-list-detail-grid.component.d.ts","sourceRoot":"","sources":["../../src/lib/ng-list-detail-grid.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-list-detail-grid.component.d.ts","sourceRoot":"","sources":["../../src/lib/ng-list-detail-grid.component.ts"],"names":[],"mappings":"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"}
@@ -216,11 +216,18 @@ export class ListDetailGridComponent extends BaseAngularComponent {
216
216
  // Uses the primary key field(s) of the entity and the schema from List Details entity
217
217
  const schema = listDetailsEntityInfo.SchemaName;
218
218
  const extraFilter = this.buildListFilter(entityInfo, schema, list.ID);
219
- // Create the RunViewParams for the grid
219
+ // The grid filter is a cross-entity subquery into `vwListDetails`
220
+ // (`ID IN (SELECT RecordID FROM vwListDetails WHERE ListID='…')`).
221
+ // The server's RunView cache fingerprints by the OUTER entity, so a
222
+ // mutation on `MJ: List Details` doesn't invalidate this query's
223
+ // cached result — the grid would otherwise serve stale rows until a
224
+ // server restart. `BypassCache: true` makes the server skip both
225
+ // the cache lookup and the write for this query.
220
226
  this.gridParams = {
221
227
  EntityName: entityInfo.Name,
222
228
  ExtraFilter: extraFilter,
223
- ResultType: 'entity_object'
229
+ ResultType: 'entity_object',
230
+ BypassCache: true
224
231
  };
225
232
  this.listLoaded = true;
226
233
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ng-list-detail-grid.component.js","sourceRoot":"","sources":["../../src/lib/ng-list-detail-grid.component.ts","../../src/lib/ng-list-detail-grid.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ViewChild\n} from '@angular/core';\nimport { Metadata, EntityInfo, CompositeKey, BaseEntity, RunViewParams } from '@memberjunction/core';\nimport { MJListEntity } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport {\n AfterRowClickEventArgs,\n AfterRowDoubleClickEventArgs,\n AfterDataLoadEventArgs,\n GridToolbarConfig,\n GridSelectionMode,\n EntityDataGridComponent\n} from '@memberjunction/ng-entity-viewer';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n/**\n * Event emitted when a row is clicked in the list detail grid\n */\nexport interface ListGridRowClickedEvent {\n entityId: string;\n entityName: string;\n compositeKey: CompositeKey;\n record: Record<string, unknown>;\n}\n\n/**\n * ListDetailGridComponent - Displays records from a List using mj-entity-data-grid\n *\n * This component wraps the modern mj-entity-data-grid component to display\n * records that belong to a specific List. It uses a subquery filter to fetch\n * only records whose IDs are in the List Details for the given ListID.\n *\n * @example\n * ```html\n * <mj-list-detail-grid\n * [listId]=\"selectedList.ID\"\n * [autoNavigate]=\"true\"\n * (rowClicked)=\"onRecordSelected($event)\">\n * </mj-list-detail-grid>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-list-detail-grid',\n templateUrl: './ng-list-detail-grid.component.html',\n styleUrls: ['./ng-list-detail-grid.component.css']\n})\nexport class ListDetailGridComponent extends BaseAngularComponent implements OnInit, OnChanges {\n /**\n * The List ID to display records for.\n * When set, the component loads the list entity and builds a filter\n * to show only records that are in this list.\n */\n @Input() listId: string | null = null;\n\n /**\n * Optional: The List entity object if already loaded.\n * If provided, avoids an extra database call to load the list.\n */\n @Input() listEntity: MJListEntity | null = null;\n\n /**\n * Whether to auto-navigate to the record when double-clicked.\n * Defaults to true.\n */\n @Input() autoNavigate: boolean = true;\n\n /**\n * Height of the grid. Can be a number (pixels), 'auto', or 'fit-content'.\n * Defaults to 'auto'.\n */\n @Input() height: number | 'auto' | 'fit-content' = 'auto';\n\n /**\n * Show the grid toolbar.\n * Defaults to true.\n */\n @Input() showToolbar: boolean = true;\n\n /**\n * Selection mode for the grid.\n * Defaults to 'single'.\n */\n @Input() selectionMode: GridSelectionMode = 'single';\n\n /**\n * Emitted when a row is clicked (single click).\n */\n @Output() rowClicked = new EventEmitter<ListGridRowClickedEvent>();\n\n /**\n * Emitted when a row is double-clicked.\n */\n @Output() rowDoubleClicked = new EventEmitter<ListGridRowClickedEvent>();\n\n /**\n * Emitted when the grid data is loaded.\n */\n @Output() dataLoaded = new EventEmitter<{ totalCount: number }>();\n\n /**\n * Emitted when row selection changes (for checkbox mode).\n */\n @Output() selectionChange = new EventEmitter<string[]>();\n\n /**\n * Custom toolbar configuration. If not provided, uses default.\n */\n @Input() toolbarConfig: GridToolbarConfig | null = null;\n\n // ViewChild to access the underlying EDG component\n @ViewChild('entityDataGrid') entityDataGrid: EntityDataGridComponent | undefined;\n\n // Internal state\n entityInfo: EntityInfo | null = null;\n gridParams: RunViewParams | null = null;\n isLoading: boolean = false;\n listLoaded: boolean = false;\n selectedKeys: string[] = [];\n totalRowCount: number = 0;\n\n // Default toolbar configuration - minimal for list display\n private defaultToolbarConfig: GridToolbarConfig = {\n showSearch: true,\n showRefresh: true,\n showAdd: false,\n showDelete: false,\n showExport: true,\n showRowCount: true,\n showSelectionCount: true\n };\n\n /**\n * Get the effective toolbar config (custom or default)\n */\n get effectiveToolbarConfig(): GridToolbarConfig {\n return this.toolbarConfig || this.defaultToolbarConfig;\n }\n\n constructor(\n private sharedService: SharedService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnInit(): void {\n if (this.listId || this.listEntity) {\n this.loadList();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['listId'] || changes['listEntity']) {\n this.loadList();\n }\n }\n\n /**\n * Build the SQL filter to select records that are in the given list.\n * For single PK entities, uses a simple IN clause.\n * For composite PK entities, uses a JOIN that concatenates PK columns to match the RecordID format.\n */\n private buildListFilter(entityInfo: EntityInfo, listDetailsSchema: string, listId: string): string {\n const primaryKeys = entityInfo.PrimaryKeys;\n\n if (primaryKeys.length === 1) {\n // Simple case: single primary key\n // Use a simple IN clause matching the first PK field\n const pkField = primaryKeys[0].Name;\n return `${pkField} IN (SELECT RecordID FROM ${listDetailsSchema}.vwListDetails WHERE ListID = '${listId}')`;\n } else {\n // Composite key case: need to JOIN and match concatenated key format\n // RecordID format is \"Field1|Value1||Field2|Value2\" (using CompositeKey delimiters)\n // Build SQL expression that concatenates the PK fields in the same format\n // Build the concatenation expression for the entity's PK columns\n // Format: Field1 + '|' + CAST(Value1 AS NVARCHAR(MAX)) + '||' + Field2 + '|' + CAST(Value2 AS NVARCHAR(MAX))\n const concatParts = primaryKeys.map((pk, index) => {\n const fieldNameLiteral = `'${pk.Name}|'`;\n const fieldValue = `CAST([${pk.Name}] AS NVARCHAR(MAX))`;\n if (index === 0) {\n return `${fieldNameLiteral} + ${fieldValue}`;\n } else {\n return `'||' + ${fieldNameLiteral} + ${fieldValue}`;\n }\n });\n const compositeKeyExpr = concatParts.join(' + ');\n\n // Use EXISTS with a subquery that matches the concatenated key against RecordID\n return `EXISTS (\n SELECT 1 FROM ${listDetailsSchema}.vwListDetails ld\n WHERE ld.ListID = '${listId}'\n AND ld.RecordID = (${compositeKeyExpr})\n )`;\n }\n }\n\n /**\n * Load the list entity and set up the grid params with filter\n */\n private async loadList(): Promise<void> {\n // Reset state\n this.listLoaded = false;\n this.gridParams = null;\n\n if (!this.listId && !this.listEntity) {\n return;\n }\n\n this.isLoading = true;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n let list: MJListEntity | null = this.listEntity;\n\n // Load the list entity if not provided\n if (!list && this.listId) {\n list = await md.GetEntityObject<MJListEntity>('MJ: Lists');\n await list.Load(this.listId);\n }\n\n if (!list) {\n console.error('Failed to load list');\n return;\n }\n\n // Get the entity info for this list\n const entityInfo = md.EntityByID(list.EntityID);\n if (!entityInfo) {\n console.error(`Entity not found for ID: ${list.EntityID}`);\n return;\n }\n\n this.entityInfo = entityInfo;\n\n // Get the List Details entity info to get the correct schema name\n const listDetailsEntityInfo = md.EntityByName('MJ: List Details');\n if (!listDetailsEntityInfo) {\n console.error('List Details entity not found in metadata');\n return;\n }\n\n // Build the subquery filter to get records in this list\n // Uses the primary key field(s) of the entity and the schema from List Details entity\n const schema = listDetailsEntityInfo.SchemaName;\n const extraFilter = this.buildListFilter(entityInfo, schema, list.ID);\n\n // Create the RunViewParams for the grid\n this.gridParams = {\n EntityName: entityInfo.Name,\n ExtraFilter: extraFilter,\n ResultType: 'entity_object'\n };\n\n this.listLoaded = true;\n } catch (error) {\n console.error('Error loading list:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handle row click event from the grid\n */\n onRowClick(event: AfterRowClickEventArgs): void {\n if (!this.entityInfo || !event.row) return;\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(this.entityInfo, event.row);\n\n this.rowClicked.emit({\n entityId: this.entityInfo.ID,\n entityName: this.entityInfo.Name,\n compositeKey,\n record: event.row\n });\n }\n\n /**\n * Handle row double-click event from the grid\n */\n onRowDoubleClick(event: AfterRowDoubleClickEventArgs): void {\n if (!this.entityInfo || !event.row) return;\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(this.entityInfo, event.row);\n\n this.rowDoubleClicked.emit({\n entityId: this.entityInfo.ID,\n entityName: this.entityInfo.Name,\n compositeKey,\n record: event.row\n });\n\n // Auto-navigate if enabled - use SharedService for proper tab-based navigation\n if (this.autoNavigate) {\n this.sharedService.OpenEntityRecord(this.entityInfo.Name, compositeKey);\n }\n }\n\n /**\n * Handle data loaded event from the grid\n */\n onDataLoaded(event: AfterDataLoadEventArgs): void {\n this.totalRowCount = event.totalRowCount;\n this.dataLoaded.emit({ totalCount: event.totalRowCount });\n }\n\n /**\n * Handle selection change from the grid\n */\n onSelectionChange(keys: string[]): void {\n this.selectedKeys = keys;\n this.selectionChange.emit(keys);\n }\n\n /**\n * Refresh the grid data\n */\n refresh(): void {\n // Re-trigger load to refresh data\n this.loadList();\n }\n\n /**\n * Get the currently selected entity objects\n */\n getSelectedRows(): Record<string, unknown>[] {\n if (this.entityDataGrid) {\n return this.entityDataGrid.GetSelectedRows();\n }\n return [];\n }\n\n /**\n * Clear all selections\n */\n clearSelection(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.ClearSelection();\n }\n this.selectedKeys = [];\n }\n\n /**\n * Select specific rows by key\n */\n selectRows(keys: string[], additive: boolean = false): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.SelectRows(keys, additive);\n }\n }\n\n /**\n * Select all rows\n */\n selectAll(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.SelectAll();\n }\n }\n\n /**\n * Get the total row count\n */\n get rowCount(): number {\n return this.totalRowCount;\n }\n\n /**\n * Get the selected row count\n */\n get selectedCount(): number {\n return this.selectedKeys.length;\n }\n\n /**\n * Trigger the export dialog\n */\n export(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.onExportClick();\n }\n }\n}\n","<div class=\"list-detail-grid-container\">\n <!-- Loading state while list is being loaded -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading list...\"></mj-loading>\n </div>\n }\n\n <!-- Empty state when no list is selected -->\n @if (!isLoading && !listLoaded && !listId && !listEntity) {\n <div class=\"empty-state\">\n <span class=\"fa-solid fa-rectangle-list empty-icon\"></span>\n <p>Select a list to view its records</p>\n </div>\n }\n\n <!-- Grid display when list is loaded -->\n @if (listLoaded && gridParams) {\n <mj-entity-data-grid\n #entityDataGrid\n [Params]=\"gridParams\"\n [Height]=\"height\"\n [ShowToolbar]=\"showToolbar\"\n [ToolbarConfig]=\"effectiveToolbarConfig\"\n [SelectionMode]=\"selectionMode\"\n (AfterRowClick)=\"onRowClick($event)\"\n (AfterRowDoubleClick)=\"onRowDoubleClick($event)\"\n (AfterDataLoad)=\"onDataLoaded($event)\"\n (SelectionChange)=\"onSelectionChange($event)\">\n </mj-entity-data-grid>\n }\n</div>\n"]}
1
+ {"version":3,"file":"ng-list-detail-grid.component.js","sourceRoot":"","sources":["../../src/lib/ng-list-detail-grid.component.ts","../../src/lib/ng-list-detail-grid.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EAKZ,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAwB,YAAY,EAA6B,MAAM,sBAAsB,CAAC;AAYrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;;;;;;ICpBjE,8BAA+B;IAC7B,gCAAgD;IAClD,iBAAM;;;IAKN,8BAAyB;IACvB,0BAA2D;IAC3D,yBAAG;IAAA,iDAAiC;IACtC,AADsC,iBAAI,EACpC;;;;IAKN,iDAUgD;IAA9C,AADA,AADA,AADA,8NAAiB,yBAAkB,KAAC,6NACb,+BAAwB,KAAC,iNAC/B,2BAAoB,KAAC,qNACnB,gCAAyB,KAAC;IAC/C,iBAAsB;;;IALpB,AADA,AADA,AADA,AADA,0CAAqB,yBACJ,mCACU,gDACa,uCACT;;ADUrC;;;;;;;;;;;;;;;GAeG;AAOH,MAAM,OAAO,uBAAwB,SAAQ,oBAAoB;IA6FrD;IACA;IA7FV;;;;OAIG;IACM,MAAM,GAAkB,IAAI,CAAC;IAEtC;;;OAGG;IACM,UAAU,GAAwB,IAAI,CAAC;IAEhD;;;OAGG;IACM,YAAY,GAAY,IAAI,CAAC;IAEtC;;;OAGG;IACM,MAAM,GAAoC,MAAM,CAAC;IAE1D;;;OAGG;IACM,WAAW,GAAY,IAAI,CAAC;IAErC;;;OAGG;IACM,aAAa,GAAsB,QAAQ,CAAC;IAErD;;OAEG;IACO,UAAU,GAAG,IAAI,YAAY,EAA2B,CAAC;IAEnE;;OAEG;IACO,gBAAgB,GAAG,IAAI,YAAY,EAA2B,CAAC;IAEzE;;OAEG;IACO,UAAU,GAAG,IAAI,YAAY,EAA0B,CAAC;IAElE;;OAEG;IACO,eAAe,GAAG,IAAI,YAAY,EAAY,CAAC;IAEzD;;OAEG;IACM,aAAa,GAA6B,IAAI,CAAC;IAExD,mDAAmD;IACtB,cAAc,CAAsC;IAEjF,iBAAiB;IACjB,UAAU,GAAsB,IAAI,CAAC;IACrC,UAAU,GAAyB,IAAI,CAAC;IACxC,SAAS,GAAY,KAAK,CAAC;IAC3B,UAAU,GAAY,KAAK,CAAC;IAC5B,YAAY,GAAa,EAAE,CAAC;IAC5B,aAAa,GAAW,CAAC,CAAC;IAE1B,2DAA2D;IACnD,oBAAoB,GAAsB;QAChD,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,KAAK;QACd,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI;QAClB,kBAAkB,EAAE,IAAI;KACzB,CAAC;IAEF;;OAEG;IACH,IAAI,sBAAsB;QACxB,OAAO,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,oBAAoB,CAAC;IACzD,CAAC;IAED,YACU,aAA4B,EAC5B,GAAsB;QAE9B,KAAK,EAAE,CAAC;QAHA,kBAAa,GAAb,aAAa,CAAe;QAC5B,QAAG,GAAH,GAAG,CAAmB;IAEtB,CAAC;IAEX,QAAQ;QACN,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,WAAW,CAAC,OAAsB;QAChC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,eAAe,CAAC,UAAsB,EAAE,iBAAyB,EAAE,MAAc;QACvF,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;QAE3C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,kCAAkC;YAClC,qDAAqD;YACrD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACpC,OAAO,GAAG,OAAO,6BAA6B,iBAAiB,kCAAkC,MAAM,IAAI,CAAC;QAC9G,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,oFAAoF;YACpF,0EAA0E;YAC1E,iEAAiE;YACjE,6GAA6G;YAC7G,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;gBAChD,MAAM,gBAAgB,GAAG,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC;gBACzC,MAAM,UAAU,GAAG,SAAS,EAAE,CAAC,IAAI,qBAAqB,CAAC;gBACzD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;oBAChB,OAAO,GAAG,gBAAgB,MAAM,UAAU,EAAE,CAAC;gBAC/C,CAAC;qBAAM,CAAC;oBACN,OAAO,UAAU,gBAAgB,MAAM,UAAU,EAAE,CAAC;gBACtD,CAAC;YACH,CAAC,CAAC,CAAC;YACH,MAAM,gBAAgB,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEjD,gFAAgF;YAChF,OAAO;wBACW,iBAAiB;6BACZ,MAAM;6BACN,gBAAgB;QACrC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ;QACpB,cAAc;QACd,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;YAC9B,IAAI,IAAI,GAAwB,IAAI,CAAC,UAAU,CAAC;YAEhD,uCAAuC;YACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACzB,IAAI,GAAG,MAAM,EAAE,CAAC,eAAe,CAAe,WAAW,CAAC,CAAC;gBAC3D,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC;YAED,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBACrC,OAAO;YACT,CAAC;YAED,oCAAoC;YACpC,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAE7B,kEAAkE;YAClE,MAAM,qBAAqB,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;YAClE,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,wDAAwD;YACxD,sFAAsF;YACtF,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,CAAC;YAChD,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAEtE,kEAAkE;YAClE,mEAAmE;YACnE,oEAAoE;YACpE,iEAAiE;YACjE,oEAAoE;YACpE,iEAAiE;YACjE,iDAAiD;YACjD,IAAI,CAAC,UAAU,GAAG;gBAChB,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,WAAW,EAAE,WAAW;gBACxB,UAAU,EAAE,eAAe;gBAC3B,WAAW,EAAE,IAAI;aAClB,CAAC;YAEF,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,KAA6B;QACtC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO;QAE3C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,YAAY,CAAC,2BAA2B,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAErE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;YAChC,YAAY;YACZ,MAAM,EAAE,KAAK,CAAC,GAAG;SAClB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,KAAmC;QAClD,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO;QAE3C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,YAAY,CAAC,2BAA2B,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAErE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACzB,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;YAChC,YAAY;YACZ,MAAM,EAAE,KAAK,CAAC,GAAG;SAClB,CAAC,CAAC;QAEH,+EAA+E;QAC/E,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,KAA6B;QACxC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,IAAc;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,OAAO;QACL,kCAAkC;QAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAc,EAAE,WAAoB,KAAK;QAClD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,SAAS;QACP,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;iHAzVU,uBAAuB;6DAAvB,uBAAuB;;;;;;YCxDpC,8BAAwC;YAEtC,yFAAiB;YAOjB,yFAA2D;YAQ3D,yGAAgC;YAclC,iBAAM;;YA7BJ,cAIC;YAJD,wCAIC;YAGD,cAKC;YALD,8FAKC;YAGD,cAaC;YAbD,2DAaC;;;iFD0BU,uBAAuB;cANnC,SAAS;6BACI,KAAK,YACP,qBAAqB;;kBAU9B,KAAK;;kBAML,KAAK;;kBAML,KAAK;;kBAML,KAAK;;kBAML,KAAK;;kBAML,KAAK;;kBAKL,MAAM;;kBAKN,MAAM;;kBAKN,MAAM;;kBAKN,MAAM;;kBAKN,KAAK;;kBAGL,SAAS;mBAAC,gBAAgB;;kFAhEhB,uBAAuB","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ViewChild\n} from '@angular/core';\nimport { Metadata, EntityInfo, CompositeKey, BaseEntity, RunViewParams } from '@memberjunction/core';\nimport { MJListEntity } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport {\n AfterRowClickEventArgs,\n AfterRowDoubleClickEventArgs,\n AfterDataLoadEventArgs,\n GridToolbarConfig,\n GridSelectionMode,\n EntityDataGridComponent\n} from '@memberjunction/ng-entity-viewer';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n/**\n * Event emitted when a row is clicked in the list detail grid\n */\nexport interface ListGridRowClickedEvent {\n entityId: string;\n entityName: string;\n compositeKey: CompositeKey;\n record: Record<string, unknown>;\n}\n\n/**\n * ListDetailGridComponent - Displays records from a List using mj-entity-data-grid\n *\n * This component wraps the modern mj-entity-data-grid component to display\n * records that belong to a specific List. It uses a subquery filter to fetch\n * only records whose IDs are in the List Details for the given ListID.\n *\n * @example\n * ```html\n * <mj-list-detail-grid\n * [listId]=\"selectedList.ID\"\n * [autoNavigate]=\"true\"\n * (rowClicked)=\"onRecordSelected($event)\">\n * </mj-list-detail-grid>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-list-detail-grid',\n templateUrl: './ng-list-detail-grid.component.html',\n styleUrls: ['./ng-list-detail-grid.component.css']\n})\nexport class ListDetailGridComponent extends BaseAngularComponent implements OnInit, OnChanges {\n /**\n * The List ID to display records for.\n * When set, the component loads the list entity and builds a filter\n * to show only records that are in this list.\n */\n @Input() listId: string | null = null;\n\n /**\n * Optional: The List entity object if already loaded.\n * If provided, avoids an extra database call to load the list.\n */\n @Input() listEntity: MJListEntity | null = null;\n\n /**\n * Whether to auto-navigate to the record when double-clicked.\n * Defaults to true.\n */\n @Input() autoNavigate: boolean = true;\n\n /**\n * Height of the grid. Can be a number (pixels), 'auto', or 'fit-content'.\n * Defaults to 'auto'.\n */\n @Input() height: number | 'auto' | 'fit-content' = 'auto';\n\n /**\n * Show the grid toolbar.\n * Defaults to true.\n */\n @Input() showToolbar: boolean = true;\n\n /**\n * Selection mode for the grid.\n * Defaults to 'single'.\n */\n @Input() selectionMode: GridSelectionMode = 'single';\n\n /**\n * Emitted when a row is clicked (single click).\n */\n @Output() rowClicked = new EventEmitter<ListGridRowClickedEvent>();\n\n /**\n * Emitted when a row is double-clicked.\n */\n @Output() rowDoubleClicked = new EventEmitter<ListGridRowClickedEvent>();\n\n /**\n * Emitted when the grid data is loaded.\n */\n @Output() dataLoaded = new EventEmitter<{ totalCount: number }>();\n\n /**\n * Emitted when row selection changes (for checkbox mode).\n */\n @Output() selectionChange = new EventEmitter<string[]>();\n\n /**\n * Custom toolbar configuration. If not provided, uses default.\n */\n @Input() toolbarConfig: GridToolbarConfig | null = null;\n\n // ViewChild to access the underlying EDG component\n @ViewChild('entityDataGrid') entityDataGrid: EntityDataGridComponent | undefined;\n\n // Internal state\n entityInfo: EntityInfo | null = null;\n gridParams: RunViewParams | null = null;\n isLoading: boolean = false;\n listLoaded: boolean = false;\n selectedKeys: string[] = [];\n totalRowCount: number = 0;\n\n // Default toolbar configuration - minimal for list display\n private defaultToolbarConfig: GridToolbarConfig = {\n showSearch: true,\n showRefresh: true,\n showAdd: false,\n showDelete: false,\n showExport: true,\n showRowCount: true,\n showSelectionCount: true\n };\n\n /**\n * Get the effective toolbar config (custom or default)\n */\n get effectiveToolbarConfig(): GridToolbarConfig {\n return this.toolbarConfig || this.defaultToolbarConfig;\n }\n\n constructor(\n private sharedService: SharedService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnInit(): void {\n if (this.listId || this.listEntity) {\n this.loadList();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['listId'] || changes['listEntity']) {\n this.loadList();\n }\n }\n\n /**\n * Build the SQL filter to select records that are in the given list.\n * For single PK entities, uses a simple IN clause.\n * For composite PK entities, uses a JOIN that concatenates PK columns to match the RecordID format.\n */\n private buildListFilter(entityInfo: EntityInfo, listDetailsSchema: string, listId: string): string {\n const primaryKeys = entityInfo.PrimaryKeys;\n\n if (primaryKeys.length === 1) {\n // Simple case: single primary key\n // Use a simple IN clause matching the first PK field\n const pkField = primaryKeys[0].Name;\n return `${pkField} IN (SELECT RecordID FROM ${listDetailsSchema}.vwListDetails WHERE ListID = '${listId}')`;\n } else {\n // Composite key case: need to JOIN and match concatenated key format\n // RecordID format is \"Field1|Value1||Field2|Value2\" (using CompositeKey delimiters)\n // Build SQL expression that concatenates the PK fields in the same format\n // Build the concatenation expression for the entity's PK columns\n // Format: Field1 + '|' + CAST(Value1 AS NVARCHAR(MAX)) + '||' + Field2 + '|' + CAST(Value2 AS NVARCHAR(MAX))\n const concatParts = primaryKeys.map((pk, index) => {\n const fieldNameLiteral = `'${pk.Name}|'`;\n const fieldValue = `CAST([${pk.Name}] AS NVARCHAR(MAX))`;\n if (index === 0) {\n return `${fieldNameLiteral} + ${fieldValue}`;\n } else {\n return `'||' + ${fieldNameLiteral} + ${fieldValue}`;\n }\n });\n const compositeKeyExpr = concatParts.join(' + ');\n\n // Use EXISTS with a subquery that matches the concatenated key against RecordID\n return `EXISTS (\n SELECT 1 FROM ${listDetailsSchema}.vwListDetails ld\n WHERE ld.ListID = '${listId}'\n AND ld.RecordID = (${compositeKeyExpr})\n )`;\n }\n }\n\n /**\n * Load the list entity and set up the grid params with filter\n */\n private async loadList(): Promise<void> {\n // Reset state\n this.listLoaded = false;\n this.gridParams = null;\n\n if (!this.listId && !this.listEntity) {\n return;\n }\n\n this.isLoading = true;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n let list: MJListEntity | null = this.listEntity;\n\n // Load the list entity if not provided\n if (!list && this.listId) {\n list = await md.GetEntityObject<MJListEntity>('MJ: Lists');\n await list.Load(this.listId);\n }\n\n if (!list) {\n console.error('Failed to load list');\n return;\n }\n\n // Get the entity info for this list\n const entityInfo = md.EntityByID(list.EntityID);\n if (!entityInfo) {\n console.error(`Entity not found for ID: ${list.EntityID}`);\n return;\n }\n\n this.entityInfo = entityInfo;\n\n // Get the List Details entity info to get the correct schema name\n const listDetailsEntityInfo = md.EntityByName('MJ: List Details');\n if (!listDetailsEntityInfo) {\n console.error('List Details entity not found in metadata');\n return;\n }\n\n // Build the subquery filter to get records in this list\n // Uses the primary key field(s) of the entity and the schema from List Details entity\n const schema = listDetailsEntityInfo.SchemaName;\n const extraFilter = this.buildListFilter(entityInfo, schema, list.ID);\n\n // The grid filter is a cross-entity subquery into `vwListDetails`\n // (`ID IN (SELECT RecordID FROM vwListDetails WHERE ListID='…')`).\n // The server's RunView cache fingerprints by the OUTER entity, so a\n // mutation on `MJ: List Details` doesn't invalidate this query's\n // cached result — the grid would otherwise serve stale rows until a\n // server restart. `BypassCache: true` makes the server skip both\n // the cache lookup and the write for this query.\n this.gridParams = {\n EntityName: entityInfo.Name,\n ExtraFilter: extraFilter,\n ResultType: 'entity_object',\n BypassCache: true\n };\n\n this.listLoaded = true;\n } catch (error) {\n console.error('Error loading list:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handle row click event from the grid\n */\n onRowClick(event: AfterRowClickEventArgs): void {\n if (!this.entityInfo || !event.row) return;\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(this.entityInfo, event.row);\n\n this.rowClicked.emit({\n entityId: this.entityInfo.ID,\n entityName: this.entityInfo.Name,\n compositeKey,\n record: event.row\n });\n }\n\n /**\n * Handle row double-click event from the grid\n */\n onRowDoubleClick(event: AfterRowDoubleClickEventArgs): void {\n if (!this.entityInfo || !event.row) return;\n\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromEntityInfoAndRecord(this.entityInfo, event.row);\n\n this.rowDoubleClicked.emit({\n entityId: this.entityInfo.ID,\n entityName: this.entityInfo.Name,\n compositeKey,\n record: event.row\n });\n\n // Auto-navigate if enabled - use SharedService for proper tab-based navigation\n if (this.autoNavigate) {\n this.sharedService.OpenEntityRecord(this.entityInfo.Name, compositeKey);\n }\n }\n\n /**\n * Handle data loaded event from the grid\n */\n onDataLoaded(event: AfterDataLoadEventArgs): void {\n this.totalRowCount = event.totalRowCount;\n this.dataLoaded.emit({ totalCount: event.totalRowCount });\n }\n\n /**\n * Handle selection change from the grid\n */\n onSelectionChange(keys: string[]): void {\n this.selectedKeys = keys;\n this.selectionChange.emit(keys);\n }\n\n /**\n * Refresh the grid data\n */\n refresh(): void {\n // Re-trigger load to refresh data\n this.loadList();\n }\n\n /**\n * Get the currently selected entity objects\n */\n getSelectedRows(): Record<string, unknown>[] {\n if (this.entityDataGrid) {\n return this.entityDataGrid.GetSelectedRows();\n }\n return [];\n }\n\n /**\n * Clear all selections\n */\n clearSelection(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.ClearSelection();\n }\n this.selectedKeys = [];\n }\n\n /**\n * Select specific rows by key\n */\n selectRows(keys: string[], additive: boolean = false): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.SelectRows(keys, additive);\n }\n }\n\n /**\n * Select all rows\n */\n selectAll(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.SelectAll();\n }\n }\n\n /**\n * Get the total row count\n */\n get rowCount(): number {\n return this.totalRowCount;\n }\n\n /**\n * Get the selected row count\n */\n get selectedCount(): number {\n return this.selectedKeys.length;\n }\n\n /**\n * Trigger the export dialog\n */\n export(): void {\n if (this.entityDataGrid) {\n this.entityDataGrid.onExportClick();\n }\n }\n}\n","<div class=\"list-detail-grid-container\">\n <!-- Loading state while list is being loaded -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading list...\"></mj-loading>\n </div>\n }\n\n <!-- Empty state when no list is selected -->\n @if (!isLoading && !listLoaded && !listId && !listEntity) {\n <div class=\"empty-state\">\n <span class=\"fa-solid fa-rectangle-list empty-icon\"></span>\n <p>Select a list to view its records</p>\n </div>\n }\n\n <!-- Grid display when list is loaded -->\n @if (listLoaded && gridParams) {\n <mj-entity-data-grid\n #entityDataGrid\n [Params]=\"gridParams\"\n [Height]=\"height\"\n [ShowToolbar]=\"showToolbar\"\n [ToolbarConfig]=\"effectiveToolbarConfig\"\n [SelectionMode]=\"selectionMode\"\n (AfterRowClick)=\"onRowClick($event)\"\n (AfterRowDoubleClick)=\"onRowDoubleClick($event)\"\n (AfterDataLoad)=\"onDataLoaded($event)\"\n (SelectionChange)=\"onSelectionChange($event)\">\n </mj-entity-data-grid>\n }\n</div>\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-list-detail-grid",
3
- "version": "5.34.1",
3
+ "version": "5.36.0",
4
4
  "description": "MemberJunction: Angular Grid to display dynamic and saved List Details for any entity in MemberJunction.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -25,13 +25,13 @@
25
25
  "@angular/router": "21.1.3"
26
26
  },
27
27
  "dependencies": {
28
- "@memberjunction/core": "5.34.1",
29
- "@memberjunction/core-entities": "5.34.1",
30
- "@memberjunction/global": "5.34.1",
31
- "@memberjunction/ng-base-types": "5.34.1",
32
- "@memberjunction/ng-entity-viewer": "5.34.1",
33
- "@memberjunction/ng-shared": "5.34.1",
34
- "@memberjunction/ng-shared-generic": "5.34.1",
28
+ "@memberjunction/core": "5.36.0",
29
+ "@memberjunction/core-entities": "5.36.0",
30
+ "@memberjunction/global": "5.36.0",
31
+ "@memberjunction/ng-base-types": "5.36.0",
32
+ "@memberjunction/ng-entity-viewer": "5.36.0",
33
+ "@memberjunction/ng-shared": "5.36.0",
34
+ "@memberjunction/ng-shared-generic": "5.36.0",
35
35
  "rxjs": "~7.8.2",
36
36
  "tslib": "^2.8.1"
37
37
  },