This is an automated email from the ASF dual-hosted git repository. dominikriemer pushed a commit to branch keep-selection-in-overview-tables in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit cead08881808df699058b5b2a5f037f3e75c3a7b Author: Dominik Riemer <[email protected]> AuthorDate: Mon Jul 20 20:31:22 2026 +0200 feat: Keep selection after executing multi-select action --- .../lib/components/sp-table/sp-table.component.ts | 39 ++++++++++++++++------ ui/src/app/pipelines/pipelines.component.html | 1 + ui/src/app/pipelines/pipelines.component.ts | 1 - 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.ts index d3a1c068e6..3580b50b5f 100644 --- a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.ts +++ b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.ts @@ -279,8 +279,6 @@ export class SpTableComponent<T> ngOnChanges(changes: SimpleChanges) { if (changes['dataSource']) { - this.selection.clear(); - this.emitSelection(); this.visiblePageRows = []; this.configureNameSearch(); if (this.viewInitialized) { @@ -642,12 +640,12 @@ export class SpTableComponent<T> return rows.slice(startIndex, startIndex + pageSize); } - private updateRenderedState(rows: T[], pruneSelection = true) { + private updateRenderedState(rows: T[], reconcileSelection = true) { this.visiblePageRows = rows; this.rebuildGroupedSections(rows); - if (pruneSelection) { - this.pruneSelection(); + if (reconcileSelection) { + this.reconcileSelection(); } if (this.viewInitialized) { @@ -658,24 +656,43 @@ export class SpTableComponent<T> } } - private pruneSelection() { + private reconcileSelection() { if (!this.selection.hasValue() || !this.dataSource) { return; } - const availableRows = new Set(this.dataSource.filteredData ?? []); - const rowsToRemove = this.selection.selected.filter( - row => !availableRows.has(row), + const availableRowsByResourceId = new Map<unknown, T>( + (this.dataSource.data ?? []).map(row => [ + this.getSelectionKey(row), + row, + ]), ); + const reconciledSelection = this.selection.selected + .map(row => + availableRowsByResourceId.get(this.getSelectionKey(row)), + ) + .filter((row): row is T => row !== undefined); + const selectionChanged = + reconciledSelection.length !== this.selection.selected.length || + reconciledSelection.some( + (row, index) => row !== this.selection.selected[index], + ); - if (!rowsToRemove.length) { + if (!selectionChanged) { return; } - this.selection.deselect(...rowsToRemove); + this.selection.clear(); + this.selection.select(...reconciledSelection); this.emitSelection(); } + private getSelectionKey(row: T): unknown { + const resourceId = (row as Record<string, unknown>)[this.resourceIdKey]; + + return resourceId ?? row; + } + private emitSelection() { this.selectionChanged.emit(this.selection.selected); } diff --git a/ui/src/app/pipelines/pipelines.component.html b/ui/src/app/pipelines/pipelines.component.html index 34c0db5950..fbc81e8f55 100644 --- a/ui/src/app/pipelines/pipelines.component.html +++ b/ui/src/app/pipelines/pipelines.component.html @@ -51,6 +51,7 @@ <button mat-icon-button color="accent" + data-cy="refresh-pipelines" matTooltip="Refresh pipelines" matTooltipPosition="above" (click)="getPipelines()" diff --git a/ui/src/app/pipelines/pipelines.component.ts b/ui/src/app/pipelines/pipelines.component.ts index d755a95f39..476c7510df 100644 --- a/ui/src/app/pipelines/pipelines.component.ts +++ b/ui/src/app/pipelines/pipelines.component.ts @@ -141,7 +141,6 @@ export class PipelinesComponent implements OnInit, OnDestroy { } getPipelines() { - this.pipelines = []; this.pipelineService.getPipelineSummary().subscribe(resourceSummary => { this.pipelines = resourceSummary.resources.sort((a, b) => a.name.localeCompare(b.name),
