diff --git a/apps/desktop/src/components/export/ExportProgressDialog.vue b/apps/desktop/src/components/export/ExportProgressDialog.vue
index d20df2e63..16c5aba07 100644
--- a/apps/desktop/src/components/export/ExportProgressDialog.vue
+++ b/apps/desktop/src/components/export/ExportProgressDialog.vue
@@ -1,12 +1,17 @@
@@ -108,6 +128,11 @@ const rowsText = computed(() => {
+
diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue
index 3671ea14b..7168c50f9 100644
--- a/apps/desktop/src/components/grid/DataGrid.vue
+++ b/apps/desktop/src/components/grid/DataGrid.vue
@@ -6591,6 +6591,7 @@ const exportProgressState = ref({
totalRows: null as number | null,
status: "",
errorMessage: null as string | null,
+ filePath: null as string | null,
});
const exportCancelHandler = ref<(() => Promise) | null>(null);
diff --git a/apps/desktop/src/composables/useDataGridExport.ts b/apps/desktop/src/composables/useDataGridExport.ts
index f12315d53..dc5773ce3 100644
--- a/apps/desktop/src/composables/useDataGridExport.ts
+++ b/apps/desktop/src/composables/useDataGridExport.ts
@@ -103,6 +103,7 @@ export interface UseDataGridExportOptions {
totalRows: number | null;
status: string;
errorMessage: string | null;
+ filePath: string | null;
}>;
exportCancelHandler?: Ref<(() => Promise) | null>;
}
@@ -688,6 +689,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
totalRows: null,
status: "Running",
errorMessage: null,
+ filePath: null,
};
exportProgressDialog.value = true;
}
@@ -733,6 +735,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
if (needsFullExport && exportProgressState) {
exportProgressState.value = {
...exportProgressState.value,
+ filePath: outputPath,
status: "Done",
rowsExported: result.rows.length,
totalRows: result.rows.length,
@@ -920,6 +923,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
totalRows: null,
status: "Running",
errorMessage: null,
+ filePath: outputPath,
};
exportProgressDialog.value = true;
}
@@ -1073,6 +1077,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
totalRows: null,
status: "Running",
errorMessage: null,
+ filePath: outputPath,
};
}
if (exportProgressDialog) exportProgressDialog.value = true;
@@ -1160,6 +1165,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
totalRows: request.totalRows ?? null,
status: "Running",
errorMessage: null,
+ filePath: outputPath,
};
}
if (exportProgressDialog) exportProgressDialog.value = true;
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts
index fce381209..8b3ad89fe 100644
--- a/apps/desktop/src/i18n/locales/en.ts
+++ b/apps/desktop/src/i18n/locales/en.ts
@@ -1077,6 +1077,8 @@ export default {
rowsExported: "{count} rows exported",
rowsShort: "rows",
cancel: "Cancel",
+ openFolder: "Open containing folder",
+ openFolderFailed: "Failed to open folder: {message}",
close: "Close",
tooltip: "Background Tasks",
failedTooltip: "{count} background task failed | {count} background tasks failed",
diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts
index 5dcfe117a..6401dc5d7 100644
--- a/apps/desktop/src/i18n/locales/es.ts
+++ b/apps/desktop/src/i18n/locales/es.ts
@@ -1021,6 +1021,8 @@ export default withEnglishFallback({
rowsExported: "{count} filas exportadas",
rowsShort: "filas",
cancel: "Cancelar",
+ openFolder: "Abrir carpeta contenedora",
+ openFolderFailed: "No se pudo abrir la carpeta: {message}",
close: "Cerrar",
tooltip: "Progreso de exportación",
popoverTitle: "Exportaciones",
diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts
index faadb6489..6ba6f8cf4 100644
--- a/apps/desktop/src/i18n/locales/it.ts
+++ b/apps/desktop/src/i18n/locales/it.ts
@@ -1019,6 +1019,8 @@ export default withEnglishFallback({
rowsExported: "{count} righe esportate",
rowsShort: "righe",
cancel: "Annulla",
+ openFolder: "Apri cartella contenente",
+ openFolderFailed: "Impossibile aprire la cartella: {message}",
close: "Chiudi",
tooltip: "Stato Esportazione",
failedTooltip: "{count} attività in background non riuscita | {count} attività in background non riuscite",
diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts
index e27856a15..bf9a8ea77 100644
--- a/apps/desktop/src/i18n/locales/ja.ts
+++ b/apps/desktop/src/i18n/locales/ja.ts
@@ -1020,6 +1020,8 @@ export default withEnglishFallback({
rowsExported: "{count}行をエクスポートしました",
rowsShort: "行",
cancel: "キャンセル",
+ openFolder: "保存先フォルダーを開く",
+ openFolderFailed: "フォルダーを開けませんでした:{message}",
close: "閉じる",
tooltip: "エクスポートの進行状況",
popoverTitle: "エクスポート",
diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts
index efb9f61a0..4435ca6e0 100644
--- a/apps/desktop/src/i18n/locales/pt-BR.ts
+++ b/apps/desktop/src/i18n/locales/pt-BR.ts
@@ -1021,6 +1021,8 @@ export default withEnglishFallback({
rowsExported: "{count} linhas exportadas",
rowsShort: "linhas",
cancel: "Cancelar",
+ openFolder: "Abrir pasta do arquivo",
+ openFolderFailed: "Falha ao abrir a pasta: {message}",
close: "Fechar",
tooltip: "Progresso da Exportação",
failedTooltip: "{count} tarefa em segundo plano falhou | {count} tarefas em segundo plano falharam",
diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts
index a18e88684..30b787a97 100644
--- a/apps/desktop/src/i18n/locales/zh-CN.ts
+++ b/apps/desktop/src/i18n/locales/zh-CN.ts
@@ -1079,6 +1079,8 @@ export default withEnglishFallback({
rowsExported: "已导出 {count} 行",
rowsShort: "行",
cancel: "取消",
+ openFolder: "打开所在文件夹",
+ openFolderFailed: "打开文件夹失败:{message}",
close: "关闭",
tooltip: "后台任务",
failedTooltip: "{count} 个后台任务失败",
diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts
index 4d22d432b..4380ec7dd 100644
--- a/apps/desktop/src/i18n/locales/zh-TW.ts
+++ b/apps/desktop/src/i18n/locales/zh-TW.ts
@@ -1021,6 +1021,8 @@ export default withEnglishFallback({
rowsExported: "已匯出 {count} 列",
rowsShort: "列",
cancel: "取消",
+ openFolder: "開啟所在資料夾",
+ openFolderFailed: "開啟資料夾失敗:{message}",
close: "關閉",
tooltip: "背景工作",
failedTooltip: "{count} 個背景工作失敗 | {count} 個背景工作失敗",
diff --git a/packages/app-tests/useDataGridExport.test.ts b/packages/app-tests/useDataGridExport.test.ts
index 0ef859da8..a86466d7e 100644
--- a/packages/app-tests/useDataGridExport.test.ts
+++ b/packages/app-tests/useDataGridExport.test.ts
@@ -65,6 +65,7 @@ function buildExportHarness(
totalRows: null as number | null,
status: "",
errorMessage: null as string | null,
+ filePath: null as string | null,
});
const exportCancelHandler = ref<(() => Promise) | null>(null);
const fullExportResult = vi.fn(async () => {
@@ -150,6 +151,7 @@ function buildTableDataExportHarness() {
totalRows: null as number | null,
status: "",
errorMessage: null as string | null,
+ filePath: null as string | null,
});
const exportCancelHandler = ref<(() => Promise) | null>(null);
@@ -626,6 +628,7 @@ test("full query result CSV export streams through the backend without loading a
assert.equal(apiMock.exportQueryResultCsv.mock.calls.length, 0);
assert.equal(exportProgressDialog.value, true);
assert.equal(exportProgressState.value.status, "Done");
+ assert.equal(exportProgressState.value.filePath, apiMock.startQueryResultExport.mock.calls[0][0].filePath);
});
test("full query result CSV export defaults to the saved SQL title", async () => {
@@ -662,11 +665,12 @@ test("table data export keeps the table name as the default file base", async ()
const restoreStorage = installMemoryStorage();
try {
vi.setSystemTime(new Date(2026, 5, 2, 15, 4, 5));
- const { composable } = buildTableDataExportHarness();
+ const { composable, exportProgressState } = buildTableDataExportHarness();
await composable.exportCsv();
assert.equal(apiMock.startTableExport.mock.calls[0][0].filePath, "users_260602150405.csv");
+ assert.equal(exportProgressState.value.filePath, "users_260602150405.csv");
} finally {
vi.useRealTimers();
restoreStorage();