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-8661-b928f82b90286b92f15efd8514134578fcb19577 in repository https://gitbox.apache.org/repos/asf/texera.git
commit 63db8e3f43cdbbc5c031321727bbf937fbbdc6ea Author: Xinyuan Lin <[email protected]> AuthorDate: Sun Sep 27 22:08:55 2026 +0000 chore(frontend): remove dead search-results inputs and styles (#8661) ### What changes were proposed in this PR? Removes the three `SearchResultsComponent` inputs that it never reads (`searchKeywords`, `showResourceTypes`, `pid`), the parent code that still computes and binds them, and the CSS in `search-results.component.scss` and `section-style.scss` that matches no element it can reach. Pure deletion, no behaviour change: **−172 / +10 lines**. ### History | | | | --- | --- | | **Reads removed by** | #2793 (2024-08-20) — "Generalize List Item" replaced the per-type list items, and the `nz-layout` / `nz-sider` resource-type icon around each one, with the generic `ListItemComponent`, deleting every template read of the three inputs | | **Never matched** | #2776 (2024-08-19) — `.section-title .management-panel` and `.section-title .go-back-button` arrived with the extraction of `section-style.scss` and never matched a template that includes it | > Reviewer note — the keyword chain. `searchKeywords` fed each old list item's `[keywords]` input, which drove the search-term highlight. `SearchComponent` and `HubSearchResultComponent` kept recomputing it from the filter bar on every search and binding it into the results list, where nothing read it. The field and its assignments go in both parents. The two `SearchComponent` tests that only pinned the field go too. The tests that asserted on it alongside something still live now assert on that: the `?q=` tests check the filter bar's master list, the hub early-return test checks `getSearchFilterParameters`, and the hub binding test checks `currentUid` alone. `FiltersComponent.getSearchKeywords()` stays, because the search requests still call it. > Reviewer note — `detectChanges()` stays. `SearchComponent.ngAfterViewInit` assigned the keywords and then called `this.cdr.detectChanges()`. Only the assignment goes. The call also re-renders after a `?q=` param is pushed into the filter bar, so it is not part of the dead chain. > Reviewer note — the CSS. Component styles use Emulated encapsulation, so a rule in `search-results.component.scss` can only match that component's own template: a card, a virtual-scroll list of `texera-list-item`s, and two text-only "Load more" buttons. `nz-sider`, `nz-content` and `.resource-type-icon` styled the wrapper #2793 removed. `.dataset-search-bar`, the `.dataset-list-item { … }` block, `.subsection-grid-container` and `.ant-btn-icon-only` match nothing there. The last two also duplicate the identical rules in `section-style.scss`, which the stylesheet already `@use`s. In `section-style.scss`, none of the nine stylesheets that include it belongs to a template containing `management-panel` or `go-back-button`. The search page's back button is in `SearchComponent`, whose stylesheet does not include `section-style.scss`, and the hub detail page styles its own. The commented-out `.utility-button-group` rule goes too. The header comment that called the layout "shared between workflows and files section" now says it is shared by the user dashboard's resource sections. ### Any related issues, documentation, discussions? Closes #8660 ### How was this PR tested? Existing tests, updated where they asserted on the removed field or inputs. From `frontend/`: - `npx ng build` — **success**. This is the gate that matters: a leftover `[searchKeywords]` or `[showResourceTypes]` binding on `texera-search-results` fails only under AOT, since template diagnostics are AOT-only. - `npx ng test --watch=false --include='**/search.component.spec.ts' --include='**/hub-search-result.component.spec.ts' --include='**/search-results.component.spec.ts'` — 81 tests pass (3 files). - `yarn format:ci` — clean. Verification, re-runnable by a reviewer (both return nothing): ``` git grep -n "searchKeywords\|showResourceTypes" -- frontend/src git grep -n "resource-type-icon\|dataset-search-bar\|dataset-list-item\|management-panel" -- frontend/src ``` ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) --- .../src/app/dashboard/component/section-style.scss | 18 +--- .../search-results/search-results.component.scss | 98 ---------------------- .../search-results/search-results.component.ts | 3 - .../component/user/search/search.component.html | 6 +- .../component/user/search/search.component.spec.ts | 27 ++---- .../component/user/search/search.component.ts | 6 -- .../hub-search-result.component.html | 2 - .../hub-search-result.component.spec.ts | 20 +---- .../hub-search-result.component.ts | 2 - 9 files changed, 10 insertions(+), 172 deletions(-) diff --git a/frontend/src/app/dashboard/component/section-style.scss b/frontend/src/app/dashboard/component/section-style.scss index 446187f502..5dc9167136 100644 --- a/frontend/src/app/dashboard/component/section-style.scss +++ b/frontend/src/app/dashboard/component/section-style.scss @@ -40,7 +40,7 @@ * The second row contains the search bar. * The third row contains the saved workflow/files list. * - * This layout is shared between workflows and files section. + * This layout is shared by the user dashboard's resource sections. * * ****************** * * * @@ -74,22 +74,6 @@ $dashboard-navigation-height: 76px; .page-title { font-family: -apple-system, BlinkMacSystemFont, sans-serif; } - - .management-panel { - display: flex; - align-items: center; - justify-content: space-between; - } - - // .utility-button-group { - // float: left; - // } - - .go-back-button { - position: absolute; - left: 20px; - top: 20px; - } } /** diff --git a/frontend/src/app/dashboard/component/user/search-results/search-results.component.scss b/frontend/src/app/dashboard/component/user/search-results/search-results.component.scss index a2c66114a9..c3be0b6f4e 100644 --- a/frontend/src/app/dashboard/component/user/search-results/search-results.component.scss +++ b/frontend/src/app/dashboard/component/user/search-results/search-results.component.scss @@ -27,104 +27,6 @@ line-height: 32px; } -nz-sider { - background: rgb(255, 255, 255); -} - -nz-content { - background: rgb(255, 255, 255); -} - -.resource-type-icon { - font-size: 30px; - margin-top: 10px; - margin-left: 5px; -} - -.dataset-search-bar { - margin-left: 10px; -} - -.dataset-list-item { - margin-bottom: 10px; - min-height: 70px; - padding: 5px 0 5px 0; - - .dataset-item-checkbox { - margin: 8px; - } - - .dataset-item-meta-title { - display: flex; - align-items: center; - - .dataset-name { - font-size: 20px; - font-family: -apple-system, BlinkMacSystemFont, sans-serif; - text-align: center; - margin-bottom: 0; - color: inherit; - text-decoration: none; - } - - .dataset-name:hover { - cursor: pointer; - } - - i { - position: relative; - font-size: 17px; - } - - i.dataset-is-owner-icon { - margin-left: 7px; - } - } - - .dataset-item-meta-description { - display: flex; - align-items: center; - padding: 2px 8px 2px 10px; - margin-bottom: 5px; - - .dataset-description { - font-size: 13px; - font-family: -apple-system, BlinkMacSystemFont, sans-serif; - - display: inline-block; - min-width: 17ch; - border: 0 none; - outline: none; - - &:hover { - cursor: pointer; - box-shadow: 0 0 0 1px rgb(202, 202, 202); - } - } - - .dataset-editable-description { - margin-bottom: 5px; - display: inline-block; - min-width: 17ch; - border: 0 none; - outline: none; - box-shadow: 0 0 0 2px #007bff; - } - } -} - -.subsection-grid-container { - min-width: 100%; - width: 100%; - min-height: 100%; - height: 100%; -} - -.ant-btn-icon-only { - margin-left: 5px; - margin-right: 5px; -} - .card-scroll-container { height: 100%; overflow-y: auto; diff --git a/frontend/src/app/dashboard/component/user/search-results/search-results.component.ts b/frontend/src/app/dashboard/component/user/search-results/search-results.component.ts index baddea9f68..4e122aa4fd 100644 --- a/frontend/src/app/dashboard/component/user/search-results/search-results.component.ts +++ b/frontend/src/app/dashboard/component/user/search-results/search-results.component.ts @@ -59,10 +59,7 @@ export class SearchResultsComponent { entries: ReadonlyArray<DashboardEntry> = []; private resetCounter = 0; @Input() isPrivateSearch = false; - @Input() showResourceTypes = false; - @Input() public pid: number = 0; @Input() editable = false; - @Input() searchKeywords: string[] = []; @Input() currentUid: number | undefined; @Input() viewMode: SearchResultsViewMode = "list"; /** Template rendered for each entry in card mode; receives the entry via $implicit. */ diff --git a/frontend/src/app/dashboard/component/user/search/search.component.html b/frontend/src/app/dashboard/component/user/search/search.component.html index 167b3fcd93..c91a029691 100644 --- a/frontend/src/app/dashboard/component/user/search/search.component.html +++ b/frontend/src/app/dashboard/component/user/search/search.component.html @@ -85,10 +85,6 @@ </div> <div class="search-result"> - <texera-search-results - [showResourceTypes]="true" - [searchKeywords]="searchKeywords" - [currentUid]="this.currentUid"> - </texera-search-results> + <texera-search-results [currentUid]="this.currentUid"></texera-search-results> </div> </div> diff --git a/frontend/src/app/dashboard/component/user/search/search.component.spec.ts b/frontend/src/app/dashboard/component/user/search/search.component.spec.ts index 6a5b244f24..876928f212 100644 --- a/frontend/src/app/dashboard/component/user/search/search.component.spec.ts +++ b/frontend/src/app/dashboard/component/user/search/search.component.spec.ts @@ -49,8 +49,7 @@ import { EntityType } from "../../../../hub/service/hub.service"; // Lightweight stand-in for FiltersComponent. It registers itself under the real // FiltersComponent token so SearchComponent's `@ViewChild(FiltersComponent)` // resolves to it, without dragging in FiltersComponent's six service -// dependencies and backend-touching ngOnInit. `getSearchKeywords()` mirrors the -// current filter list so route-driven searches can be asserted end to end. +// dependencies and backend-touching ngOnInit. @Component({ selector: "texera-filters", template: "", @@ -61,7 +60,6 @@ class MockFiltersComponent { @Input() ownerScope?: string; masterFilterListChange = EMPTY; masterFilterList: ReadonlyArray<string> = []; - getSearchKeywords = (): string[] => [...this.masterFilterList]; getSearchFilterParameters = () => ({}); clearFacetSelections = vi.fn(); } @@ -71,8 +69,6 @@ class MockFiltersComponent { template: "", }) class MockSearchResultsComponent { - @Input() showResourceTypes = false; - @Input() searchKeywords: string[] = []; @Input() currentUid?: number; } @@ -141,10 +137,6 @@ describe("SearchComponent", () => { expect(() => fixture.detectChanges()).not.toThrow(); }); - it("starts with an empty searchKeywords list so the template binding is always safe", () => { - expect(component.searchKeywords).toEqual([]); - }); - // ─── filters getter / setter ──────────────────────────────────────────────── it("throws from the filters getter before the ViewChild has resolved", () => { @@ -169,33 +161,24 @@ describe("SearchComponent", () => { // ─── ngAfterViewInit / query params ───────────────────────────────────────── - it("applies the `q` query param to the filters and populates searchKeywords", () => { + it("applies the `q` query param to the filters", () => { fixture.detectChanges(); // resolves the filters ViewChild and subscribes to queryParams queryParams$.next({ q: "foo bar" }); expect(component.searchParam).toBe("foo bar"); - expect(component.searchKeywords).toEqual(["foo", "bar"]); + expect(component.filters.masterFilterList).toEqual(["foo", "bar"]); }); - it("leaves searchParam empty and searchKeywords empty when there is no `q` param", () => { + it("leaves searchParam and the filters empty when there is no `q` param", () => { fixture.detectChanges(); queryParams$.next({}); expect(component.searchParam).toBe(""); - expect(component.searchKeywords).toEqual([]); + expect(component.filters.masterFilterList).toEqual([]); }); // ─── search() ─────────────────────────────────────────────────────────────── - it("syncs searchKeywords from the filters when a search runs", async () => { - component.filters = makeFiltersDouble(["alpha", "beta"]); - component.searchResultsComponent = makeSearchResultsDouble() as unknown as SearchResultsComponent; - - await component.search(); - - expect(component.searchKeywords).toEqual(["alpha", "beta"]); - }); - it("drives the results component (reset + loadMore) on a fresh search", async () => { component.filters = makeFiltersDouble(["x"]); const results = makeSearchResultsDouble(); diff --git a/frontend/src/app/dashboard/component/user/search/search.component.ts b/frontend/src/app/dashboard/component/user/search/search.component.ts index 7ef7d22c90..db27a92c7a 100644 --- a/frontend/src/app/dashboard/component/user/search/search.component.ts +++ b/frontend/src/app/dashboard/component/user/search/search.component.ts @@ -62,7 +62,6 @@ export class SearchComponent implements AfterViewInit { private isLogin = this.userService.isLogin(); private includePublic = true; currentUid = this.userService.getCurrentUser()?.uid; - searchKeywords: string[] = []; selectedType: "workflow" | "dataset" | "model" | null = null; @@ -112,16 +111,11 @@ export class SearchComponent implements AfterViewInit { this.updateMasterFilterList(); } - this.searchKeywords = this.filters.getSearchKeywords(); this.cdr.detectChanges(); }); } async search(): Promise<void> { - // Keep the highlight keywords in sync with the current filters. This is read - // by the template's search-results binding; the template must not call the - // `filters` getter directly, since it throws until the ViewChild resolves. - this.searchKeywords = this.filters.getSearchKeywords(); const sameList = this.filters.masterFilterList.length === this.masterFilterList.length && this.filters.masterFilterList.every((v, i) => v === this.masterFilterList[i]); diff --git a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.html b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.html index 18604d4273..9e5c03dd89 100644 --- a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.html +++ b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.html @@ -66,8 +66,6 @@ <div class="search-result"> <texera-search-results - [showResourceTypes]="true" - [searchKeywords]="searchKeywords" [currentUid]="this.currentUid" [viewMode]="isVersionedResource ? viewMode : 'list'" [cardTemplate]="isVersionedResource ? cardTpl : undefined"> diff --git a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.spec.ts b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.spec.ts index 56df200a84..fd16d9d54d 100644 --- a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.spec.ts +++ b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.spec.ts @@ -80,7 +80,6 @@ class StubFiltersComponent { @Input() ownerScope?: string; masterFilterList: ReadonlyArray<string> = []; masterFilterListChange = new Subject<ReadonlyArray<string>>(); - getSearchKeywords = vi.fn(() => [] as string[]); getSearchFilterParameters = vi.fn(() => ({})); } @@ -90,8 +89,6 @@ class StubFiltersComponent { template: "", }) class StubSearchResultsComponent { - @Input() showResourceTypes?: boolean; - @Input() searchKeywords?: string[]; @Input() currentUid?: number; @Input() viewMode?: string; @Input() cardTemplate?: TemplateRef<unknown>; @@ -109,7 +106,6 @@ class StubCardItemComponent { interface FiltersMock { masterFilterList: ReadonlyArray<string>; - getSearchKeywords: ReturnType<typeof vi.fn>; getSearchFilterParameters: ReturnType<typeof vi.fn>; masterFilterListChange: Subject<ReadonlyArray<string>>; } @@ -164,7 +160,6 @@ describe("HubSearchResultComponent", () => { function makeFiltersMock(list: ReadonlyArray<string> = ["a"]): FiltersMock { return { masterFilterList: list, - getSearchKeywords: vi.fn(() => ["k"]), getSearchFilterParameters: vi.fn(() => ({})), masterFilterListChange: new Subject<ReadonlyArray<string>>(), }; @@ -308,7 +303,7 @@ describe("HubSearchResultComponent", () => { await component.search(); - expect(filters.getSearchKeywords).not.toHaveBeenCalled(); + expect(filters.getSearchFilterParameters).not.toHaveBeenCalled(); expect(searchServiceMock.executeSearch).not.toHaveBeenCalled(); }); @@ -323,7 +318,6 @@ describe("HubSearchResultComponent", () => { expect(results.reset).toHaveBeenCalledTimes(1); expect(typeof results.reset.mock.calls[0][0]).toBe("function"); expect(results.loadMore).toHaveBeenCalledTimes(1); - expect(component.searchKeywords).toEqual(["k"]); }); it("skips a repeated search with the same filter list and sortMethod, but honors forced=true", async () => { @@ -637,19 +631,11 @@ describe("HubSearchResultComponent rendered template", () => { expect(results().cardTemplate).toBeUndefined(); }); - it("hands the resource types, the filter keywords and the signed-in uid to the results list", () => { + it("hands the signed-in uid to the results list", () => { render(EntityType.Workflow); - const filters = fixture.debugElement.query(By.directive(FiltersComponent)).componentInstance as FiltersComponent; - // Committing a filter list is what the real filter bar does on every change, and it - // is what makes the component republish its keywords. - filters.masterFilterList = ["alpha"]; - fixture.detectChanges(); - - // Asserted on the child inputs rather than the DOM because all three only reach the + // Asserted on the child input rather than the DOM because currentUid only reaches the // markup through texera-list-item, which is not rendered while the result list is empty. - expect(results().showResourceTypes).toBe(true); - expect(results().searchKeywords).toEqual(["alpha"]); expect(results().currentUid).toBe(MOCK_USER_ID); }); }); diff --git a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.ts b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.ts index cfe9c59e3a..e2608a6fbe 100644 --- a/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.ts +++ b/frontend/src/app/hub/component/hub-search-result/hub-search-result.component.ts @@ -74,7 +74,6 @@ export class HubSearchResultComponent implements OnInit, AfterViewInit { return this.entityType === EntityType.Dataset || this.entityType === EntityType.Model; } - public searchKeywords: string[] = []; currentUid = this.userService.getCurrentUser()?.uid; public viewMode: SearchResultsViewMode = localStorage.getItem(HUB_VIEW_MODE_STORAGE_KEY) === "card" ? "card" : "list"; @@ -155,7 +154,6 @@ export class HubSearchResultComponent implements OnInit, AfterViewInit { } this.lastSortMethod = this.sortMethod; this.masterFilterList = this.filters.masterFilterList; - this.searchKeywords = this.filters.getSearchKeywords(); let filterParams = this.filters.getSearchFilterParameters(); this.searchResultsComponent.reset((start, count) => {
