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
77 changes: 77 additions & 0 deletions packages/jsapi-components/src/useSetPaddedViewportCallback.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,35 @@ import { TableUtils } from '@deephaven/jsapi-utils';
import useSetPaddedViewportCallback from './useSetPaddedViewportCallback';

let table: dh.Table;
let table2: dh.Table;
let viewportOptions: dh.ViewportSubscriptionOptions;
let viewportOptionsMissingRows: Partial<dh.ViewportSubscriptionOptions>;
let viewportOptionsMissingColumns: Partial<dh.ViewportSubscriptionOptions>;
let viewportOptionsMissingBoth: Partial<dh.ViewportSubscriptionOptions>;
const viewportSize = 10;
const viewportPadding = 4;

beforeEach(() => {
jest.clearAllMocks();
table = TestUtils.createMockProxy<dh.Table>({ size: 100 });
table2 = TestUtils.createMockProxy<dh.Table>({ size: 101 });
viewportOptions = {
rows: {
first: 0,
last: 0,
},
columns: table.columns,
};
viewportOptionsMissingRows = {
columns: table2.columns,
};
viewportOptionsMissingColumns = {
rows: {
first: 5,
last: 15,
},
};
viewportOptionsMissingBoth = {};
});

it('should create a callback that sets a padded viewport', () => {
Expand Down Expand Up @@ -89,6 +104,68 @@ it('should use TableViewportSubscription if viewport options are provided', () =
expect(table.setViewport).not.toHaveBeenCalled();
});

it('should fill missing rows and columns when creating a subscription', () => {
jest.spyOn(TableUtils, 'isTreeTable').mockReturnValue(false);

const mockSubscription = {
update: jest.fn(),
close: jest.fn(),
};

(table.createViewportSubscription as jest.Mock).mockReturnValue(
mockSubscription
);

const { result, rerender } = renderHook(
options =>
useSetPaddedViewportCallback(
table,
viewportSize,
viewportPadding,
options
),
{ initialProps: viewportOptionsMissingRows }
);

const firstRow = 30;
result.current(firstRow);

const expectedRows = {
first: firstRow - viewportPadding,
last: firstRow + viewportSize + viewportPadding - 1,
};

expect(table.createViewportSubscription).toHaveBeenCalledWith({
columns: viewportOptionsMissingRows.columns,
rows: expectedRows,
});

jest.clearAllMocks();

rerender(viewportOptionsMissingColumns);
result.current(firstRow + 5);

expect(table.createViewportSubscription).toHaveBeenCalledWith({
rows: viewportOptionsMissingColumns.rows,
columns: table.columns,
});

jest.clearAllMocks();

rerender(viewportOptionsMissingBoth);
result.current(firstRow + 10);

const expectedRows2 = {
first: firstRow + 10 - viewportPadding,
last: firstRow + 10 + viewportSize + viewportPadding - 1,
};

expect(table.createViewportSubscription).toHaveBeenCalledWith({
rows: expectedRows2,
columns: table.columns,
});
});

it('should use setViewport if provided a tree table', () => {
jest.spyOn(TableUtils, 'isTreeTable').mockReturnValue(true);

Expand Down
19 changes: 12 additions & 7 deletions packages/jsapi-components/src/useSetPaddedViewportCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ import {
* @param viewportPadding The padding to add before and after the viewport.
* @param viewportSubscriptionOptions The viewport subscription options to use. If provided and
* the table is not a `TreeTable`, the data will be requested using a `TableViewportSubscription`.
* Rows and columns are filled in when the subscription is created if they are missing.
* @returns A callback function for setting the viewport.
*/
export function useSetPaddedViewportCallback(
table: dh.Table | dh.TreeTable | null,
viewportSize: number,
viewportPadding: number,
viewportSubscriptionOptions: dh.ViewportSubscriptionOptions | null = null
viewportSubscriptionOptions: Partial<dh.ViewportSubscriptionOptions> | null = null
): (firstRow: number) => void {
const subscriptionRef = useRef<dh.TableViewportSubscription | null>(null);
const prevTableRef = useRef<dh.Table | dh.TreeTable | null>(null);
const prevViewportOptionsRef = useRef<dh.ViewportSubscriptionOptions | null>(
null
);
const prevViewportOptionsRef =
useRef<Partial<dh.ViewportSubscriptionOptions> | null>(null);

const cleanupSubscription = () => {
if (subscriptionRef.current) {
Expand Down Expand Up @@ -66,9 +66,14 @@ export function useSetPaddedViewportCallback(
viewportSubscriptionOptions != null &&
!TableUtils.isTreeTable(table)
) {
subscriptionRef.current = table.createViewportSubscription(
viewportSubscriptionOptions
);
const subscriptionOptions: dh.ViewportSubscriptionOptions = {
...viewportSubscriptionOptions,
rows: viewportSubscriptionOptions.rows ?? { first, last },
columns: viewportSubscriptionOptions.columns ?? table.columns,
};

subscriptionRef.current =
table.createViewportSubscription(subscriptionOptions);
}

if (subscriptionRef.current == null) {
Expand Down
3 changes: 2 additions & 1 deletion packages/jsapi-components/src/useViewportData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface UseViewportDataProps<
viewportPadding?: number;
viewportSize?: number;
deserializeRow?: RowDeserializer<TItem>;
viewportSubscriptionOptions?: dh.ViewportSubscriptionOptions | null;
viewportSubscriptionOptions?: Partial<dh.ViewportSubscriptionOptions> | null;
}

export interface UseViewportDataResult<
Expand Down Expand Up @@ -71,6 +71,7 @@ export interface UseViewportDataResult<
* @param reuseItemsOnTableResize If true, existing items will be re-used when
* @param viewportSubscriptionOptions The viewport subscription options to use. If provided and
* the table is not a `TreeTable`, the data will be requested using a `TableViewportSubscription`.
* Rows and columns are filled in when the subscription is created if they are missing.
* @returns An object for managing Table viewport state.
*/
export function useViewportData<TItem, TTable extends dh.Table | dh.TreeTable>({
Expand Down
Loading