Skip to content

Commit b43b5b2

Browse files
authored
chore: DH-15527 Move ACL Editor Code to Community (#1490)
Moved ACL Editor util code from Enterprise to Community. This should not introduce any functional changes. Supports #1469 and DH-15527
1 parent d15d6b1 commit b43b5b2

93 files changed

Lines changed: 28831 additions & 17696 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 22631 additions & 17403 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/jsapi-components/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
"@deephaven/log": "file:../log",
3030
"@deephaven/react-hooks": "file:../react-hooks",
3131
"@deephaven/utils": "file:../utils",
32-
"@react-stately/data": "^3.9.1",
3332
"@types/js-cookie": "^3.0.3",
3433
"classnames": "^2.3.2",
3534
"js-cookie": "^3.0.5",

packages/jsapi-components/src/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@ export * from './RefreshTokenBootstrap';
44
export * from './RefreshTokenUtils';
55
export { default as useBroadcastChannel } from './useBroadcastChannel';
66
export { default as useBroadcastLoginListener } from './useBroadcastLoginListener';
7+
export * from './useCheckIfExistsValue';
78
export { default as useDebouncedViewportSearch } from './useDebouncedViewportSearch';
9+
export * from './useDebouncedViewportSelectionFilter';
10+
export * from './useFilterConditionFactories';
11+
export * from './useFilteredItemsWithDefaultValue';
12+
export * from './useGetItemPosition';
813
export { default as useInitializeViewportData } from './useInitializeViewportData';
14+
export * from './useSearchableViewportData';
15+
export * from './useNotNullOrEmptyFilter';
16+
export * from './usePickerWithSelectedValues';
17+
export { default as useSelectDistinctTable } from './useSelectDistinctTable';
18+
export { default as useSetPaddedViewportCallback } from './useSetPaddedViewportCallback';
19+
export * from './useShowOnlyEmptyFilter';
920
export { default as useTable } from './useTable';
1021
export { default as useTableColumn } from './useTableColumn';
1122
export { default as useTableListener } from './useTableListener';
12-
export { default as useSelectDistinctTable } from './useSelectDistinctTable';
13-
export { default as useSetPaddedViewportCallback } from './useSetPaddedViewportCallback';
1423
export { default as useTableClose } from './useTableClose';
1524
export { default as useTableSize } from './useTableSize';
1625
export { default as useTableUtils } from './useTableUtils';
26+
export * from './useValueFilter';
1727
export { default as useViewportData } from './useViewportData';
1828
export type { UseSelectDistinctTableResult } from './useSelectDistinctTable';
1929
export type { UseViewportDataResult } from './useViewportData';
30+
export * from './useViewportFilter';
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { act, renderHook } from '@testing-library/react-hooks';
2+
import type { Table } from '@deephaven/jsapi-types';
3+
import { TableUtils } from '@deephaven/jsapi-utils';
4+
import { TestUtils } from '@deephaven/utils';
5+
import useCheckIfExistsValue from './useCheckIfExistsValue';
6+
import useTableUtils from './useTableUtils';
7+
8+
jest.mock('@deephaven/jsapi-utils');
9+
jest.mock('./useTableUtils');
10+
11+
const { asMock, createMockProxy } = TestUtils;
12+
13+
beforeEach(() => {
14+
jest.clearAllMocks();
15+
expect.hasAssertions();
16+
});
17+
18+
afterEach(() => {
19+
jest.useRealTimers();
20+
});
21+
22+
describe.each([true, false])('useCheckIfExistsValue: %s', valueExists => {
23+
const mock = {
24+
table: createMockProxy<Table>(),
25+
tableUtils: createMockProxy<TableUtils>(),
26+
columnNames: ['mock.columnA', 'mock.columnB'],
27+
debounceMs: 500,
28+
};
29+
30+
function completeDebounce() {
31+
act(() => {
32+
jest.advanceTimersByTime(mock.debounceMs);
33+
});
34+
}
35+
36+
beforeEach(() => {
37+
asMock(useTableUtils)
38+
.mockName('useTableUtils')
39+
.mockReturnValue(mock.tableUtils);
40+
41+
asMock(mock.tableUtils.doesColumnValueExist).mockResolvedValue(valueExists);
42+
});
43+
44+
it.each([true, false])(
45+
'should check if value exists and return result: isCaseSensitive:%s',
46+
async isCaseSensitive => {
47+
const { result, waitForNextUpdate } = renderHook(() =>
48+
useCheckIfExistsValue(
49+
mock.table,
50+
mock.columnNames,
51+
mock.debounceMs,
52+
isCaseSensitive
53+
)
54+
);
55+
56+
await waitForNextUpdate();
57+
58+
expect(mock.tableUtils.doesColumnValueExist).toHaveBeenCalledWith(
59+
mock.table,
60+
mock.columnNames,
61+
'',
62+
isCaseSensitive
63+
);
64+
65+
expect(result.current).toEqual({
66+
valueTrimmed: '',
67+
valueTrimmedDebounced: '',
68+
valueExists,
69+
trimAndUpdateValue: expect.any(Function),
70+
});
71+
}
72+
);
73+
74+
it('should treat valueExists as indeterminant while value check is pending', async () => {
75+
// eslint-disable-next-line no-promise-executor-return
76+
const unresolvedPromise = new Promise<boolean>(() => undefined);
77+
asMock(mock.tableUtils.doesColumnValueExist).mockReturnValue(
78+
unresolvedPromise
79+
);
80+
81+
const { result, waitForNextUpdate } = renderHook(() =>
82+
useCheckIfExistsValue(mock.table, mock.columnNames, mock.debounceMs, true)
83+
);
84+
85+
await waitForNextUpdate();
86+
87+
expect(result.current).toMatchObject({
88+
valueExists: null,
89+
valueTrimmed: '',
90+
valueTrimmedDebounced: '',
91+
});
92+
});
93+
94+
it('should trim search text and treat valueExists as indeterminant while debouncing', async () => {
95+
jest.useFakeTimers();
96+
97+
const { result, waitForNextUpdate } = renderHook(() =>
98+
useCheckIfExistsValue(mock.table, mock.columnNames, mock.debounceMs, true)
99+
);
100+
101+
completeDebounce();
102+
await waitForNextUpdate();
103+
104+
act(() => result.current.trimAndUpdateValue(' blah '));
105+
106+
// While text change debounce is still settling
107+
expect(result.current).toMatchObject({
108+
valueExists: null,
109+
valueTrimmed: 'blah',
110+
valueTrimmedDebounced: '',
111+
});
112+
113+
completeDebounce();
114+
await waitForNextUpdate();
115+
116+
expect(result.current).toMatchObject({
117+
valueExists,
118+
valueTrimmed: 'blah',
119+
valueTrimmedDebounced: 'blah',
120+
});
121+
});
122+
});
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { useCallback, useState } from 'react';
2+
import type { Table } from '@deephaven/jsapi-types';
3+
import { useDebouncedValue, usePromiseFactory } from '@deephaven/react-hooks';
4+
import useTableUtils from './useTableUtils';
5+
6+
export interface CheckIfExistsValue {
7+
/** Current trimmed value */
8+
valueTrimmed: string;
9+
10+
/** Debounced trimmed value */
11+
valueTrimmedDebounced: string;
12+
13+
/**
14+
* Whether the value exists in the given table columns. Will be null whenever
15+
* the value changes until the next check is complete.
16+
*/
17+
valueExists: boolean | null;
18+
19+
/** Trims and updates the value */
20+
trimAndUpdateValue: (value: string) => void;
21+
}
22+
23+
/**
24+
* Manage a trimmed text value and check if it exists in a list of table columns.
25+
* @param table The table to check for the value
26+
* @param columnNames The column names to check
27+
* @param debounceMs Debounce timer for re-checking the value
28+
* @param isCaseSensitive Whether the value check is case sensitive
29+
*/
30+
export function useCheckIfExistsValue(
31+
table: Table | null | undefined,
32+
columnNames: string | string[],
33+
debounceMs: number,
34+
isCaseSensitive: boolean
35+
): CheckIfExistsValue {
36+
const tableUtils = useTableUtils();
37+
38+
const [valueTrimmed, setValueTrimmed] = useState('');
39+
const valueTrimmedDebounced = useDebouncedValue(valueTrimmed, debounceMs);
40+
41+
const trimAndUpdateValue = useCallback((text: string) => {
42+
setValueTrimmed(text.trim());
43+
}, []);
44+
45+
const { data: valueExistsData, isLoading: valueExistsIsLoading } =
46+
usePromiseFactory(tableUtils.doesColumnValueExist, [
47+
table,
48+
columnNames,
49+
valueTrimmedDebounced,
50+
isCaseSensitive,
51+
]);
52+
53+
// If value check is loading or if debounce hasn't settled, set
54+
// `matchesExistingValue` to null since it is indeterminate
55+
const valueExists =
56+
valueExistsIsLoading || valueTrimmed !== valueTrimmedDebounced
57+
? null
58+
: valueExistsData;
59+
60+
return {
61+
valueTrimmed,
62+
valueTrimmedDebounced,
63+
valueExists,
64+
trimAndUpdateValue,
65+
};
66+
}
67+
68+
export default useCheckIfExistsValue;

packages/jsapi-components/src/useDebouncedViewportSearch.test.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ import useDebouncedViewportSearch, {
1313
} from './useDebouncedViewportSearch';
1414
import { UseViewportDataResult } from './useViewportData';
1515
import { makeApiContextWrapper } from './HookTestUtils';
16+
import useTableUtils from './useTableUtils';
1617

17-
const tableUtils = new TableUtils(dh);
18+
jest.mock('./useTableUtils');
19+
20+
const { asMock, createMockProxy } = TestUtils;
21+
22+
const tableUtils = createMockProxy<TableUtils>();
1823

1924
const wrapper = makeApiContextWrapper(dh);
2025

@@ -38,9 +43,8 @@ beforeEach(() => {
3843
TestUtils.asMock(columnFilterValue.contains).mockReturnValue(filterCondition);
3944
TestUtils.asMock(table.findColumn).mockReturnValue(column);
4045

41-
jest
42-
.spyOn(TableUtils.prototype, 'makeFilterValue')
43-
.mockReturnValue(matchFilterValue);
46+
asMock(useTableUtils).mockName('useTableUtils').mockReturnValue(tableUtils);
47+
asMock(tableUtils.makeFilterValue).mockReturnValue(matchFilterValue);
4448
});
4549

4650
it.each([undefined, 400])(

packages/jsapi-components/src/useDebouncedViewportSearch.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import debounce from 'lodash.debounce';
22
import type { Table, TreeTable } from '@deephaven/jsapi-types';
3-
import { TableUtils } from '@deephaven/jsapi-utils';
4-
import { useApi } from '@deephaven/jsapi-bootstrap';
53
import Log from '@deephaven/log';
64
import { useEffect, useMemo } from 'react';
75
import { UseViewportDataResult } from './useViewportData';
6+
import useTableUtils from './useTableUtils';
87

98
const log = Log.module('useDebouncedViewportSearch');
109

@@ -18,16 +17,12 @@ export const DEBOUNCE_VIEWPORT_SEARCH_MS = 200;
1817
* @param debounceMs Millisecond value to debounce
1918
* @returns A debounced search function
2019
*/
21-
export default function useDebouncedViewportSearch<
22-
I,
23-
T extends Table | TreeTable,
24-
>(
20+
export function useDebouncedViewportSearch<I, T extends Table | TreeTable>(
2521
viewportData: UseViewportDataResult<I, T>,
2622
columnName: string,
2723
debounceMs = DEBOUNCE_VIEWPORT_SEARCH_MS
2824
): (searchText: string) => void {
29-
const dh = useApi();
30-
const tableUtils = useMemo(() => new TableUtils(dh), [dh]);
25+
const tableUtils = useTableUtils();
3126
const { table, applyFiltersAndRefresh } = viewportData;
3227

3328
const debouncedSearch = useMemo(
@@ -68,3 +63,5 @@ export default function useDebouncedViewportSearch<
6863

6964
return debouncedSearch;
7065
}
66+
67+
export default useDebouncedViewportSearch;

0 commit comments

Comments
 (0)