diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 7d591981e1..2f78314f66 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -841,6 +841,23 @@ function currentEditorSettingsDraft(): EditorSettingsDraft { const editEditorSettingsBase = ref(editorSettingsDraftFromSettings(settingsStore.editorSettings)); const hasEditorDraftChanges = computed(() => editorSettingsDraftChanged(currentEditorSettingsDraft(), editEditorSettingsBase.value)); +// Defaults can also be changed from the result-grid menu while this dialog is +// open. Refresh untouched draft fields so both entry points stay consistent, +// without overwriting an edit the user is actively making here. +watch( + () => [settingsStore.editorSettings.pageSize, settingsStore.editorSettings.tableOpenPageSize] as const, + ([pageSize, tableOpenPageSize]) => { + if (editPageSize.value === editEditorSettingsBase.value.pageSize) { + editPageSize.value = pageSize; + editEditorSettingsBase.value.pageSize = pageSize; + } + if (editTableOpenPageSize.value === editEditorSettingsBase.value.tableOpenPageSize) { + editTableOpenPageSize.value = tableOpenPageSize; + editEditorSettingsBase.value.tableOpenPageSize = tableOpenPageSize; + } + }, +); + // --- Background image draft state --- function cloneBackgroundImageDraft(settings: BackgroundImageSettings): BackgroundImageSettings { return JSON.parse(JSON.stringify(settings)) as BackgroundImageSettings; diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 7717342bf4..bf33853135 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -2934,6 +2934,7 @@ watch([localFilterScopeKey, localFilterRestoreKey], ([, restoreKey], [, previous // --- Pagination --- const pageSizePreference = computed(() => resolveDataGridPageSizePreference(props.context, props.pageSizePreference)); +const defaultPageSize = computed(() => preferredDataGridPageSize(settingsStore.editorSettings, pageSizePreference.value)); const pageSize = ref(preferredDataGridPageSize(settingsStore.editorSettings, pageSizePreference.value, props.pageLimit)); const currentPage = ref(1); const pageSizeOptions = computed(() => resultPageSizeMenuOptions(pageSize.value)); @@ -3356,7 +3357,6 @@ function checkInfiniteScroll(scroller: HTMLElement) { function changePageSize(size: number) { const normalizedSize = normalizeResultPageSize(size); pageSize.value = normalizedSize; - settingsStore.updateEditorSettings(dataGridPageSizeSettingsPatch(pageSizePreference.value, normalizedSize)); currentPage.value = 1; lastInfiniteScrollPage = 0; infiniteScrollAllLoaded = false; @@ -3365,6 +3365,15 @@ function changePageSize(size: number) { emit("paginate", 0, normalizedSize, currentWhereInput(), currentOrderBy()); } +function setDefaultPageSize() { + settingsStore.updateEditorSettings(dataGridPageSizeSettingsPatch(pageSizePreference.value, pageSize.value)); +} + +function applyCustomPageSizeAndSetDefault() { + applyCustomPageSize(); + setDefaultPageSize(); +} + function applyCustomPageSize() { changePageSize(normalizeResultPageSize(customPageSizeInput.value, pageSize.value)); } @@ -13435,6 +13444,7 @@ useUpdateBlocker(() => (hasPendingChanges.value || hasPendingDataEditorDraft.val :infinite-scroll-enabled="infiniteScrollEnabled" :infinite-scroll-all-loaded="infiniteScrollAllLoaded" :page-size="pageSize" + :default-page-size="defaultPageSize" :page-size-menu-items="pageSizeMenuItems" :export-menu-items="exportMenuItems" :current-page="currentPage" @@ -13443,6 +13453,7 @@ useUpdateBlocker(() => (hasPendingChanges.value || hasPendingDataEditorDraft.val :can-jump-last-page="canJumpLastPage" @select-page-size="selectPageSizeMenuItem" @apply-custom-page-size="applyCustomPageSize" + @apply-custom-page-size-and-set-default="applyCustomPageSizeAndSetDefault" @first-page="firstPage" @previous-page="prevPage" @next-page="nextPage" diff --git a/apps/desktop/src/components/grid/DataGridPagination.vue b/apps/desktop/src/components/grid/DataGridPagination.vue index f26beb770c..871eecb60c 100644 --- a/apps/desktop/src/components/grid/DataGridPagination.vue +++ b/apps/desktop/src/components/grid/DataGridPagination.vue @@ -21,6 +21,7 @@ const props = withDefaults( infiniteScrollEnabled: boolean; infiniteScrollAllLoaded: boolean; pageSize: number; + defaultPageSize: number; pageSizeMenuItems: LightDropdownItem[]; exportMenuItems: LightDropdownItem[]; currentPage: number; @@ -49,6 +50,7 @@ const emit = defineEmits<{ jumpPage: [page: number]; lastPage: []; selectExport: [value: string]; + applyCustomPageSizeAndSetDefault: []; }>(); watch( @@ -103,31 +105,36 @@ function handlePageInputKeydown(event: KeyboardEvent) { :items="pageSizeMenuItems" :trigger-label="`${pageSize}${t('grid.rowsPerPageShort')}`" trigger-class="inline-flex h-5 shrink-0 items-center justify-center whitespace-nowrap rounded-md px-1.5 text-xs hover:bg-accent hover:text-accent-foreground" - content-class="w-36" + content-class="w-52" :highlight-selected="false" check-position="none" align="end" @update:model-value="emit('selectPageSize', $event)" >
-
{{ t("grid.customRowsPerPage") }}
-
+
{{ t("grid.customRowsPerPage") }}
+
{{ t("grid.currentAndDefaultPageSize", { current: pageSize, default: defaultPageSize }) }}
+
{{ t("grid.applyPageSize") }}
+
+ + +
diff --git a/apps/desktop/src/components/grid/__tests__/DataGridPaginationShortcuts.spec.ts b/apps/desktop/src/components/grid/__tests__/DataGridPaginationShortcuts.spec.ts index b82b151b63..801b0ac62f 100644 --- a/apps/desktop/src/components/grid/__tests__/DataGridPaginationShortcuts.spec.ts +++ b/apps/desktop/src/components/grid/__tests__/DataGridPaginationShortcuts.spec.ts @@ -65,6 +65,7 @@ function mountGrid( infiniteScroll?: boolean; empty?: boolean; configurePaginationShortcuts?: boolean; + pageSizePreference?: "results" | "table-open"; } = {}, ) { const pinia = createPinia(); @@ -107,6 +108,7 @@ function mountGrid( result, databaseType: "mysql", context: "table-data", + pageSizePreference: options.pageSizePreference, pageLimit: 100, pageOffset: options.pageOffset ?? 200, totalRowCount: options.totalRowCount ?? 500, @@ -125,7 +127,7 @@ function mountGrid( app.mount(host); const mounted = { app, host }; mountedApps.push(mounted); - return { host, paginate }; + return { host, paginate, settingsStore }; } async function settle() { @@ -146,6 +148,29 @@ function dispatchShortcut(target: HTMLElement, key: string): KeyboardEvent { return event; } +function menuActionButton(label: string): HTMLButtonElement { + const button = Array.from(document.querySelectorAll('[role="menu"] button')).find((candidate) => candidate.textContent?.trim() === label); + if (!button) throw new Error(`Menu action button not found: ${label}`); + return button; +} + +async function openCustomPageSizeMenu(host: HTMLElement): Promise { + const trigger = Array.from(host.querySelectorAll("button[aria-expanded]")).find((button) => button.textContent?.includes("100")); + expect(trigger).toBeDefined(); + trigger!.click(); + await settle(); + const input = document.querySelector('[role="menu"] input[type="number"]'); + expect(input).not.toBeNull(); + return input!; +} + +async function enterCustomPageSize(host: HTMLElement, size: string): Promise { + const input = await openCustomPageSizeMenu(host); + input.value = size; + input.dispatchEvent(new Event("input", { bubbles: true })); + await settle(); +} + afterEach(() => { for (const { app, host } of mountedApps.splice(0)) { app.unmount(); @@ -154,6 +179,31 @@ afterEach(() => { }); describe("DataGrid pagination shortcuts", () => { + it("allows pointer focus and editing in the custom page size input", async () => { + const { host, paginate } = mountGrid(); + await settle(); + const trigger = Array.from(host.querySelectorAll("button[aria-expanded]")).find((button) => button.textContent?.includes("100")); + expect(trigger).toBeDefined(); + trigger!.click(); + await settle(); + + const input = document.querySelector('[role="menu"] input[type="number"]'); + expect(input).not.toBeNull(); + const pointer = new MouseEvent("pointerdown", { bubbles: true, cancelable: true, button: 0 }); + input!.dispatchEvent(pointer); + // Canceling pointerdown suppresses the browser's native focus behavior. + expect(pointer.defaultPrevented).toBe(false); + input!.focus(); + input!.value = "250"; + input!.dispatchEvent(new Event("input", { bubbles: true })); + await settle(); + expect(document.activeElement).toBe(input); + input!.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true, cancelable: true })); + await settle(); + expect(paginate).toHaveBeenCalledOnce(); + expect(paginate.mock.calls[0]?.slice(0, 2)).toEqual([0, 250]); + }); + it.each(shortcutCases)("runs $functionName through the configured $actionId shortcut", async ({ key, offset }) => { const { host, paginate } = mountGrid(); await settle(); @@ -277,3 +327,53 @@ describe("DataGrid pagination shortcuts", () => { expect(actionIds).toHaveLength(4); }); }); + +describe("DataGrid custom page size persistence", () => { + it("applying a custom page size is temporary and does not write editor settings", async () => { + const { host, paginate, settingsStore } = mountGrid(); + await settle(); + const updateEditorSettings = vi.spyOn(settingsStore, "updateEditorSettings"); + + await enterCustomPageSize(host, "250"); + menuActionButton(i18n.global.t("grid.applyForThisQuery")).click(); + await settle(); + + expect(paginate).toHaveBeenCalledOnce(); + expect(paginate.mock.calls[0]?.slice(0, 2)).toEqual([0, 250]); + expect(updateEditorSettings).not.toHaveBeenCalled(); + expect(settingsStore.editorSettings.pageSize).toBe(100); + expect(settingsStore.editorSettings.tableOpenPageSize).toBe(100); + }); + + it("set-as-default persists the table-open page size for table grids", async () => { + const { host, paginate, settingsStore } = mountGrid(); + await settle(); + const updateEditorSettings = vi.spyOn(settingsStore, "updateEditorSettings"); + + await enterCustomPageSize(host, "250"); + menuActionButton(i18n.global.t("grid.applyAndSetDefault")).click(); + await settle(); + + expect(paginate).toHaveBeenCalledOnce(); + expect(paginate.mock.calls[0]?.slice(0, 2)).toEqual([0, 250]); + expect(updateEditorSettings).toHaveBeenCalledWith({ tableOpenPageSize: 250 }); + expect(settingsStore.editorSettings.tableOpenPageSize).toBe(250); + expect(settingsStore.editorSettings.pageSize).toBe(100); + }); + + it("set-as-default persists the query page size for results grids", async () => { + const { host, paginate, settingsStore } = mountGrid({ pageSizePreference: "results" }); + await settle(); + const updateEditorSettings = vi.spyOn(settingsStore, "updateEditorSettings"); + + await enterCustomPageSize(host, "250"); + menuActionButton(i18n.global.t("grid.applyAndSetDefault")).click(); + await settle(); + + expect(paginate).toHaveBeenCalledOnce(); + expect(paginate.mock.calls[0]?.slice(0, 2)).toEqual([0, 250]); + expect(updateEditorSettings).toHaveBeenCalledWith({ pageSize: 250 }); + expect(settingsStore.editorSettings.pageSize).toBe(250); + expect(settingsStore.editorSettings.tableOpenPageSize).toBe(100); + }); +}); diff --git a/apps/desktop/src/i18n/locales/az.ts b/apps/desktop/src/i18n/locales/az.ts index 7d7d3fc78c..e41e6767b4 100644 --- a/apps/desktop/src/i18n/locales/az.ts +++ b/apps/desktop/src/i18n/locales/az.ts @@ -2044,6 +2044,9 @@ export default withEnglishFallback({ rowsPerPage: "Səhifədəki sətir sayı", customRowsPerPage: "Fərdi sətir sayı", applyPageSize: "Tətbiq et", + currentAndDefaultPageSize: "Cari: {current} · Standart: {default}", + applyForThisQuery: "Bu dəfə", + applyAndSetDefault: "Standart et", save: "Yadda saxla", discard: "Dəyişiklikləri at", dismiss: "Bağla", @@ -6965,7 +6968,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "Təsirin önbaxışını genişləndir", dataGridFilterViewPreviewCollapse: "Təsirin önbaxışını yığ", tableOpenPageSize: "Cədvəllər açıldıqda səhifə başına standart sətir sayı", - tableOpenPageSizeDescription: "Yeni cədvəl açıldıqda hər səhifədə yüklənən sətirlər. Cədvəldə səhifə başına sətir sayını dəyişmək gələcək cədvəl vərəqləri üçün bu standartı yeniləyir.", + tableOpenPageSizeDescription: "Yeni cədvəl açıldıqda hər səhifədə yüklənən sətirlərin sayı. Cədvəldəki müvəqqəti dəyişikliklər bu standartı dəyişmir; yalnız “Standart et” seçildikdə yenilənir.", queryPageSize: "Sorğuda səhifə başına standart sətir sayı", queryPageSizeDescription: "Sorğu nəticəsinin hər səhifəsində yüklənən sətirlər. Dəstəklənən maksimum səhifə ölçüsü {max} təşkil edir.", defaultAutoKeepResults: "Sorğu nəticələrini standart olaraq avtomatik saxla", diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 8e893439e1..8f83f3cd54 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -2177,6 +2177,9 @@ export default { rowsPerPage: "Rows per page", customRowsPerPage: "Custom rows", applyPageSize: "Apply", + currentAndDefaultPageSize: "Current: {current} · Default: {default}", + applyForThisQuery: "For now", + applyAndSetDefault: "Set default", save: "Save", discard: "Discard", dismiss: "Dismiss", @@ -7152,7 +7155,7 @@ export default { dataGridFilterViewPreviewExpand: "Expand effect preview", dataGridFilterViewPreviewCollapse: "Collapse effect preview", tableOpenPageSize: "Default rows per page when opening tables", - tableOpenPageSizeDescription: "Rows loaded per page when opening a new table. Changing rows per page in a table updates this default for future table tabs.", + tableOpenPageSizeDescription: "Rows loaded per page when opening a new table. Temporary changes do not update this default; only choosing “Set default” does.", queryPageSize: "Default query rows per page", queryPageSizeDescription: "Rows loaded per query result page. The maximum supported page size is {max}.", defaultAutoKeepResults: "Auto-keep query results by default", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index c5c64299d3..d8fd938ae7 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -2022,6 +2022,9 @@ export default withEnglishFallback({ rowsPerPage: "Filas por página", customRowsPerPage: "Filas personalizadas", applyPageSize: "Aplicar", + currentAndDefaultPageSize: "Actual: {current} · Predeterminado: {default}", + applyForThisQuery: "Solo ahora", + applyAndSetDefault: "Predeterminado", save: "Guardar", discard: "Descartar", dismiss: "Cerrar", @@ -6714,7 +6717,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "Expandir vista previa del efecto", dataGridFilterViewPreviewCollapse: "Contraer vista previa del efecto", tableOpenPageSize: "Filas predeterminadas por página al abrir tablas", - tableOpenPageSizeDescription: "Filas cargadas por página al abrir una tabla nueva. Cambiar las filas por página actualiza este valor para futuras pestañas de tablas.", + tableOpenPageSizeDescription: "Filas cargadas por página al abrir una nueva tabla. Los cambios temporales no modifican este valor; solo se actualiza al elegir “Predeterminado”.", queryPageSize: "Filas predeterminadas por página de consulta", queryPageSizeDescription: "Filas cargadas por página de resultados. Se admiten hasta {max} filas.", defaultAutoKeepResults: "Conservar resultados automáticamente por defecto", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index ec36971976..b7d2fe1f0c 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -2020,6 +2020,9 @@ export default withEnglishFallback({ rowsPerPage: "Righe per pagina", customRowsPerPage: "Righe personalizzate", applyPageSize: "Applica", + currentAndDefaultPageSize: "Attuale: {current} · Predefinito: {default}", + applyForThisQuery: "Solo ora", + applyAndSetDefault: "Predefinito", save: "Salva", discard: "Scarta", dismiss: "Ignora", @@ -6714,7 +6717,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "Espandi anteprima effetto", dataGridFilterViewPreviewCollapse: "Comprimi anteprima effetto", tableOpenPageSize: "Righe predefinite per pagina all'apertura delle tabelle", - tableOpenPageSizeDescription: "Righe caricate per pagina quando si apre una nuova tabella. La modifica delle righe per pagina aggiorna questo valore per le future schede tabella.", + tableOpenPageSizeDescription: "Righe caricate per pagina quando si apre una nuova tabella. Le modifiche temporanee non cambiano questo valore; viene aggiornato solo scegliendo “Predefinito”.", queryPageSize: "Righe predefinite per pagina di query", queryPageSizeDescription: "Righe caricate per pagina dei risultati. Sono supportate fino a {max} righe.", defaultAutoKeepResults: "Mantieni automaticamente i risultati per impostazione predefinita", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index 51d319dae8..1e1aadc351 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -2032,6 +2032,9 @@ export default withEnglishFallback({ rowsPerPage: "1ページあたりの行数", customRowsPerPage: "カスタム行数", applyPageSize: "適用", + currentAndDefaultPageSize: "現在:{current} · デフォルト:{default}", + applyForThisQuery: "今回のみ", + applyAndSetDefault: "デフォルトに設定", save: "保存", discard: "破棄", dismiss: "閉じる", @@ -6748,7 +6751,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "効果プレビューを展開", dataGridFilterViewPreviewCollapse: "効果プレビューを折りたたむ", tableOpenPageSize: "テーブルを開くときのデフォルト行数", - tableOpenPageSizeDescription: "新しいテーブルを開くときに 1 ページあたり読み込む行数です。テーブルで行数を変更すると、今後のテーブルタブのデフォルトも更新されます。", + tableOpenPageSizeDescription: "新しいテーブルを開くときに1ページあたり読み込む行数です。一時的な変更では更新されず、「デフォルトに設定」を選択した場合のみ更新されます。", queryPageSize: "クエリ結果のデフォルト行数", queryPageSizeDescription: "クエリ結果の 1 ページあたりの行数です。最大 {max} 行まで指定できます。", defaultAutoKeepResults: "クエリ結果を既定で自動保持", diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts index 9031ed35ba..090c311416 100644 --- a/apps/desktop/src/i18n/locales/ko.ts +++ b/apps/desktop/src/i18n/locales/ko.ts @@ -2013,6 +2013,9 @@ export default withEnglishFallback({ rowsPerPage: "페이지당 행", customRowsPerPage: "사용자 지정 행", applyPageSize: "적용", + currentAndDefaultPageSize: "현재: {current} · 기본값: {default}", + applyForThisQuery: "이번만", + applyAndSetDefault: "기본값 설정", save: "저장", discard: "저장 안 함", dismiss: "닫기", @@ -6464,7 +6467,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "효과 미리보기 펼치기", dataGridFilterViewPreviewCollapse: "효과 미리보기 접기", tableOpenPageSize: "테이블을 열 때 기본 페이지당 행 수", - tableOpenPageSizeDescription: "새 테이블을 열 때 페이지당 로드되는 행 수입니다. 테이블에서 페이지당 행을 변경하면 향후 테이블 탭의 기본값이 업데이트됩니다.", + tableOpenPageSizeDescription: "새 테이블을 열 때 페이지당 불러오는 행 수입니다. 임시 변경은 이 기본값에 영향을 주지 않으며, “기본값 설정”을 선택한 경우에만 변경됩니다.", queryPageSize: "쿼리 결과 기본 페이지당 행 수", queryPageSizeDescription: "쿼리 결과 페이지당 로드할 행 수입니다. 최대 {max}행을 지원합니다.", defaultAutoKeepResults: "기본적으로 쿼리 결과 자동 보관", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index 69c85120a4..0eb8d7ca39 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -2022,6 +2022,9 @@ export default withEnglishFallback({ rowsPerPage: "Linhas por página", customRowsPerPage: "Linhas personalizadas", applyPageSize: "Aplicar", + currentAndDefaultPageSize: "Atual: {current} · Padrão: {default}", + applyForThisQuery: "Só agora", + applyAndSetDefault: "Definir padrão", save: "Salvar", discard: "Descartar", dismiss: "Dispensar", @@ -6716,7 +6719,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "Expandir prévia do efeito", dataGridFilterViewPreviewCollapse: "Recolher prévia do efeito", tableOpenPageSize: "Linhas padrão por página ao abrir tabelas", - tableOpenPageSizeDescription: "Linhas carregadas por página ao abrir uma nova tabela. Alterar as linhas por página atualiza esse padrão para futuras abas de tabelas.", + tableOpenPageSizeDescription: "Linhas carregadas por página ao abrir uma nova tabela. Alterações temporárias não modificam esse valor; ele só é atualizado ao escolher “Definir padrão”.", queryPageSize: "Linhas padrão por página de consulta", queryPageSizeDescription: "Linhas carregadas por página de resultados. São suportadas até {max} linhas.", defaultAutoKeepResults: "Manter resultados automaticamente por padrão", diff --git a/apps/desktop/src/i18n/locales/tr.ts b/apps/desktop/src/i18n/locales/tr.ts index 10ffa6b5a1..238f0f0421 100644 --- a/apps/desktop/src/i18n/locales/tr.ts +++ b/apps/desktop/src/i18n/locales/tr.ts @@ -2039,6 +2039,9 @@ export default withEnglishFallback({ rowsPerPage: "Sayfa başına satır", customRowsPerPage: "Özel satır sayısı", applyPageSize: "Uygula", + currentAndDefaultPageSize: "Geçerli: {current} · Varsayılan: {default}", + applyForThisQuery: "Bu sefer", + applyAndSetDefault: "Varsayılan yap", save: "Kaydet", discard: "Vazgeç", dismiss: "Kapat", @@ -6847,7 +6850,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "Etki önizlemesini genişlet", dataGridFilterViewPreviewCollapse: "Etki önizlemesini daralt", tableOpenPageSize: "Tablolar açılırken varsayılan sayfa başına satır", - tableOpenPageSizeDescription: "Yeni bir tablo açıldığında sayfa başına yüklenen satır sayısı. Bir tabloda sayfa başına satırı değiştirmek, sonraki tablo sekmeleri için bu varsayılanı günceller.", + tableOpenPageSizeDescription: "Yeni bir tablo açıldığında sayfa başına yüklenen satır sayısı. Geçici değişiklikler bu değeri değiştirmez; yalnızca “Varsayılan yap” seçildiğinde güncellenir.", queryPageSize: "Varsayılan sorgu sayfa başına satır", queryPageSizeDescription: "Sorgu sonucu sayfası başına yüklenen satır sayısı. Desteklenen en büyük sayfa boyutu {max}.", defaultAutoKeepResults: "Sorgu sonuçlarını varsayılan olarak otomatik sakla", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index e355121053..3bdce70433 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -2092,6 +2092,9 @@ export default withEnglishFallback({ rowsPerPage: "每页行数", customRowsPerPage: "自定义行数", applyPageSize: "应用", + currentAndDefaultPageSize: "当前:{current} · 默认:{default}", + applyForThisQuery: "仅本次", + applyAndSetDefault: "设为默认", save: "保存", discard: "放弃", dismiss: "关闭", @@ -7126,7 +7129,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "展开效果预览", dataGridFilterViewPreviewCollapse: "收起效果预览", tableOpenPageSize: "打开表默认每页行数", - tableOpenPageSizeDescription: "新打开数据表时每页加载的行数。在表数据页修改每页行数后,也会更新后续新建表标签页的默认值。", + tableOpenPageSizeDescription: "新打开数据表时每页加载的行数。临时修改行数不会影响此默认值,仅点击“设为默认”时更新。", queryPageSize: "查询结果默认每页行数", queryPageSizeDescription: "每个查询结果分页加载的行数,最大支持 {max} 行。", defaultAutoKeepResults: "默认自动保留查询结果", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index edf5848201..66f8fb84ae 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -2021,6 +2021,9 @@ export default withEnglishFallback({ rowsPerPage: "每頁筆數", customRowsPerPage: "自訂筆數", applyPageSize: "套用", + currentAndDefaultPageSize: "目前:{current} · 預設:{default}", + applyForThisQuery: "僅本次", + applyAndSetDefault: "設為預設", save: "儲存", discard: "放棄", dismiss: "關閉", @@ -6029,7 +6032,7 @@ export default withEnglishFallback({ dataGridFilterViewPreviewExpand: "展開效果預覽", dataGridFilterViewPreviewCollapse: "收合效果預覽", tableOpenPageSize: "開啟資料表預設每頁列數", - tableOpenPageSizeDescription: "新開啟資料表時每頁載入的列數。在資料表頁面調整每頁列數後,也會更新後續新建資料表分頁的預設值。", + tableOpenPageSizeDescription: "新開啟資料表時每頁載入的列數。暫時調整列數不會影響此預設值,僅點選「設為預設」時更新。", queryPageSize: "查詢結果預設每頁列數", queryPageSizeDescription: "每個查詢結果分頁載入的列數,最多支援 {max} 列。", defaultAutoKeepResults: "預設自動保留查詢結果", diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index 4e5aafe196..5c1ff5e9e1 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -2379,8 +2379,6 @@ export const useQueryStore = defineStore("query", () => { resultSortDirection: t.resultSortDirection, resultSortMode: t.resultSortMode, orderByInput: t.orderByInput, - resultPageLimit: t.resultPageLimit, - resultPageOffset: t.resultPageOffset, whereInput: t.whereInput, pinned: t.pinned, mode: t.mode, @@ -8072,6 +8070,8 @@ export const useQueryStore = defineStore("query", () => { tab.tableMetaPending = true; } tab.resultPageSql = snapshot.resultPageSql; + // Cached rows and their pagination metadata describe the same result page. + // Restoring this state must not change the global page-size defaults. tab.resultPageLimit = snapshot.resultPageLimit; tab.resultPageOffset = snapshot.resultPageOffset; tab.resultCountSql = snapshot.resultCountSql; diff --git a/packages/app-tests/queryResultToolbar.test.ts b/packages/app-tests/queryResultToolbar.test.ts index 6f7e831939..1553151367 100644 --- a/packages/app-tests/queryResultToolbar.test.ts +++ b/packages/app-tests/queryResultToolbar.test.ts @@ -168,7 +168,15 @@ test("table-data toolbar refresh keeps page size independent from SQL editor set assert.match(dataGrid, /pageSizePreference = computed\(\(\) => resolveDataGridPageSizePreference\(props\.context, props\.pageSizePreference\)\)/); assert.match(dataGrid, /pageSize = ref\(preferredDataGridPageSize\(settingsStore\.editorSettings, pageSizePreference\.value, props\.pageLimit\)\)/); assert.match(dataGrid, /watch\([\s\S]*\(\) => settingsStore\.editorSettings\.pageSize,[\s\S]*if \(pageSizePreference\.value !== "results"\) return;[\s\S]*pageSize\.value = normalizeResultPageSize\(value, pageSize\.value\)/); - assert.match(dataGrid, /settingsStore\.updateEditorSettings\(dataGridPageSizeSettingsPatch\(pageSizePreference\.value, normalizedSize\)\)/); + // Changing the page size in the grid is temporary; only the explicit + // set-as-default action persists it back into editor settings. + const changePageSizeStart = dataGrid.indexOf("function changePageSize(size: number) {"); + assert.ok(changePageSizeStart >= 0); + const changePageSizeEnd = dataGrid.indexOf("function setDefaultPageSize", changePageSizeStart); + assert.ok(changePageSizeEnd > changePageSizeStart); + const changePageSize = dataGrid.slice(changePageSizeStart, changePageSizeEnd); + assert.doesNotMatch(changePageSize, /updateEditorSettings/); + assert.match(dataGrid, /function setDefaultPageSize\(\) \{[\s\S]*?settingsStore\.updateEditorSettings\(dataGridPageSizeSettingsPatch\(pageSizePreference\.value, pageSize\.value\)\)/); assert.match(dataGrid, /const resetToFirstPage = hasPendingConditionInputs\(\);/); assert.match(dataGrid, /emit\("reload", props\.sql, searchText\.value, currentWhereInput\(\), currentOrderBy\(\), pageSize\.value, resetToFirstPage \? 0 : \(currentPage\.value - 1\) \* pageSize\.value, intent\)/); });