This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-8965-61d435d25109d29385d8d7ce6d9a03f099c18c2e in repository https://gitbox.apache.org/repos/asf/texera.git
commit 41848581d3343f2a9c0cb3bc483ab1aa65e0049c Author: Tanishq Gandhi <[email protected]> AuthorDate: Wed Oct 14 23:50:22 2026 +0000 fix(frontend): refresh the Datasets and Models list view after revoking your own access (#8965) ### What changes were proposed in this PR? In list view, the Datasets and Models pages bound the results list’s (refresh) to ngAfterViewInit(), which only subscribed to the user stream again. The search it triggered saw the same filters and sort and returned early, so the list was never reloaded. After revoking your own access, the item stayed listed until a page reload, and each refresh added another subscription that was never removed. Both pages now bind (refresh)="search(true)", the forced search card view already uses. Before: after revoking your own access to sales-2026, it is still listed: <img width="1440" height="900" alt="before-2-revoke-own-access" src="https://github.com/user-attachments/assets/0bd7c55a-a538-43ca-885f-7935f877f67a" /> <img width="1440" height="900" alt="before-3-row-still-listed" src="https://github.com/user-attachments/assets/7a1a79ad-99fb-4972-8ca3-2b97762c740d" /> After: the item disappears right away on both pages: <img width="1440" height="900" alt="after-2-datasets-row-gone" src="https://github.com/user-attachments/assets/2be72235-895e-457f-ba8d-1d70092d5ce0" /> <img width="1440" height="900" alt="after-4-models-row-gone" src="https://github.com/user-attachments/assets/749ff178-a843-4ce5-9087-2c91feecace8" /> ### Any related issues, documentation, discussions? Closes #8964 ### How was this PR tested? Added a case to each of user-dataset.component.spec.ts and user-model.component.spec.ts: a refresh from the results list runs a forced search. Both fail without the fix. cd frontend yarn ng test --watch=false --include='**/user-dataset.component.spec.ts' --include='**/user-model.component.spec.ts' Tests 65 passed (65) Also checked against a local stack: as a WRITE collaborator in list view, revoking your own access removes the dataset or model from the list on both pages. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) Co-authored-by: Xuan Gu <[email protected]> --- .../component/user/user-dataset/user-dataset.component.html | 2 +- .../component/user/user-dataset/user-dataset.component.spec.ts | 10 ++++++++++ .../component/user/user-model/user-model.component.html | 2 +- .../component/user/user-model/user-model.component.spec.ts | 10 ++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.html b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.html index 87a1db132b..69061cb5ec 100644 --- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.html +++ b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.html @@ -99,6 +99,6 @@ [viewMode]="viewType" [cardTemplate]="datasetCardTpl" (deleted)="deleteDataset($event)" - (refresh)="ngAfterViewInit()" + (refresh)="search(true)" [currentUid]="currentUid"></texera-search-results> </div> diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.spec.ts b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.spec.ts index f80b956e31..12411ecbee 100644 --- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.spec.ts +++ b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.spec.ts @@ -787,4 +787,14 @@ describe("UserDatasetComponent card view", () => { // the filters nor the sort changed. expect(searchSpy).toHaveBeenCalledWith(true); }); + + it("forces a fresh search when the results list asks for a refresh", () => { + const results = fixture.debugElement.query(By.directive(SearchResultsComponent)) + .componentInstance as SearchResultsComponent; + const searchSpy = vi.spyOn(component, "search").mockResolvedValue(undefined); + + results.refresh.emit(); + + expect(searchSpy).toHaveBeenCalledWith(true); + }); }); diff --git a/frontend/src/app/dashboard/component/user/user-model/user-model.component.html b/frontend/src/app/dashboard/component/user/user-model/user-model.component.html index 8b2f95d76a..1bb1187b20 100644 --- a/frontend/src/app/dashboard/component/user/user-model/user-model.component.html +++ b/frontend/src/app/dashboard/component/user/user-model/user-model.component.html @@ -99,6 +99,6 @@ [viewMode]="viewType" [cardTemplate]="modelCardTpl" (deleted)="deleteModel($event)" - (refresh)="ngAfterViewInit()" + (refresh)="search(true)" [currentUid]="currentUid"></texera-search-results> </div> diff --git a/frontend/src/app/dashboard/component/user/user-model/user-model.component.spec.ts b/frontend/src/app/dashboard/component/user/user-model/user-model.component.spec.ts index 479b13a9b4..90bca4914f 100644 --- a/frontend/src/app/dashboard/component/user/user-model/user-model.component.spec.ts +++ b/frontend/src/app/dashboard/component/user/user-model/user-model.component.spec.ts @@ -395,6 +395,16 @@ describe("UserModelComponent rendering", () => { expect(results.currentUid).toBe(component.currentUid); }); + it("forces a fresh search when the results list asks for a refresh", () => { + const results = fixture.debugElement.query(By.directive(SearchResultsComponent)) + .componentInstance as SearchResultsComponent; + const searchSpy = vi.spyOn(component, "search").mockResolvedValue(undefined); + + results.refresh.emit(); + + expect(searchSpy).toHaveBeenCalledWith(true); + }); + /** A search hit, in the shape DashboardEntry accepts. */ function modelEntry(mid = 3, name = "resnet"): DashboardEntry { return new DashboardEntry({
