Browse Source

Merge pull request #26110 from abpframework/auto-merge-forward/rel-10.6-to-rel-10.7-25

Auto-merge forward rel-10.6 → rel-10.7
rel-10.7
Volosoft Agent 3 days ago
committed by GitHub
parent
commit
93905de1c2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      docs/en/studio/release-notes.md
  2. 2
      docs/en/studio/version-mapping.md
  3. 70
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts

13
docs/en/studio/release-notes.md

@ -9,7 +9,18 @@
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
## 3.1.0 (2026-08-24) Latest
## 3.1.1 (2026-08-28) Latest
* Refactor release version resolution logic to ensure proper tag handling
* Fix chmod command syntax in set-executable-permissions scripts for Li…
* Restore macOS signing env values used by the 3.0 pipelines
* Show preparing-solution banner only after creation
* Add top spacing above the browser address bar
* Improve fullscreen flyout interaction and small-window clipping
* Fix Admin Console command input export
* Prefer Docker Compose v2 when starting containers
## 3.1.0 (2026-08-24)
* Clarify CLI tracked-process stop method: //github.com/volosoft/abp-studio/pull/4517
* Action of studio template test is working with self hosted agent

2
docs/en/studio/version-mapping.md

@ -11,7 +11,7 @@ This document provides a general overview of the relationship between various ve
| **ABP Studio Version** | **ABP Version of Startup Template** |
|------------------------|---------------------------|
| 3.0.9 - 3.1.0 | 10.6.0 |
| 3.0.9 - 3.1.1 | 10.6.0 |
| 3.0.6 - 3.0.8 | 10.5.0 |
| 3.0.4 - 3.0.5 | 10.4.1 |
| 3.0.3 | 10.4.0 |

70
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts

@ -1,8 +1,10 @@
import {
afterNextRender,
AfterViewInit,
ChangeDetectionStrategy,
Component,
computed,
DestroyRef,
inject,
Injector,
LOCALE_ID,
@ -17,9 +19,10 @@ import {
contentChild,
viewChild,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AsyncPipe, isPlatformBrowser, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
import { Observable, filter, map, Subject, debounceTime, distinctUntilChanged } from 'rxjs';
import { Observable, map, Subject, debounceTime, distinctUntilChanged } from 'rxjs';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import {
@ -92,6 +95,7 @@ const DEFAULT_ACTIONS_COLUMN_WIDTH = 150;
})
export class ExtensibleTableComponent<R = any> implements AfterViewInit, OnDestroy {
readonly #injector = inject(Injector);
readonly #destroyRef = inject(DestroyRef);
readonly getInjected = this.#injector.get.bind(this.#injector);
protected readonly locale = inject(LOCALE_ID);
protected readonly config = inject(ConfigStateService);
@ -186,6 +190,10 @@ export class ExtensibleTableComponent<R = any> implements AfterViewInit, OnDestr
},
);
private horizontalScrollOffset = 0;
private hasPendingHorizontalScrollOffset = false;
hasAtLeastOnePermittedAction: boolean;
readonly propList: EntityPropList<R>;
@ -232,6 +240,7 @@ export class ExtensibleTableComponent<R = any> implements AfterViewInit, OnDestr
}
this._data.set(dataValue.map((record, index) => this.prepareRecord(record, index)));
this.restoreHorizontalScrollOffset();
});
}
@ -363,13 +372,66 @@ export class ExtensibleTableComponent<R = any> implements AfterViewInit, OnDestr
ngAfterViewInit(): void {
if (!this.infiniteScroll()) {
this.list()
?.requestStatus$?.pipe(filter(status => status === 'loading'))
.subscribe(() => {
this._data.set([]);
?.requestStatus$?.pipe(takeUntilDestroyed(this.#destroyRef))
.subscribe(status => {
if (status === 'loading') {
this.rememberHorizontalScrollOffset();
this._data.set([]);
return;
}
// A failed request never reaches the data input, restore from here instead
if (status === 'error') {
this.restoreHorizontalScrollOffset();
}
});
}
}
private getBodyElement(): HTMLElement | null {
if (!this.isBrowser) {
return null;
}
return this.table()?.element?.querySelector('datatable-body') ?? null;
}
// The element carrying the column width is gone while loading without rows, so the browser
// resets the horizontal scroll position and the header keeps the offset it had before
private rememberHorizontalScrollOffset(): void {
const body = this.getBodyElement();
this.hasPendingHorizontalScrollOffset = true;
// Not scrollable while a previous request is still in flight, keep the offset taken back then
if (body && body.scrollWidth > body.clientWidth) {
this.horizontalScrollOffset = body.scrollLeft;
}
}
private restoreHorizontalScrollOffset(): void {
if (!this.hasPendingHorizontalScrollOffset) {
return;
}
this.hasPendingHorizontalScrollOffset = false;
afterNextRender(
() => {
const body = this.getBodyElement();
if (!body) {
return;
}
body.scrollLeft = this.horizontalScrollOffset;
// The header only follows a scroll event, scrolling to the same position does not raise one
body.dispatchEvent(new Event('scroll'));
},
{ injector: this.#injector },
);
}
ngOnDestroy(): void {
this.loadMoreSubscription.unsubscribe();
}

Loading…
Cancel
Save