Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

Commit

Permalink
feat: only adjust left header widths (#479)
Browse files Browse the repository at this point in the history
  • Loading branch information
enell authored Dec 7, 2023
1 parent 70f2440 commit 4462b96
Show file tree
Hide file tree
Showing 15 changed files with 249 additions and 94 deletions.
7 changes: 5 additions & 2 deletions src/pivot-table/components/cells/DimensionValue/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { areEqual } from "react-window";
import type { ListItemData } from "../../../../types/types";
import { ColumnWidthLocation, type ListItemData } from "../../../../types/types";
import { useSelectionsContext } from "../../../contexts/SelectionsProvider";
import { useStyleContext } from "../../../contexts/StyleProvider";
import useIsAdjustingWidth from "../../../hooks/use-is-adjusting-width";
Expand Down Expand Up @@ -74,7 +74,10 @@ const DimensionValue = ({ index, style, data }: DimensionValueProps): JSX.Elemen
</Text>
</StickyCellContainer>
<ColumnAdjusterWrapper
cellInfo={cell}
cellInfo={{
...cell,
columnWidthLocation: cell.isPseudoDimension ? ColumnWidthLocation.Measures : ColumnWidthLocation.Dimension,
}}
columnWidth={style.width as number}
dataModel={dataModel}
isLastColumn={isLastColumn}
Expand Down
45 changes: 42 additions & 3 deletions src/pivot-table/data/__tests__/extract-headers.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { PSEUDO_DIMENSION_INDEX, PSEUDO_DIMENSION_KEY } from "../../../constants";
import type { LayoutService, VisibleDimensionInfo } from "../../../types/types";
import { ColumnWidthLocation, type LayoutService, type VisibleDimensionInfo } from "../../../types/types";
import extractHeaders from "../extract-headers";
import { createDimInfos } from "./test-helper";

describe("extractHeaders", () => {
const mockedIsLeftDimension: jest.MockedFunction<(index: number) => boolean> = jest.fn();
const mockedGetDimensionInfoIndex: jest.MockedFunction<(info: VisibleDimensionInfo) => number> = jest.fn();
let layoutService: LayoutService;

beforeEach(() => {
mockedIsLeftDimension.mockReturnValue(false);
mockedGetDimensionInfoIndex.mockImplementation((info: VisibleDimensionInfo) => (info === -1 ? -1 : 0));
layoutService = {
layout: {
qHyperCube: {
activelySortedColumn: { colIdx: 0 },
},
},
isLeftDimension: jest.fn(() => false),
getDimensionInfoIndex: (info: VisibleDimensionInfo) => (info === -1 ? -1 : 0),
isLeftDimension: mockedIsLeftDimension,
getDimensionInfoIndex: mockedGetDimensionInfoIndex,
} as unknown as LayoutService;
});

Expand Down Expand Up @@ -152,4 +156,39 @@ describe("extractHeaders", () => {
expect(headers[1][2]?.label).toBe("dim 3");
expect(headers[1][2]?.id).toBe("id-3");
});

describe("ColumnWidthLocation", () => {
test("should have ColumnWidthLocation measures on any pseudo dimension in left", () => {
const sortedLeftDimensionInfo = createDimInfos([PSEUDO_DIMENSION_INDEX, 1]);
const sortedTopDimensionInfo = createDimInfos([2]);
const headers = extractHeaders(layoutService, sortedTopDimensionInfo, sortedLeftDimensionInfo);

expect(headers[0][0]?.columnWidthLocation).toBe(ColumnWidthLocation.Measures);
});

test("should have ColumnWidthLocation measures on last left", () => {
const sortedLeftDimensionInfo = createDimInfos([1, PSEUDO_DIMENSION_INDEX]);
const sortedTopDimensionInfo = createDimInfos([2]);
const headers = extractHeaders(layoutService, sortedTopDimensionInfo, sortedLeftDimensionInfo);

expect(headers[0][1]?.isLeftDimension).toBeFalsy();
expect(headers[0][1]?.columnWidthLocation).toBe(ColumnWidthLocation.Measures);
});

test("should have ColumnWidthLocation pivot on last left", () => {
const sortedLeftDimensionInfo = createDimInfos([PSEUDO_DIMENSION_INDEX, 1]);
const sortedTopDimensionInfo = createDimInfos([2]);
layoutService.hasPseudoDimOnLeft = true;
mockedIsLeftDimension.mockImplementation((index: number) => index !== 2);

mockedGetDimensionInfoIndex.mockImplementation((info) =>
info === PSEUDO_DIMENSION_INDEX
? PSEUDO_DIMENSION_INDEX
: [...sortedLeftDimensionInfo, ...sortedTopDimensionInfo].indexOf(info),
);
const headers = extractHeaders(layoutService, sortedTopDimensionInfo, sortedLeftDimensionInfo);

expect(headers[0][2]?.columnWidthLocation).toBe(ColumnWidthLocation.Pivot);
});
});
});
30 changes: 26 additions & 4 deletions src/pivot-table/data/extract-headers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { PSEUDO_DIMENSION_INDEX } from "../../constants";
import type { HeaderCell, HeadersDataMatrix, LayoutService, VisibleDimensionInfo } from "../../types/types";
import {
ColumnWidthLocation,
type HeaderCell,
type HeadersDataMatrix,
type LayoutService,
type VisibleDimensionInfo,
} from "../../types/types";
import getKey from "../components/helpers/get-key";

interface CreateMatrixProps {
Expand Down Expand Up @@ -42,9 +48,10 @@ const createHeaderCell = (
isDim: false,
headTextAlign: "left",
dimensionInfoIndex,
canBeResized: false,
canBeResized: false, // has to be properly set later, would be incorrect after transposing otherwise
isLeftDimension,
isLastDimension,
columnWidthLocation: ColumnWidthLocation.Measures,
};
}
return {
Expand All @@ -66,6 +73,7 @@ const createHeaderCell = (
canBeResized: false, // has to be properly set later, would be incorrect after transposing otherwise
isLeftDimension,
isLastDimension,
columnWidthLocation: ColumnWidthLocation.Dimension,
};
};

Expand Down Expand Up @@ -112,13 +120,27 @@ const extractHeaders = (
);
}

// Update canBeResized, isActivelySorted and colIdx on bottom row
// Update canBeResized, columnWidthLocation, isActivelySorted and colIdx on bottom row
if (matrix.length) {
for (const [colIdx, cell] of matrix[matrix.length - 1].entries()) {
if (cell) {
cell.canBeResized = cell.isLeftDimension;
cell.canBeResized = true;
cell.isActivelySorted = colIdx === (layoutService.layout.qHyperCube.activelySortedColumn?.colIdx ?? 0);
cell.colIdx = cell.colIdx || colIdx;

if (cell.dimensionInfoIndex === PSEUDO_DIMENSION_INDEX) {
cell.columnWidthLocation = ColumnWidthLocation.Measures;
} else if (!cell.isLeftDimension) {
if (visibleLeftDimensionInfos.at(-1) === PSEUDO_DIMENSION_INDEX) {
// pseudo dimension is last in left dimensions
cell.columnWidthLocation = ColumnWidthLocation.Measures;
} else if (layoutService.hasPseudoDimOnLeft) {
// pseudo dimension is anywhere else in left dimensions
cell.columnWidthLocation = ColumnWidthLocation.Pivot;
}
} else {
cell.columnWidthLocation = ColumnWidthLocation.Dimension;
}
}
}
}
Expand Down
16 changes: 15 additions & 1 deletion src/pivot-table/hooks/__tests__/use-data-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ColumnWidthType } from "@qlik/nebula-table-utils/lib/constants";
import { renderHook } from "@testing-library/react";
import { Q_PATH } from "../../../constants";
import { type ExtendedDimensionInfo, type ExtendedMeasureInfo, type Model } from "../../../types/QIX";
import type { AdjusterCellInfo, LayoutService, PageInfo } from "../../../types/types";
import { ColumnWidthLocation, type AdjusterCellInfo, type LayoutService, type PageInfo } from "../../../types/types";
import useDataModel from "../use-data-model";

const pivotPage = {};
Expand Down Expand Up @@ -181,13 +181,15 @@ describe("useDataModel", () => {

test("should call applyPatches with qPath for dimension", () => {
const { applyColumnWidth } = renderer();
cellInfo.columnWidthLocation = ColumnWidthLocation.Dimension;
applyColumnWidth(newColumnWidth, cellInfo);

expect(model?.applyPatches).toHaveBeenCalledWith([patch], true);
});

test("should call applyPatches with qOp replace when columnWidth exists on dimension", () => {
layoutService.layout.qHyperCube.qDimensionInfo[0].columnWidth = { type: ColumnWidthType.Auto };
cellInfo.columnWidthLocation = ColumnWidthLocation.Dimension;
patch.qOp = "Replace";

const { applyColumnWidth } = renderer();
Expand All @@ -198,6 +200,7 @@ describe("useDataModel", () => {

test("should call applyPatches with qPath for top grid measure", async () => {
cellInfo.dimensionInfoIndex = -1;
cellInfo.columnWidthLocation = ColumnWidthLocation.Measures;
patch.qPath = "/qHyperCubeDef/qMeasures/0/qDef/columnWidth";

const { applyColumnWidth } = renderer();
Expand All @@ -208,6 +211,7 @@ describe("useDataModel", () => {

test("should call applyPatches with patches for all measures when resizing header grid pseudo dimension", async () => {
cellInfo.dimensionInfoIndex = -1;
cellInfo.columnWidthLocation = ColumnWidthLocation.Measures;
cellInfo.isLeftColumn = true;
const patches = [
{ ...patch, qPath: "/qHyperCubeDef/qMeasures/0/qDef/columnWidth" },
Expand All @@ -219,5 +223,15 @@ describe("useDataModel", () => {

expect(model?.applyPatches).toHaveBeenCalledWith(patches, true);
});

test("should call applyPatches with patches for pivot when resizing extra column", async () => {
cellInfo.columnWidthLocation = ColumnWidthLocation.Pivot;
const patches = [{ ...patch, qPath: "/qHyperCubeDef/topHeadersColumnWidth" }];

const { applyColumnWidth } = renderer();
applyColumnWidth(newColumnWidth, cellInfo);

expect(model?.applyPatches).toHaveBeenCalledWith(patches, true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import { act, renderHook } from "@testing-library/react";
import useColumnWidth from "..";
import { PSEUDO_DIMENSION_INDEX } from "../../../../constants";
import type { ExtendedDimensionInfo, ExtendedMeasureInfo } from "../../../../types/QIX";
import type { HeadersData, LayoutService, Rect, VisibleDimensionInfo } from "../../../../types/types";
import {
ColumnWidthLocation,
type HeadersData,
type LayoutService,
type Rect,
type VisibleDimensionInfo,
} from "../../../../types/types";
import { GRID_BORDER } from "../../../constants";
import { createDimInfos } from "../../../data/__tests__/test-helper";
import createHeadersData from "../../../data/headers-data";
Expand All @@ -30,6 +36,7 @@ describe("useColumnWidth", () => {
let mockedUseMeasureText: jest.MockedFunction<(styling: UseMeasureTextProps) => MeasureTextHook>;
let mockedMeasureText: MeasureTextHook;
let mockedIsLeftDimension: jest.MockedFunction<(index: number) => boolean>;
let mockedGetDimensionInfoIndex: jest.MockedFunction<(info: VisibleDimensionInfo) => number>;
let layoutService: LayoutService;
let visibleLeftDimensionInfo: VisibleDimensionInfo[];
let visibleTopDimensionInfo: VisibleDimensionInfo[];
Expand All @@ -45,6 +52,7 @@ describe("useColumnWidth", () => {
percentageConversion = tableRect.width / 100;
mockedUseMeasureText = useMeasureText as jest.MockedFunction<typeof useMeasureText>;
mockedIsLeftDimension = jest.fn().mockReturnValue(true);
mockedGetDimensionInfoIndex = jest.fn().mockReturnValue(0);

layoutService = {
layout: {
Expand All @@ -60,7 +68,7 @@ describe("useColumnWidth", () => {
y: 1,
},
getMeasureInfoIndexFromCellIndex: (index: number) => index,
getDimensionInfoIndex: () => 0,
getDimensionInfoIndex: mockedGetDimensionInfoIndex,
isLeftDimension: mockedIsLeftDimension,
} as unknown as LayoutService;

Expand Down Expand Up @@ -130,7 +138,7 @@ describe("useColumnWidth", () => {
expect(leftGridColumnWidths[0]).toBe(width + EXPAND_ICON_SIZE + TOTAL_CELL_PADDING);
});

test("should return left column width for auto setting, not left dimension, 3 top dimension and pseudo last", () => {
test("should return left column width for auto setting, no left dimension, 3 top dimension and pseudo last", () => {
const width = 25;
mockEstimateWidth(width);
mockMeasureText(width);
Expand All @@ -143,6 +151,26 @@ describe("useColumnWidth", () => {
expect(leftGridColumnWidths[0]).toBe(width + TOTAL_CELL_PADDING + MENU_ICON_SIZE);
});

test("should return left column width for pixel setting, 2 left dimensions and pseudo last", () => {
const width = 25;
mockEstimateWidth(width);
mockMeasureText(width);
visibleLeftDimensionInfo = createDimInfos([0, PSEUDO_DIMENSION_INDEX]);
visibleTopDimensionInfo = createDimInfos([1, 2]);
layoutService.layout.qHyperCube.qMeasureInfo = [
{ columnWidth: { type: ColumnWidthType.Pixels, pixels: 30 } } as ExtendedMeasureInfo,
];
mockedGetDimensionInfoIndex.mockImplementation((info) =>
[...visibleLeftDimensionInfo, ...visibleTopDimensionInfo].indexOf(info),
);
mockedIsLeftDimension.mockImplementation((idx) => idx < visibleLeftDimensionInfo.length);
headersData = createHeadersData(layoutService, visibleTopDimensionInfo, visibleLeftDimensionInfo);

const { leftGridColumnWidths } = renderUseColumnWidth();
expect(leftGridColumnWidths[0]).toBe(width + TOTAL_CELL_PADDING + EXPAND_ICON_SIZE);
expect(leftGridColumnWidths[1]).toBe(30);
});

test("should return left column width for pixel setting", () => {
// need to make the width bigger so the col widths are not scaled
tableRect = { width: 800, height: 100 };
Expand Down Expand Up @@ -250,6 +278,27 @@ describe("useColumnWidth", () => {
expect(result.current.leftGridColumnWidths[1]).toBe(width + EXPAND_ICON_SIZE + TOTAL_CELL_PADDING);
expect(result.current.leftGridColumnWidths[2]).toBe(width + TOTAL_CELL_PADDING + MENU_ICON_SIZE);
});

test("should return left column width when column location is set to pivot", () => {
const width = 25;
mockEstimateWidth(width);
mockMeasureText(width);

const topHeadersColumnWidth = 100;

visibleLeftDimensionInfo = createDimInfos([PSEUDO_DIMENSION_INDEX, 0]);
visibleTopDimensionInfo = createDimInfos([1]);
layoutService.layout.qHyperCube.topHeadersColumnWidth = {
type: ColumnWidthType.Pixels,
pixels: topHeadersColumnWidth,
};
headersData = createHeadersData(layoutService, visibleTopDimensionInfo, visibleLeftDimensionInfo);
headersData.data[0][2]!.isLeftDimension = false;
headersData.data[0][2]!.columnWidthLocation = ColumnWidthLocation.Pivot;

const { leftGridColumnWidths } = renderUseColumnWidth();
expect(leftGridColumnWidths[2]).toBe(topHeadersColumnWidth);
});
});

describe("getRightGridColumnWidth", () => {
Expand Down
Loading

0 comments on commit 4462b96

Please sign in to comment.