This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new eddec267a2 fix(frontend, amber): source filter owners per resource
kind and apply them to datasets (#8060)
eddec267a2 is described below
commit eddec267a2c6974d0ea0f29b63e9c7506e12f9b4
Author: Tanishq Gandhi <[email protected]>
AuthorDate: Fri Aug 28 00:20:14 2026 +0000
fix(frontend, amber): source filter owners per resource kind and apply them
to datasets (#8060)
### What changes were proposed in this PR?
The Owner filter on the Datasets pages was broken on both sides:
1. **Wrong list.** `<texera-filters>` always read its Owner and ID
dropdowns from `WorkflowPersistService`, so Datasets listed workflow
owners and offered a workflow-ID filter.
2. **No effect.** `VersionedResourceSearchQueryBuilder` applied the
date, id and full-text filters but dropped `params.owners`, so selecting
an owner changed nothing.
```
Before: Datasets -> filters -> workflowPersistService.retrieveOwners() ->
workflow owners
owner=<email> -> VersionedResourceSearchQueryBuilder ->
ignored
After: Datasets -> filters -> datasetService.retrieveOwners() ->
dataset owners
owner=<email> -> VersionedResourceSearchQueryBuilder ->
USER.EMAIL predicate
```
Before -
<img width="1239" height="533" alt="Screenshot 2026-08-27 at 3 36 49 PM"
src="https://github.com/user-attachments/assets/ca1f0055-17d3-46cb-b4c8-65a1005bec5f"
/>
After -
<img width="1227" height="598" alt="Screenshot 2026-08-27 at 4 41 05 PM"
src="https://github.com/user-attachments/assets/294335e6-6028-44c2-af46-c2ad19781c97"
/>
- `filters.component.ts` gains `@Input() entityType`, defaulting to
`Workflow`, so the Workflows and
unified search pages are untouched.
- `VersionedResourceSearchQueryBuilder` adds the
`getContainsFilter(params.owners, USER.EMAIL)` the
workflow builder already uses. The `USER` join was already in the FROM
clause.
- The id dropdown hides where no id endpoint exists. Adding
`/dataset/user-dataset-ids` and
`/model/user-model-ids` is left to a follow-up feature.
### Any related issues, documentation, discussions?
Closes #8059.
### How was this PR tested?
Five new tests in `filters.component.spec.ts` (owners per kind, ids only
for workflows, dropdown
hidden for datasets) and three in `DatasetSearchQueryBuilderSpec` (one
owner renders the predicate,
several OR together but AND with the id filter, none renders nothing).
```bash
cd frontend && npx ng test $(grep -rl "FiltersComponent\|DatasetService"
src/app | grep "spec.ts$" | sed 's/^/--include /' | tr '\n' ' ')
sbt 'testOnly *DatasetSearchQueryBuilderSpec'
```
909 frontend tests, 21 backend, all passing. Plus `tsc --noEmit`,
eslint, prettier, `scalafmtCheck`.
Manual: signed in as a user with a shared dataset plus their own
workflow, the Datasets page now
lists only the dataset's owner, ticking it narrows the list, and the id
dropdown is gone. Workflows
page unchanged.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code Opus 5
---
.../VersionedResourceSearchQueryBuilder.scala | 2 +
.../dashboard/DatasetSearchQueryBuilderSpec.scala | 27 ++++++
.../component/user/filters/filters.component.html | 2 +-
.../user/filters/filters.component.spec.ts | 97 ++++++++++++++++++++++
.../component/user/filters/filters.component.ts | 45 ++++++----
.../user/user-dataset/user-dataset.component.html | 4 +-
.../user-dataset/user-dataset.component.spec.ts | 10 ++-
.../user/user-dataset/user-dataset.component.ts | 2 +
.../hub-search-result.component.html | 4 +-
.../hub-search-result.component.spec.ts | 7 +-
.../hub-search-result.component.ts | 7 ++
11 files changed, 186 insertions(+), 21 deletions(-)
diff --git
a/amber/src/main/scala/org/apache/texera/web/resource/dashboard/VersionedResourceSearchQueryBuilder.scala
b/amber/src/main/scala/org/apache/texera/web/resource/dashboard/VersionedResourceSearchQueryBuilder.scala
index a1e00ec45a..8893c20395 100644
---
a/amber/src/main/scala/org/apache/texera/web/resource/dashboard/VersionedResourceSearchQueryBuilder.scala
+++
b/amber/src/main/scala/org/apache/texera/web/resource/dashboard/VersionedResourceSearchQueryBuilder.scala
@@ -24,6 +24,7 @@ import
org.apache.texera.web.resource.dashboard.FulltextSearchQueryUtils.{
getDateFilter,
getFullTextSearchFilter
}
+import org.apache.texera.dao.jooq.generated.tables.User.USER
import org.jooq.impl.DSL
import org.jooq.{Condition, GroupField, Record, TableLike}
@@ -78,6 +79,7 @@ abstract class VersionedResourceSearchQueryBuilder[Rec <:
Record, P](
tables.creationTimeColumn
)
.and(getContainsFilter(tables.searchIds(params), tables.idColumn))
+ .and(getContainsFilter(params.owners, USER.EMAIL))
.and(
getFullTextSearchFilter(splitKeywords, List(tables.nameColumn,
tables.descriptionColumn))
)
diff --git
a/amber/src/test/scala/org/apache/texera/web/resource/dashboard/DatasetSearchQueryBuilderSpec.scala
b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/DatasetSearchQueryBuilderSpec.scala
index cc60e1853e..e585848d3c 100644
---
a/amber/src/test/scala/org/apache/texera/web/resource/dashboard/DatasetSearchQueryBuilderSpec.scala
+++
b/amber/src/test/scala/org/apache/texera/web/resource/dashboard/DatasetSearchQueryBuilderSpec.scala
@@ -448,6 +448,33 @@ class DatasetSearchQueryBuilderSpec
sql should include(s"texera_db.dataset.did = $sizedDid and (")
}
+ it should "filter on the owner's email, the way the workflow builder does"
in {
+ val p = SearchQueryParams(owners =
List("[email protected]").asJava)
+
+ sqlFor(uid, includePublic = true, p) should include(
+ "texera_db.user.email = '[email protected]'"
+ )
+ }
+
+ it should "OR several owners together, and AND them with the other filters"
in {
+ val p = SearchQueryParams(
+ owners = List("[email protected]", "[email protected]").asJava,
+ datasetIds = List(sizedDid).asJava
+ )
+ val sql = sqlFor(uid, includePublic = true, p)
+
+ // ORed with each other: ANDing two owners would always return nothing.
+ sql should include("texera_db.user.email = '[email protected]'")
+ sql should include("texera_db.user.email = '[email protected]'")
+ sql should include("or texera_db.user.email")
+ // ... but ANDed with the id filter.
+ sql should include(s"texera_db.dataset.did = $sizedDid and (")
+ }
+
+ it should "add no owner predicate when the caller selected none" in {
+ sqlFor(uid, includePublic = true) should not include "texera_db.user.email
="
+ }
+
"the query" should "dedupe with selectDistinct rather than a group by" in {
// getGroupByFields is empty here, unlike the workflow and project
builders, so the DISTINCT is
// the only thing collapsing the rows the access join multiplies out.
diff --git
a/frontend/src/app/dashboard/component/user/filters/filters.component.html
b/frontend/src/app/dashboard/component/user/filters/filters.component.html
index 01d89c8282..977e204cf6 100644
--- a/frontend/src/app/dashboard/component/user/filters/filters.component.html
+++ b/frontend/src/app/dashboard/component/user/filters/filters.component.html
@@ -106,7 +106,7 @@
</nz-dropdown-menu>
<a
- *ngIf="this.isLogin"
+ *ngIf="this.isLogin && hasIdFilter"
[nzDropdownMenu]="IDSearchOptions"
nz-dropdown
nzTrigger="click"
diff --git
a/frontend/src/app/dashboard/component/user/filters/filters.component.spec.ts
b/frontend/src/app/dashboard/component/user/filters/filters.component.spec.ts
index 9fab7d2a07..e6aad3859a 100644
---
a/frontend/src/app/dashboard/component/user/filters/filters.component.spec.ts
+++
b/frontend/src/app/dashboard/component/user/filters/filters.component.spec.ts
@@ -38,6 +38,10 @@ import { MOCK_USER, StubUserService } from
"src/app/common/service/user/stub-use
import { UserProjectService } from
"src/app/dashboard/service/user/project/user-project.service";
import { StubUserProjectService } from
"src/app/dashboard/service/user/project/stub-user-project.service";
import { NotificationService } from
"src/app/common/service/notification/notification.service";
+import { DatasetService } from
"src/app/dashboard/service/user/dataset/dataset.service";
+import { EntityType } from "src/app/hub/service/hub.service";
+import { By } from "@angular/platform-browser";
+import { of } from "rxjs";
describe("FiltersComponent", () => {
let component: FiltersComponent;
@@ -66,6 +70,7 @@ describe("FiltersComponent", () => {
{ provide: OperatorMetadataService, useClass:
StubOperatorMetadataService },
{ provide: UserService, useClass: StubUserService },
{ provide: UserProjectService, useClass: StubUserProjectService },
+ { provide: DatasetService, useValue: { retrieveOwners: vi.fn(() =>
of([])) } },
provideNzI18n(en_US),
...commonTestProviders,
],
@@ -493,3 +498,95 @@ describe("FiltersComponent", () => {
});
});
});
+
+/** The bar is shared by several pages; these pin that it sources owners and
ids per kind. */
+describe("FiltersComponent per-resource owners", () => {
+ let fixture: ComponentFixture<FiltersComponent>;
+ let component: FiltersComponent;
+ let datasetOwners: ReturnType<typeof vi.fn>;
+ let workflowOwners: ReturnType<typeof vi.fn>;
+ let workflowIds: ReturnType<typeof vi.fn>;
+
+ /** The input has to be set before ngOnInit reads it. */
+ async function render(entityType?: EntityType): Promise<void> {
+ datasetOwners = vi.fn(() => of(["dataset-owner"]));
+ workflowOwners = vi.fn(() => of(["workflow-owner"]));
+ workflowIds = vi.fn(() => of([7]));
+
+ await TestBed.configureTestingModule({
+ providers: [
+ JwtHelperService,
+ { provide: JWT_OPTIONS, useValue: {} },
+ {
+ provide: WorkflowPersistService,
+ useValue: { retrieveOwners: workflowOwners, retrieveWorkflowIDs:
workflowIds },
+ },
+ { provide: DatasetService, useValue: { retrieveOwners: datasetOwners }
},
+ { provide: OperatorMetadataService, useClass:
StubOperatorMetadataService },
+ { provide: UserService, useClass: StubUserService },
+ { provide: UserProjectService, useClass: StubUserProjectService },
+ provideNzI18n(en_US),
+ ...commonTestProviders,
+ ],
+ imports: [FiltersComponent, NzModalModule, NzDropDownModule,
FormsModule, HttpClientTestingModule],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(FiltersComponent);
+ component = fixture.componentInstance;
+ if (entityType !== undefined) {
+ component.entityType = entityType;
+ }
+ fixture.detectChanges();
+ }
+
+ afterEach(() => {
+ const overlayContainer = TestBed.inject(OverlayContainer, null);
+ if (overlayContainer) {
+ overlayContainer.getContainerElement().innerHTML = "";
+ }
+ });
+
+ it("defaults to workflows, so the call sites that pass nothing are
unaffected", async () => {
+ await render();
+
+ expect(component.entityType).toBe(EntityType.Workflow);
+ expect(workflowOwners).toHaveBeenCalled();
+ expect(datasetOwners).not.toHaveBeenCalled();
+ expect(component.owners.map(owner =>
owner.userName)).toEqual(["workflow-owner"]);
+ });
+
+ it("lists dataset owners, not workflow owners, when filtering datasets",
async () => {
+ await render(EntityType.Dataset);
+
+ expect(datasetOwners).toHaveBeenCalled();
+ expect(workflowOwners).not.toHaveBeenCalled();
+ expect(component.owners.map(owner =>
owner.userName)).toEqual(["dataset-owner"]);
+ });
+
+ it("offers workflow ids only when filtering workflows", async () => {
+ await render(EntityType.Workflow);
+ expect(component.hasIdFilter).toBe(true);
+ expect(workflowIds).toHaveBeenCalled();
+ expect(component.wids.map(wid => wid.id)).toEqual(["7"]);
+ });
+
+ it("asks for no ids at all when filtering datasets, rather than showing
workflow ids", async () => {
+ await render(EntityType.Dataset);
+
+ expect(component.hasIdFilter).toBe(false);
+ expect(workflowIds).not.toHaveBeenCalled();
+ expect(component.wids).toEqual([]);
+ });
+
+ it("hides the id dropdown for a kind that has no ids to offer", async () => {
+ await render(EntityType.Dataset);
+
+
expect(fixture.debugElement.query(By.css(".search-wids-button"))).toBeNull();
+ });
+
+ it("still renders the id dropdown for workflows", async () => {
+ await render(EntityType.Workflow);
+
+
expect(fixture.debugElement.query(By.css(".search-wids-button"))).not.toBeNull();
+ });
+});
diff --git
a/frontend/src/app/dashboard/component/user/filters/filters.component.ts
b/frontend/src/app/dashboard/component/user/filters/filters.component.ts
index 85da98d0e0..824ace5d44 100644
--- a/frontend/src/app/dashboard/component/user/filters/filters.component.ts
+++ b/frontend/src/app/dashboard/component/user/filters/filters.component.ts
@@ -25,6 +25,8 @@ import { DashboardProject } from
"../../../type/dashboard-project.interface";
import { NotificationService } from
"src/app/common/service/notification/notification.service";
import { UserProjectService } from
"../../../service/user/project/user-project.service";
import { WorkflowPersistService } from
"src/app/common/service/workflow-persist/workflow-persist.service";
+import { DatasetService } from "../../../service/user/dataset/dataset.service";
+import { EntityType } from "../../../../hub/service/hub.service";
import { SearchFilterParameters } from
"../../../type/search-filter-parameters";
import { UserService } from "../../../../common/service/user/user.service";
import { switchMap } from "rxjs/operators";
@@ -71,6 +73,8 @@ export class FiltersComponent implements OnInit {
private _masterFilterList: ReadonlyArray<string> = [];
// receive input from parent components (UserProjectSection), if any
@Input() public pid?: number = undefined;
+ /** Which resource kind this page lists; decides whose owners and ids are
offered. */
+ @Input() public entityType: EntityType = EntityType.Workflow;
@Output()
public masterFilterListChange = new EventEmitter<typeof
this._masterFilterList>();
public get masterFilterList(): ReadonlyArray<string> {
@@ -121,9 +125,21 @@ export class FiltersComponent implements OnInit {
private notificationService: NotificationService,
private userProjectService: UserProjectService,
private workflowPersistService: WorkflowPersistService,
+ private datasetService: DatasetService,
private cdr: ChangeDetectorRef
) {}
+ /** Only workflows expose an id-listing endpoint. */
+ public get hasIdFilter(): boolean {
+ return this.entityType === EntityType.Workflow;
+ }
+
+ private retrieveOwners(): Observable<string[]> {
+ return this.entityType === EntityType.Dataset
+ ? this.datasetService.retrieveOwners()
+ : this.workflowPersistService.retrieveOwners();
+ }
+
ngOnInit(): void {
this.setupUserProject();
this.searchParameterBackendSetup();
@@ -157,9 +173,7 @@ export class FiltersComponent implements OnInit {
});
}
- /**
- * Backend calls for Workflow IDs, Owners, and Operators in saved workflow
component
- */
+ /** Backend calls for the filtered kind's owners and ids, plus the operator
metadata. */
private searchParameterBackendSetup() {
this.operatorMetadataService
.getOperatorMetadata()
@@ -183,23 +197,24 @@ export class FiltersComponent implements OnInit {
this.operatorGroups = opdata.groups.map(group => group.groupName);
});
if (this.isLogin) {
- this.workflowPersistService
- .retrieveOwners()
+ this.retrieveOwners()
.pipe(untilDestroyed(this))
.subscribe(list_of_owners => {
this.owners = list_of_owners.map(i => ({ userName: i, checked: false
}));
});
- this.workflowPersistService
- .retrieveWorkflowIDs()
- .pipe(untilDestroyed(this))
- .subscribe(wids => {
- this.wids = wids.map(wid => {
- return {
- id: wid.toString(),
- checked: false,
- };
+ if (this.hasIdFilter) {
+ this.workflowPersistService
+ .retrieveWorkflowIDs()
+ .pipe(untilDestroyed(this))
+ .subscribe(wids => {
+ this.wids = wids.map(wid => {
+ return {
+ id: wid.toString(),
+ checked: false,
+ };
+ });
});
- });
+ }
}
}
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 d9f6f62cbb..87a1db132b 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
@@ -58,7 +58,9 @@
nzTheme="outline"></i>
</button>
</nz-space-compact>
- <texera-filters #filters></texera-filters>
+ <texera-filters
+ [entityType]="entityType"
+ #filters></texera-filters>
</div>
</nz-card>
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 30d27d96d6..f80b956e31 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
@@ -504,7 +504,10 @@ describe("UserDatasetComponent rendering", () => {
{ provide: NzModalService, useValue: { create: vi.fn() } },
{ provide: UserService, useClass: StubUserService },
{ provide: SearchService, useValue: { executeSearch: searchSpy } },
- { provide: DatasetService, useValue: { deleteDatasets: vi.fn(() =>
of({} as Response)) } },
+ {
+ provide: DatasetService,
+ useValue: { deleteDatasets: vi.fn(() => of({} as Response)),
retrieveOwners: vi.fn(() => of([])) },
+ },
{ provide: NzMessageService, useValue: { warning: vi.fn() } },
// ng-zorro defaults to zh-cn and throws NG0701 without locale data;
the app registers en_US.
{ provide: NZ_I18N, useValue: en_US },
@@ -705,7 +708,10 @@ describe("UserDatasetComponent card view", () => {
),
},
},
- { provide: DatasetService, useValue: { deleteDatasets:
deleteDatasetsSpy } },
+ {
+ provide: DatasetService,
+ useValue: { deleteDatasets: deleteDatasetsSpy, retrieveOwners:
vi.fn(() => of([])) },
+ },
{ provide: NzMessageService, useValue: { warning: vi.fn() } },
{ provide: NZ_I18N, useValue: en_US },
provideRouter([]),
diff --git
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts
index 88ace52081..409f55218f 100644
---
a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts
+++
b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.ts
@@ -45,6 +45,7 @@ import { NzIconDirective } from "ng-zorro-antd/icon";
import { FiltersInstructionsComponent } from
"../filters-instructions/filters-instructions.component";
import { NzSelectComponent } from "ng-zorro-antd/select";
import { FormsModule } from "@angular/forms";
+import { EntityType } from "../../../../hub/service/hub.service";
@UntilDestroy()
@Component({
@@ -69,6 +70,7 @@ import { FormsModule } from "@angular/forms";
],
})
export class UserDatasetComponent implements AfterViewInit {
+ public readonly entityType = EntityType.Dataset;
private static readonly VIEW_MODE_STORAGE_KEY =
"texera.userDataset.viewMode";
// Datasets have no "last modified" timestamp, so EditTimeDesc leaves the
sort key NULL for every
// row and produces an undefined order. Default to CreateTimeDesc so newly
created datasets appear first.
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 112b65d580..6f4a273ad2 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
@@ -24,7 +24,9 @@
[showEditTime]="searchType !== 'dataset'"
[showExecutionTime]="searchType !== 'dataset'"
(sortMethodChange)="sortMethod = $event;
search()"></texera-sort-button>
- <texera-filters #filters></texera-filters>
+ <texera-filters
+ [entityType]="filterEntityType"
+ #filters></texera-filters>
<div
*ngIf="searchType === 'dataset'"
class="view-toggle">
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 cfc5a4936a..5d221442bc 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
@@ -41,6 +41,7 @@ import { UserService } from
"../../../common/service/user/user.service";
import { MOCK_USER_ID, StubUserService } from
"../../../common/service/user/stub-user.service";
import { SearchService } from "../../../dashboard/service/user/search.service";
import { commonTestProviders } from "../../../common/testing/test-utils";
+import { EntityType } from "../../service/hub.service";
import { OperatorMetadataService } from
"../../../workspace/service/operator-metadata/operator-metadata.service";
import { StubOperatorMetadataService } from
"../../../workspace/service/operator-metadata/stub-operator-metadata.service";
import { UserProjectService } from
"../../../dashboard/service/user/project/user-project.service";
@@ -77,6 +78,7 @@ class StubSortButtonComponent {
providers: [{ provide: FiltersComponent, useExisting: forwardRef(() =>
StubFiltersComponent) }],
})
class StubFiltersComponent {
+ @Input() entityType?: EntityType;
masterFilterList: ReadonlyArray<string> = [];
masterFilterListChange = new Subject<ReadonlyArray<string>>();
getSearchKeywords = vi.fn(() => [] as string[]);
@@ -482,7 +484,10 @@ describe("HubSearchResultComponent rendered template", ()
=> {
{ provide: OperatorMetadataService, useClass:
StubOperatorMetadataService },
{ provide: UserProjectService, useClass: StubUserProjectService },
{ provide: WorkflowPersistService, useValue: new
StubWorkflowPersistService([]) },
- { provide: DatasetService, useValue: { getDatasetCoverUrl: vi.fn(() =>
of({ url: undefined })) } },
+ {
+ provide: DatasetService,
+ useValue: { getDatasetCoverUrl: vi.fn(() => of({ url: undefined })),
retrieveOwners: vi.fn(() => of([])) },
+ },
{ provide: WorkflowCoverService, useValue: { getCover: vi.fn(() =>
of(undefined)) } },
NzModalService,
provideNzI18n(en_US),
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 15f576bb01..35e916b05e 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
@@ -37,6 +37,7 @@ import { isDefined } from "../../../common/util/predicate";
import { firstValueFrom } from "rxjs";
import { map } from "rxjs/operators";
import { SortButtonComponent } from
"../../../dashboard/component/user/sort-button/sort-button.component";
+import { EntityType } from "../../service/hub.service";
const HUB_DATASET_VIEW_MODE_STORAGE_KEY = "texera.hub.dataset.viewMode";
@@ -58,6 +59,12 @@ const HUB_DATASET_VIEW_MODE_STORAGE_KEY =
"texera.hub.dataset.viewMode";
})
export class HubSearchResultComponent implements OnInit, AfterViewInit {
public searchType: "dataset" | "workflow" = "workflow";
+
+ /** `searchType` as an EntityType, for the filters bar. */
+ public get filterEntityType(): EntityType {
+ return this.searchType === "dataset" ? EntityType.Dataset :
EntityType.Workflow;
+ }
+
public searchKeywords: string[] = [];
currentUid = this.userService.getCurrentUser()?.uid;
public viewMode: SearchResultsViewMode =