@trudb/tru-common-lib 0.2.472 → 0.2.474

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.
@@ -8221,11 +8221,8 @@ class TruDataChangeParser {
8221
8221
  }
8222
8222
  else if (entity[key] !== this.checkIfDateTime(change.properties[key], entity[key], entityType.typeName)) {
8223
8223
  if (!propertyModified) {
8224
- let newValue = this.checkIfDateTime(change.properties[key], entity[key], entityType.typeName);
8225
- if (entity[key] !== newValue) {
8226
- entity[key] = newValue;
8227
- delete originalValues[key];
8228
- }
8224
+ entity[key] = this.checkIfDateTime(change.properties[key], entity[key], entityType.typeName);
8225
+ delete originalValues[key];
8229
8226
  }
8230
8227
  else {
8231
8228
  let value = this.checkIfDateTime(change.properties[key], entity[key], entityType.typeName);
@@ -8291,7 +8288,7 @@ class TruDataChangeParser {
8291
8288
  update = async (payload) => {
8292
8289
  await this.isSaving();
8293
8290
  var reloadResults = false;
8294
- payload.changes.forEach(async (change) => {
8291
+ payload.changes.filter((change) => { return change.modifiedRef.toString() !== this.user.activeUserRef.toString(); }).forEach(async (change) => {
8295
8292
  var foundEntities = [];
8296
8293
  var localEntity = this.findEntityInCache(change);
8297
8294
  var globalEntity = this.findEntityInGlobalCache(change);
@@ -8600,6 +8597,8 @@ class TruDataGrid {
8600
8597
  rowFocuedOnMousedown = null;
8601
8598
  copiedRowData = [];
8602
8599
  scrollOffsetCleanup = null;
8600
+ detailResizeCleanup = null;
8601
+ pendingResizeFrameId = null;
8603
8602
  constructor(dataContext, componentLookup, searchResultViewManager, appEnvironment, searchViewEventHandler, uiNotification, connectionHub, windowEventHandler, dataGridClipboard, util, app, cdr, hostElement, desktopViewEventNotifier, tabGroupEventNotifier) {
8604
8603
  this.dataContext = dataContext;
8605
8604
  this.componentLookup = componentLookup;
@@ -9206,6 +9205,7 @@ class TruDataGrid {
9206
9205
  if (this.config?.view && this.desktopViewEventNotifier) {
9207
9206
  this.subs.push(this.desktopViewEventNotifier.onActiveStateChanged().pipe(skip(1)).subscribe(() => this.resizeGrid()));
9208
9207
  }
9208
+ this.setupDetailResizeObservers();
9209
9209
  }
9210
9210
  ngOnChanges(changes) {
9211
9211
  this.runSearch();
@@ -9213,6 +9213,7 @@ class TruDataGrid {
9213
9213
  }
9214
9214
  ngOnDestroy() {
9215
9215
  this.teardownScrollObservers();
9216
+ this.teardownDetailResizeObservers();
9216
9217
  this.subs.forEach(s => s.unsubscribe());
9217
9218
  }
9218
9219
  //this only applies to grids inside detail views and tab containers.
@@ -9282,6 +9283,71 @@ class TruDataGrid {
9282
9283
  this.scrollOffsetCleanup = null;
9283
9284
  }
9284
9285
  };
9286
+ scheduleResizeGrid = () => {
9287
+ if (this.pendingResizeFrameId !== null)
9288
+ return;
9289
+ this.pendingResizeFrameId = window.requestAnimationFrame(() => {
9290
+ this.pendingResizeFrameId = null;
9291
+ this.resizeGrid();
9292
+ });
9293
+ };
9294
+ setupDetailResizeObservers = () => {
9295
+ this.teardownDetailResizeObservers();
9296
+ const gridType = this.gridType;
9297
+ if (gridType === TruDataGridTypes.Search)
9298
+ return;
9299
+ const hostEl = this.hostElement.nativeElement;
9300
+ if (!hostEl || !hostEl.isConnected)
9301
+ return;
9302
+ const detailContent = hostEl.closest('.detail-content');
9303
+ if (!detailContent)
9304
+ return;
9305
+ // Make sure we re-measure when the grid is scrolled into view (common when the initial window height is short).
9306
+ const onScroll = () => this.scheduleResizeGrid();
9307
+ let intersectionObserver = null;
9308
+ if (typeof IntersectionObserver !== 'undefined') {
9309
+ intersectionObserver = new IntersectionObserver((entries) => {
9310
+ if (entries.some(e => e.isIntersecting)) {
9311
+ this.scheduleResizeGrid();
9312
+ }
9313
+ }, { root: detailContent, threshold: 0 });
9314
+ intersectionObserver.observe(hostEl);
9315
+ }
9316
+ else {
9317
+ detailContent.addEventListener('scroll', onScroll, { passive: true });
9318
+ }
9319
+ let resizeObserver = null;
9320
+ if (typeof ResizeObserver !== 'undefined') {
9321
+ resizeObserver = new ResizeObserver(() => this.scheduleResizeGrid());
9322
+ resizeObserver.observe(detailContent);
9323
+ }
9324
+ this.detailResizeCleanup = () => {
9325
+ if (intersectionObserver) {
9326
+ intersectionObserver.disconnect();
9327
+ intersectionObserver = null;
9328
+ }
9329
+ else {
9330
+ detailContent.removeEventListener('scroll', onScroll);
9331
+ }
9332
+ if (resizeObserver) {
9333
+ resizeObserver.disconnect();
9334
+ resizeObserver = null;
9335
+ }
9336
+ if (this.pendingResizeFrameId !== null) {
9337
+ window.cancelAnimationFrame(this.pendingResizeFrameId);
9338
+ this.pendingResizeFrameId = null;
9339
+ }
9340
+ this.detailResizeCleanup = null;
9341
+ };
9342
+ // Kick an initial measurement once layout settles.
9343
+ this.scheduleResizeGrid();
9344
+ };
9345
+ teardownDetailResizeObservers = () => {
9346
+ if (this.detailResizeCleanup) {
9347
+ this.detailResizeCleanup();
9348
+ this.detailResizeCleanup = null;
9349
+ }
9350
+ };
9285
9351
  //Adjusts grid height to fill available detail space, honoring fill/min/max rows.
9286
9352
  //this doesn't affect search grids.
9287
9353
  resizeGrid = () => {
@@ -9300,12 +9366,6 @@ class TruDataGrid {
9300
9366
  const firstGridTop = siblingGrids.length ? siblingGrids[0].getBoundingClientRect().top : hostEl.getBoundingClientRect().top;
9301
9367
  const detailRect = detailContent.getBoundingClientRect();
9302
9368
  const availableTotal = detailContent.clientHeight - (firstGridTop - detailRect.top) - 10; // small bottom padding
9303
- if (availableTotal <= 0)
9304
- return;
9305
- const perGridOverhead = 45; // toolbar + statusbar overhead (v6 does something similar i am just porting here)
9306
- const distributedHeight = siblingGrids.length > 1
9307
- ? (availableTotal - (siblingGrids.length - 1) * perGridOverhead) / siblingGrids.length
9308
- : availableTotal;
9309
9369
  const rowHeight = this.gridOptions?.rowHeight ?? 22;
9310
9370
  const headerHeight = 25;
9311
9371
  const minRows = this.config.minimumRows ?? 0;
@@ -9318,6 +9378,20 @@ class TruDataGrid {
9318
9378
  const contentMinPx = Math.max((minRows * rowHeight) + headerHeight, overlayMinPx);
9319
9379
  const minPx = contentMinPx + gridChromePx;
9320
9380
  const maxPx = typeof maxRows === 'number' ? ((maxRows * rowHeight) + headerHeight + gridChromePx) : undefined;
9381
+ // When the initial window height is short, the grid can start below the visible portion of the detail container.
9382
+ // In that case, we still need a minimum height so the parent can scroll to reveal the grid.
9383
+ if (availableTotal <= 0) {
9384
+ hostEl.style.height = `${minPx}px`;
9385
+ const apiAny = this.api;
9386
+ if (apiAny?.doLayout) {
9387
+ apiAny.doLayout();
9388
+ }
9389
+ return;
9390
+ }
9391
+ const perGridOverhead = 45; // toolbar + statusbar overhead (v6 does something similar i am just porting here)
9392
+ const distributedHeight = siblingGrids.length > 1
9393
+ ? (availableTotal - (siblingGrids.length - 1) * perGridOverhead) / siblingGrids.length
9394
+ : availableTotal;
9321
9395
  let targetHeight = distributedHeight;
9322
9396
  if (!this.config.fill) {
9323
9397
  if (maxPx !== undefined && maxPx < targetHeight)
@@ -11917,17 +11991,19 @@ class TruTabGroup {
11917
11991
  const list = new QueryList();
11918
11992
  list.reset([matTabsFromQueryList]);
11919
11993
  this.tabGroup._tabs = list;
11994
+ // Ensure the initially-selected tab is marked active so consumers (e.g. detail grids) can load/size correctly.
11995
+ // MatTabGroup won't emit selectedTabChange on initial render.
11996
+ setTimeout(() => {
11997
+ const selectedIndex = typeof this.tabGroup.selectedIndex === 'number' ? this.tabGroup.selectedIndex : 0;
11998
+ this.setActiveTabByIndex(selectedIndex);
11999
+ }, 0);
11920
12000
  }
11921
12001
  onChange(event) {
11922
- const selectedTabLabel = event.tab.textLabel;
11923
- this.tabs.forEach((tab) => {
11924
- if (selectedTabLabel === tab.label) {
11925
- tab.notifyListeners(true);
11926
- }
11927
- else {
11928
- tab.notifyListeners(false);
11929
- }
11930
- });
12002
+ this.setActiveTabByIndex(event.index);
12003
+ }
12004
+ setActiveTabByIndex(selectedIndex) {
12005
+ const allTabs = this.tabs?.toArray?.() ?? [];
12006
+ allTabs.forEach((tab, index) => tab.notifyListeners(index === selectedIndex));
11931
12007
  }
11932
12008
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
11933
12009
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruTabGroup, isStandalone: true, selector: "tru-tab-group", queries: [{ propertyName: "tabs", predicate: TruTab }], viewQueries: [{ propertyName: "tabGroup", first: true, predicate: MatTabGroup, descendants: true }], ngImport: i0, template: "<mat-tab-group #tabGroup\r\n (selectedTabChange)=\"onChange($event)\"\r\n animationDuration=\"0ms\">\r\n <ng-content #outlet></ng-content>\r\n</mat-tab-group>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], encapsulation: i0.ViewEncapsulation.None });