You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/07/10 22:51:36 UTC
(texera) branch gh-readonly-queue/main/pr-6320-3e08ebb2f795c8e630cb06b9f2da90a40e1bca77 created (now cc016adb6d)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-6320-3e08ebb2f795c8e630cb06b9f2da90a40e1bca77
in repository https://gitbox.apache.org/repos/asf/texera.git
at cc016adb6d fix(dashboard): sort datasets by creation time (newest first) (#6320)
This branch includes the following new commits:
new cc016adb6d fix(dashboard): sort datasets by creation time (newest first) (#6320)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(texera) 01/01: fix(dashboard): sort datasets by creation time (newest first) (#6320)
Posted by gi...@apache.org.
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-6320-3e08ebb2f795c8e630cb06b9f2da90a40e1bca77
in repository https://gitbox.apache.org/repos/asf/texera.git
commit cc016adb6d5854cd2beca21eb2bedcfe2e486a41
Author: Tanishq Gandhi <56...@users.noreply.github.com>
AuthorDate: Fri Jul 10 15:51:13 2026 -0700
fix(dashboard): sort datasets by creation time (newest first) (#6320)
### What changes were proposed in this PR?
The **Datasets** listing did not show newly created datasets first —
they appeared in an effectively undefined order.
**Root cause:** the datasets listing defaulted to `EditTimeDesc`, but
datasets have no "last modified" timestamp. `DatasetSearchQueryBuilder`
never maps
`lastModifiedTime`, so it falls back to `NULL` for every dataset in
`UnifiedResourceSchema`. The resulting `ORDER BY
resourceLastModifiedTime DESC NULLS LAST` ties on `NULL` for all rows,
so the database returns datasets in an arbitrary order and creation time
has no effect. The "Your Work" datasets page
also had no sort control at all, so there was no way to notice or work
around it. The Hub's dataset view shared the same latent bug.
This PR:
1. **Default the datasets listing to `CreateTimeDesc`** (newest first)
on both the "Your Work" datasets page and the Hub dataset view —
datasets do have a populated `creation_time`.
2. **Add the shared sort button to the "Your Work" datasets page**,
which previously had none, laid out consistently with the Workflows page
(`Create Dataset → [ Sort · List · Card ] → Filters`).
3. **Make `SortButtonComponent` reusable** by adding `showEditTime` and
`showExecutionTime` inputs (both default `true`). Datasets have neither
an edit nor an execution time, so those two options are hidden for
datasets to prevent them from re-introducing the `NULL`-ordering
behavior. Workflows, Search, and the Hub's workflow view are unchanged.
No backend or schema changes.
### Any related issues, documentation, discussions?
Closes #6215
### How was this PR tested?
- Updated/added frontend unit tests:
- `SortButtonComponent` — new tests covering the `showEditTime` /
`showExecutionTime` inputs and their defaults.
- `UserDatasetComponent` — asserts the default sort is `CreateTimeDesc`.
- All affected specs pass (`sort-button` 8/8, `user-dataset` 18/18).
- Full production build (`ng build`) passes with no template/type
errors.
- Manually verified on the datasets page and also Confirmed the same on
the Hub dataset view, and that Workflows / Search still show all sort
options.
Screenshot shows the datasets page in Your Work section
<img width="1220" height="721" alt="Screenshot 2026-07-10 at 2 01 08 PM"
src="https://github.com/user-attachments/assets/e6a5c0ac-66a6-45a5-987c-00f4a0b34eb6"
/>
Screenshot shows the datasets page in Hub's section
<img width="1436" height="624" alt="Screenshot 2026-07-10 at 1 59 28 PM"
src="https://github.com/user-attachments/assets/97912400-e156-4396-b750-45a8097f5a66"
/>
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)
---------
Signed-off-by: Xinyuan Lin <xi...@uci.edu>
Co-authored-by: Claude Opus 4.8 <no...@anthropic.com>
Co-authored-by: Xinyuan Lin <xi...@uci.edu>
Co-authored-by: Copilot Autofix powered by AI <17...@users.noreply.github.com>
---
.../user/sort-button/sort-button.component.html | 4 ++
.../user/sort-button/sort-button.component.spec.ts | 17 ++++++++
.../user/sort-button/sort-button.component.ts | 10 ++++-
.../user/user-dataset/user-dataset.component.html | 46 ++++++++++++----------
.../user-dataset/user-dataset.component.spec.ts | 7 ++++
.../user/user-dataset/user-dataset.component.ts | 9 ++++-
.../hub-search-result.component.html | 5 ++-
.../hub-search-result.component.ts | 3 ++
8 files changed, 77 insertions(+), 24 deletions(-)
diff --git a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.html b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.html
index d3a2aadd93..740d73aede 100644
--- a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.html
+++ b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.html
@@ -34,6 +34,7 @@
<nz-dropdown-menu #sortOptions="nzDropdownMenu">
<ul nz-menu>
+ @if (showEditTime) {
<li nz-menu-item>
<button
(click)="lastSort()"
@@ -41,6 +42,7 @@
By Edit Time
</button>
</li>
+ }
<li nz-menu-item>
<button
(click)="dateSort()"
@@ -48,6 +50,7 @@
By Create Time
</button>
</li>
+ @if (showExecutionTime) {
<li nz-menu-item>
<button
(click)="execSort()"
@@ -55,6 +58,7 @@
By Execution Time
</button>
</li>
+ }
<li nz-menu-item>
<button
(click)="ascSort()"
diff --git a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.spec.ts b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.spec.ts
index 516309e2a0..10ad6c1fac 100644
--- a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.spec.ts
+++ b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.spec.ts
@@ -76,4 +76,21 @@ describe("SortButtonComponent", () => {
expect(component.sortMethod).toBe(SortMethod.ExecutionTimeDesc);
expect(emitSpy).toHaveBeenCalledWith(SortMethod.ExecutionTimeDesc);
});
+
+ // Note: the sort options render inside an nz-dropdown-menu (a CDK overlay) that
+ // does not attach under the vitest/jsdom test environment, so we can't assert on
+ // the rendered menu text. We instead verify the input contract that the template's
+ // @if guards bind to (showEditTime / showExecutionTime).
+ it("shows the edit-time and execution-time options by default (e.g. for workflows)", () => {
+ expect(component.showEditTime).toBe(true);
+ expect(component.showExecutionTime).toBe(true);
+ });
+
+ it("can hide edit-time and execution-time options (e.g. for datasets, which have neither)", () => {
+ component.showEditTime = false;
+ component.showExecutionTime = false;
+ fixture.detectChanges();
+ expect(component.showEditTime).toBe(false);
+ expect(component.showExecutionTime).toBe(false);
+ });
});
diff --git a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.ts b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.ts
index 3282784d07..6ab39b7197 100644
--- a/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.ts
+++ b/frontend/src/app/dashboard/component/user/sort-button/sort-button.component.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { Component, EventEmitter, Output } from "@angular/core";
+import { Component, EventEmitter, Input, Output } from "@angular/core";
import { SortMethod } from "../../../type/sort-method";
import { NzDropdownADirective, NzDropdownDirective, NzDropdownMenuComponent } from "ng-zorro-antd/dropdown";
import { NzSpaceCompactItemDirective } from "ng-zorro-antd/space";
@@ -47,6 +47,14 @@ import { NzMenuDirective, NzMenuItemComponent } from "ng-zorro-antd/menu";
export class SortButtonComponent {
@Output()
public sortMethodChange = new EventEmitter<SortMethod>();
+
+ // Some resource types (e.g. datasets) have no edit or execution timestamp; hide the
+ // corresponding options so they can't produce an undefined (NULL) sort order.
+ @Input()
+ public showEditTime = true;
+ @Input()
+ public showExecutionTime = true;
+
public sortMethod = SortMethod.EditTimeDesc;
public lastSort(): void {
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 1c08a580e4..d9f6f62cbb 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
@@ -32,26 +32,32 @@
nzTheme="outline"></i>
<span>Create Dataset</span>
</button>
- <button
- nz-button
- title="List View"
- (click)="setViewType('list')"
- [nzType]="viewType === 'list' ? 'primary' : 'default'">
- <i
- nz-icon
- nzType="bars"
- nzTheme="outline"></i>
- </button>
- <button
- nz-button
- title="Card View"
- (click)="setViewType('card')"
- [nzType]="viewType === 'card' ? 'primary' : 'default'">
- <i
- nz-icon
- nzType="appstore"
- nzTheme="outline"></i>
- </button>
+ <nz-space-compact class="utility-button-group">
+ <texera-sort-button
+ [showEditTime]="false"
+ [showExecutionTime]="false"
+ (sortMethodChange)="sortMethod = $event; search()"></texera-sort-button>
+ <button
+ nz-button
+ title="List View"
+ (click)="setViewType('list')"
+ [nzType]="viewType === 'list' ? 'primary' : 'default'">
+ <i
+ nz-icon
+ nzType="bars"
+ nzTheme="outline"></i>
+ </button>
+ <button
+ nz-button
+ title="Card View"
+ (click)="setViewType('card')"
+ [nzType]="viewType === 'card' ? 'primary' : 'default'">
+ <i
+ nz-icon
+ nzType="appstore"
+ nzTheme="outline"></i>
+ </button>
+ </nz-space-compact>
<texera-filters #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 0f1386bf19..1806e51735 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
@@ -130,6 +130,13 @@ describe("UserDatasetComponent", () => {
});
});
+ describe("default sort", () => {
+ it("defaults to CreateTimeDesc so newest datasets appear first", () => {
+ // Datasets have no last-modified time, so EditTimeDesc would leave the sort key NULL.
+ expect(component.sortMethod).toBe(SortMethod.CreateTimeDesc);
+ });
+ });
+
describe("ngAfterViewInit", () => {
it("subscribes to userChanged and calls search on each emission", () => {
const searchSpy = vi.spyOn(component, "search").mockResolvedValue();
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 6ac60916c2..88ace52081 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
@@ -28,6 +28,7 @@ import { DashboardEntry } from "../../../type/dashboard-entry";
import { SearchResultsComponent } from "../search-results/search-results.component";
import { CardItemComponent } from "../list-item/card-item/card-item.component";
import { FiltersComponent } from "../filters/filters.component";
+import { SortButtonComponent } from "../sort-button/sort-button.component";
import { firstValueFrom } from "rxjs";
import { USER_DATASET } from "../../../../app-routing.constant";
import { NzModalService } from "ng-zorro-antd/modal";
@@ -36,7 +37,7 @@ import { DashboardDataset } from "../../../type/dashboard-dataset.interface";
import { NzMessageService } from "ng-zorro-antd/message";
import { map, tap } from "rxjs/operators";
import { NzCardComponent } from "ng-zorro-antd/card";
-import { NzSpaceCompactItemDirective } from "ng-zorro-antd/space";
+import { NzSpaceCompactItemDirective, NzSpaceCompactComponent } from "ng-zorro-antd/space";
import { NzButtonComponent } from "ng-zorro-antd/button";
import { NzWaveDirective } from "ng-zorro-antd/core/wave";
import { ɵNzTransitionPatchDirective } from "ng-zorro-antd/core/transition-patch";
@@ -53,11 +54,13 @@ import { FormsModule } from "@angular/forms";
imports: [
NzCardComponent,
NzSpaceCompactItemDirective,
+ NzSpaceCompactComponent,
NzButtonComponent,
NzWaveDirective,
ɵNzTransitionPatchDirective,
NzIconDirective,
FiltersComponent,
+ SortButtonComponent,
FiltersInstructionsComponent,
NzSelectComponent,
FormsModule,
@@ -67,7 +70,9 @@ import { FormsModule } from "@angular/forms";
})
export class UserDatasetComponent implements AfterViewInit {
private static readonly VIEW_MODE_STORAGE_KEY = "texera.userDataset.viewMode";
- public sortMethod = SortMethod.EditTimeDesc;
+ // 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.
+ public sortMethod = SortMethod.CreateTimeDesc;
lastSortMethod: SortMethod | null = null;
public isLogin = this.userService.isLogin();
public currentUid = this.userService.getCurrentUser()?.uid;
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 15bce4a703..112b65d580 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
@@ -20,7 +20,10 @@
<div class="search-container">
<div class="search-section">
<div class="filter">
- <texera-sort-button (sortMethodChange)="sortMethod = $event; search()"></texera-sort-button>
+ <texera-sort-button
+ [showEditTime]="searchType !== 'dataset'"
+ [showExecutionTime]="searchType !== 'dataset'"
+ (sortMethodChange)="sortMethod = $event; search()"></texera-sort-button>
<texera-filters #filters></texera-filters>
<div
*ngIf="searchType === 'dataset'"
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 2cb582c4e9..15f576bb01 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
@@ -110,6 +110,9 @@ export class HubSearchResultComponent implements OnInit, AfterViewInit {
const url = this.router.url;
if (url.includes("dataset")) {
this.searchType = "dataset";
+ // Datasets have no last-modified/execution time, so EditTimeDesc leaves the sort key NULL.
+ // Default to CreateTimeDesc so newly created datasets appear first.
+ this.sortMethod = SortMethod.CreateTimeDesc;
} else if (url.includes("workflow")) {
this.searchType = "workflow";
}