fix(grid): hide bottom export menu when result has no columns

This commit is contained in:
lxk955
2026-10-09 09:58:00 +08:00
committed by GitHub
parent e63faca4cd
commit c17fbdc8ea
4 changed files with 71 additions and 3 deletions
@@ -15353,6 +15353,7 @@ useUpdateBlocker(() => (hasPendingChanges.value || hasPendingDataEditorDraft.val
:load-all-rows-active="loadAllRowsActive"
:load-all-rows-enabled="loadAllRowsEnabled"
:can-load-all-rows="result.rows.length > 0"
:can-export="result.columns.length > 0"
:page-size="pageSize"
:default-page-size="defaultPageSize"
:page-size-menu-items="pageSizeMenuItems"
@@ -23,6 +23,7 @@ const props = withDefaults(
loadAllRowsActive: boolean;
loadAllRowsEnabled: boolean;
canLoadAllRows: boolean;
canExport?: boolean;
pageSize: number;
defaultPageSize: number;
pageSizeMenuItems: LightDropdownItem[];
@@ -32,7 +33,7 @@ const props = withDefaults(
canGoNextPage: boolean;
canJumpLastPage: boolean;
}>(),
{ paginationEnabled: true, loadAllRowsActive: false, loadAllRowsEnabled: true, canLoadAllRows: false },
{ paginationEnabled: true, loadAllRowsActive: false, loadAllRowsEnabled: true, canLoadAllRows: false, canExport: true },
);
const customPageSizeInput = defineModel<string>("customPageSizeInput", { default: "" });
@@ -164,6 +165,6 @@ function handlePageInputKeydown(event: KeyboardEvent) {
</TooltipTrigger>
<TooltipContent side="bottom">{{ t("grid.loadAllAndGoToLastRow") }}</TooltipContent>
</Tooltip>
<DataGridExportMenu :items="exportMenuItems" :label="t('grid.export')" :on-select="(value) => emit('selectExport', value)" />
<DataGridExportMenu v-if="canExport" :items="exportMenuItems" :label="t('grid.export')" :on-select="(value) => emit('selectExport', value)" />
</div>
</template>
@@ -412,6 +412,55 @@ describe("DataGridPagination", () => {
await mounted.setProps({ loading: false, canLoadAllRows: false });
expect(findOne(mounted.root, (node) => node.props["aria-label"] === "grid.loadAllAndGoToLastRow").props.disabled).toBe(true);
});
it("gates the bottom export menu based on canExport", async () => {
const mounted = mountComponent(DataGridPagination, {
selectionSummary: null,
selectionSummarySumText: "",
selectionSummaryAverageText: "",
loading: false,
infiniteScrollEnabled: false,
infiniteScrollAllLoaded: false,
pageSize: 100,
customPageSizeInput: "",
pageSizeMenuItems: [],
exportMenuItems: [{ value: "csv", label: "CSV" }],
currentPage: 1,
canGoNextPage: false,
canJumpLastPage: false,
canExport: true,
});
const findExportMenu = () => findAll(mounted.root, (node) => node.props["data-stub"] === "LightDropdown" && node.props["aria-label"] === "grid.export");
expect(findExportMenu()).toHaveLength(1);
await mounted.setProps({ canExport: false });
expect(findExportMenu()).toHaveLength(0);
await mounted.setProps({ canExport: true });
expect(findExportMenu()).toHaveLength(1);
});
it("renders export menu by default when canExport is not specified", () => {
const mounted = mountComponent(DataGridPagination, {
selectionSummary: null,
selectionSummarySumText: "",
selectionSummaryAverageText: "",
loading: false,
infiniteScrollEnabled: false,
infiniteScrollAllLoaded: false,
pageSize: 100,
customPageSizeInput: "",
pageSizeMenuItems: [],
exportMenuItems: [{ value: "csv", label: "CSV" }],
currentPage: 1,
canGoNextPage: false,
canJumpLastPage: false,
});
const exportMenus = findAll(mounted.root, (node) => node.props["data-stub"] === "LightDropdown" && node.props["aria-label"] === "grid.export");
expect(exportMenus).toHaveLength(1);
});
});
describe("DataGridColumnHeader", () => {
@@ -95,7 +95,7 @@ function mountToolbar() {
);
}
function mountGrid() {
function mountGrid(resultOverride?: Partial<QueryResult>) {
const pinia = createPinia();
setActivePinia(pinia);
const settingsStore = useSettingsStore();
@@ -108,6 +108,7 @@ function mountGrid() {
rows: [[1, "Ada"]],
affected_rows: 0,
execution_time_ms: 0,
...resultOverride,
});
const grid = ref<{ goToColumnToolbarCapability: DataGridToolbarActionCapability }>();
const host = document.createElement("div");
@@ -212,6 +213,22 @@ describe("data grid icon-only toolbar tooltips", () => {
expect(host.querySelector("[data-column-lookup-panel]")).not.toBeNull();
expect(host.querySelector('[data-slot="popover-content"]')).toBeNull();
});
it("hides the bottom pagination export menu when the result has no columns", async () => {
const { host } = mountGrid({ columns: [], rows: [] });
await settle();
const bottomExportMenu = Array.from(host.querySelectorAll("button")).find((btn) => btn.getAttribute("aria-label") === "Export");
expect(bottomExportMenu).toBeUndefined();
});
it("shows the bottom pagination export menu when the result has columns", async () => {
const { host } = mountGrid();
await settle();
const bottomExportMenu = Array.from(host.querySelectorAll("button")).find((btn) => btn.getAttribute("aria-label") === "Export");
expect(bottomExportMenu).not.toBeUndefined();
});
});
// Reka resolves the popper anchor from the nearest popper root. Wrapping an overlay