Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/(user-data)/my-models/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
trackJob,
TrackedJob,
} from '@/lib/api/jobTracker';
import { parseWorkspaceDate } from '@/lib/utils/date';

interface MyModelItem {
id: string; // Model name / filename
Expand Down Expand Up @@ -518,7 +519,7 @@ export default function MyModelsPage() {
headerName: 'Modification Date',
width: 220,
type: 'dateTime',
valueGetter: (_value, row) => (row.modDate ? new Date(row.modDate) : null),
valueGetter: (_value, row) => (row.modDate ? (parseWorkspaceDate(row.modDate) ?? new Date(row.modDate)) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
{
Expand Down
3 changes: 2 additions & 1 deletion app/(user-data)/myMedia/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { workspaceDelete } from '@/lib/api/workspace';
import { useAuth } from '@/components/auth/AuthProvider';
import DataControlHeader from '@/components/layout/DataControlHeader';
import ExportModal from '@/components/ui/ExportModal';
import { parseWorkspaceDate } from '@/lib/utils/date';

interface MyMediaItem {
id: string;
Expand Down Expand Up @@ -143,7 +144,7 @@ export default function MyMediaPage() {
headerName: 'Modification Date',
width: 250,
type: 'dateTime',
valueGetter: (_value, row) => (row.modDate ? new Date(row.modDate) : null),
valueGetter: (_value, row) => (row.modDate ? (parseWorkspaceDate(row.modDate) ?? new Date(row.modDate)) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
{
Expand Down
6 changes: 4 additions & 2 deletions app/data/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import DownloadIcon from '@mui/icons-material/Download';
import SearchIcon from '@mui/icons-material/Search';
import NextLink from 'next/link';
import { workspaceLs, workspaceDownloadUrl } from '@/lib/api/workspace';
import { parseWorkspaceDate } from '@/lib/utils/date';
import ShowMetadataDialog from '@/components/ui/ShowMetadataDialog';

interface WorkspaceItem {
Expand All @@ -53,7 +54,8 @@ function parseWorkspaceLsEntry(entry: unknown[], parentPath: string): WorkspaceI
const name = String(entry[0] || '');
const type = String(entry[1] || 'unknown');
const path = String(entry[2] || `${parentPath}/${name}`);
const timestamp = entry[3] ? new Date(String(entry[3])).toLocaleString() : '';
const rawTs = String(entry[3] || '');
const timestamp = rawTs;
const size = Number(entry[6]) || 0;
const owner = String(entry[5] || '');
const isFolder = type === 'folder' || type === 'modelfolder';
Expand Down Expand Up @@ -234,7 +236,7 @@ export default function DataBrowserPage({ params }: { params: Promise<{ path: st
headerName: 'Modified',
width: 160,
type: 'dateTime',
valueGetter: (_value, row) => (row.modDate ? new Date(row.modDate) : null),
valueGetter: (_value, row) => (row.modDate ? (parseWorkspaceDate(row.modDate) ?? new Date(row.modDate)) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
{
Expand Down
6 changes: 4 additions & 2 deletions app/fba/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ function extractFbaObjectRefsFromLs(payload: Record<string, unknown[]>): string[
if (type !== 'fba') continue;
const ref = resolveWorkspaceLsRef(entry);
if (!ref || isFbaContainerRef(ref)) continue;
const ts = Number.isFinite(new Date(String(entry[3] ?? '')).getTime())
? new Date(String(entry[3] ?? '')).getTime()
const rawTs = String(entry[3] ?? '');
const normalizedTs = rawTs.replace(/^(\d{4}-\d{2}-\d{2})-(\d{2}:\d{2}:\d{2})$/, '$1T$2');
const ts = Number.isFinite(new Date(normalizedTs).getTime())
? new Date(normalizedTs).getTime()
: 0;
Comment on lines +195 to 199
refs.push({ ref, ts });
}
Expand Down
28 changes: 15 additions & 13 deletions app/model/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
trackJob,
type TrackedJob,
} from '@/lib/api/jobTracker';
import { parseWorkspaceDate } from '@/lib/utils/date';
import ModelDetailHeader from '@/components/ui/ModelDetailHeader';
import type { FbaAdvancedOptions } from '@/components/ui/MediaSelectionDialog';
import DownloadModelMenu from '@/components/ui/DownloadModelMenu';
Expand Down Expand Up @@ -503,7 +504,7 @@ function buildTableConfig(model: Record<string, unknown>): Record<Exclude<TabKey
headerName: 'Time',
width: 180,
type: 'dateTime',
valueGetter: (_value, row) => (row.timestamp ? new Date(String(row.timestamp)) : null),
valueGetter: (_value, row) => (row.timestamp ? (parseWorkspaceDate(String(row.timestamp)) ?? new Date(String(row.timestamp))) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
],
Expand All @@ -519,7 +520,7 @@ function buildTableConfig(model: Record<string, unknown>): Record<Exclude<TabKey
headerName: 'Date',
width: 180,
type: 'dateTime',
valueGetter: (_value, row) => (row.rundate ? new Date(String(row.rundate)) : null),
valueGetter: (_value, row) => (row.rundate ? (parseWorkspaceDate(String(row.rundate)) ?? new Date(String(row.rundate))) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
],
Expand Down Expand Up @@ -562,7 +563,7 @@ function a11yProps(index: number) {

function formatRelativeTimestamp(value: unknown): string {
if (typeof value !== 'string' && typeof value !== 'number') return '-';
const date = new Date(value);
const date = parseWorkspaceDate(String(value)) ?? new Date(value);
if (Number.isNaN(date.getTime())) return String(value);
return date.toLocaleString();
}
Expand Down Expand Up @@ -859,7 +860,7 @@ function extractFbaRows(
ref,
objective: String(fba.objective ?? '-'),
objectiveFunction: String(fba.objective_function ?? 'N/A'),
media: summarizeMediaRef(fba.media),
media: summarizeMediaRef(fba.media_ref ?? fba.media),
timestamp: formatRelativeTimestamp(fba.timestamp ?? fba.rundate),
});
}
Expand Down Expand Up @@ -930,7 +931,7 @@ function extractGapfillRows(
id,
ref,
integrated: (gapfill.integrated ?? gapfill.integrated_solution) ? 'Yes' : 'No',
media: summarizeMediaRef(gapfill.media),
media: summarizeMediaRef(gapfill.media_ref ?? gapfill.media),
timestamp: formatRelativeTimestamp(gapfill.rundate ?? gapfill.timestamp),
});
}
Expand Down Expand Up @@ -1427,10 +1428,10 @@ export default function ModelDetailPage({ params }: { params: Promise<{ path: st
error: modelEditsError,
refetch: refetchModelEdits,
} = useQuery({
queryKey: ['modelEdits', USE_MODELSEED_API, workspaceCandidates[0]],
enabled: USE_MODELSEED_API && workspaceCandidates.length > 0,
queryKey: ['modelEdits', USE_MODELSEED_API, apiCandidates[0]],
enabled: USE_MODELSEED_API && apiCandidates.length > 0,
queryFn: async () => {
const edits = await listModelEditsFromApi(workspaceCandidates[0]);
const edits = await listModelEditsFromApi(apiCandidates[0]);
return Array.isArray(edits) ? edits : [];
},
retry: 0,
Expand Down Expand Up @@ -1821,7 +1822,7 @@ export default function ModelDetailPage({ params }: { params: Promise<{ path: st
headerName: 'Timestamp',
width: 220,
type: 'dateTime',
valueGetter: (value) => (value ? new Date(String(value)) : null),
valueGetter: (value) => (value ? (parseWorkspaceDate(String(value)) ?? new Date(String(value))) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
{ field: 'user', headerName: 'User', width: 220 },
Expand Down Expand Up @@ -1889,10 +1890,11 @@ export default function ModelDetailPage({ params }: { params: Promise<{ path: st
headerName: 'ID',
width: 180,
renderCell: (params) => {
const fbaId = params.value;
const fbaHref = `/fba${workspacePath}/fba/${fbaId}`;
const ref = typeof params.row.ref === 'string' && params.row.ref
? params.row.ref
: `${workspacePath}/fba/${String(params.value ?? '')}`;
return (
<Link href={fbaHref} style={{ color: '#00acc1', textDecoration: 'none' }}>
<Link href={toEncodedCatchallHref('/fba', ref)} style={{ color: '#00acc1', textDecoration: 'none' }}>
{String(params.value ?? '')}
</Link>
);
Expand All @@ -1906,7 +1908,7 @@ export default function ModelDetailPage({ params }: { params: Promise<{ path: st
headerName: 'Time',
width: 180,
type: 'dateTime',
valueGetter: (_value, row) => (row.timestamp ? new Date(String(row.timestamp)) : null),
valueGetter: (_value, row) => (row.timestamp ? (parseWorkspaceDate(String(row.timestamp)) ?? new Date(String(row.timestamp))) : null),
valueFormatter: (value: Date | null) => (value ? value.toLocaleString() : '-'),
},
];
Expand Down
5 changes: 4 additions & 1 deletion components/layout/DataControlHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
gridRowCountSelector,
gridFilteredRowCountSelector,
gridFilterModelSelector,
gridRowsLoadingSelector,
type GridColDef,
type GridFilterItem,
type GridFilterModel,
Expand Down Expand Up @@ -91,6 +92,8 @@ function CustomPagination() {
// Use filtered row count so pagination shows correct total after client-side filtering
const filteredCount = useGridSelector(apiRef, gridFilteredRowCountSelector);
const rowCount = useGridSelector(apiRef, gridRowCountSelector);
// Hide pagination while data is loading to prevent "0-0 of 0" flash
const isLoading = useGridSelector(apiRef, gridRowsLoadingSelector);
// Prefer filtered count (client-side filtering), fall back to total rowCount
const displayCount = filteredCount ?? rowCount;
const rowCountValue = displayCount ?? 0;
Expand All @@ -107,7 +110,7 @@ function CustomPagination() {
}
}, [apiRef, ready, pageValue, pageSizeValue, lastPage]);

if (!ready) {
if (!ready || isLoading) {
return null;
}

Expand Down
22 changes: 1 addition & 21 deletions lib/api/modelseed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
MODELSEED_API_URL,
MODELSEED_SUPPORT_URL,
USE_MODELSEED_API,
USE_NEW_PROXY,

Check warning on line 14 in lib/api/modelseed.ts

View workflow job for this annotation

GitHub Actions / Verify (lint, typecheck, test, build, audit)

'USE_NEW_PROXY' is defined but never used
WORKSPACE_URL,
} from './config';
import { getStoredAuthUsername, withRawTokenAuth } from './requestAuth';
Expand Down Expand Up @@ -625,27 +625,7 @@
* ```
*/
export async function listMyMediaFromApi(): Promise<ModelseedMediaSummary[]> {
const primary = await listMediaGeneric('/api/media/mine');
if (primary.length > 0) return primary;

if (!USE_NEW_PROXY) return primary;
const username = getStoredAuthUsername();
if (!username) return primary;

try {
const fallbackPaths = [
`/${username}/media`,
`/${username}/modelseed/media`,
];
for (const path of fallbackPaths) {
const viaWorkspace = await listMediaViaWorkspaceLs(path);
if (viaWorkspace.length > 0) return viaWorkspace;
}
return primary;
} catch (err) {
console.warn('modelseed-api: fallback /api/workspace/ls media lookup failed:', err);
return primary;
}
return listMediaGeneric('/api/media/mine');
}
Comment on lines 625 to 629

/**
Expand Down Expand Up @@ -746,7 +726,7 @@
}
}

async function listMediaViaWorkspaceLs(path: string): Promise<ModelseedMediaSummary[]> {

Check warning on line 729 in lib/api/modelseed.ts

View workflow job for this annotation

GitHub Actions / Verify (lint, typecheck, test, build, audit)

'listMediaViaWorkspaceLs' is defined but never used
const response = await fetch(`${WORKSPACE_URL}/ls`, {
method: 'POST',
headers: withRawTokenAuth(
Expand Down
13 changes: 13 additions & 0 deletions lib/utils/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Normalize workspace date strings like "2026-04-14-17:46:54" to ISO format.
* Workspace API returns dates with dash between date and time instead of "T".
*/
export function parseWorkspaceDate(value: unknown): Date | null {
if (typeof value !== 'string' || !value) return null;
const normalized = value.replace(
/^(\d{4}-\d{2}-\d{2})-(\d{2}:\d{2}:\d{2})$/,
'$1T$2',
);
const date = new Date(normalized);
return Number.isNaN(date.getTime()) ? null : date;
}
Loading