foundation.ts 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  1. /* eslint-disable prefer-destructuring */
  2. /* eslint-disable max-depth */
  3. /* eslint-disable max-nested-callbacks */
  4. /* eslint-disable max-len */
  5. /* eslint-disable no-param-reassign */
  6. /* eslint-disable eqeqeq */
  7. /* eslint-disable @typescript-eslint/no-empty-function */
  8. import {
  9. get,
  10. merge,
  11. isFunction,
  12. each,
  13. find,
  14. some,
  15. pull,
  16. isSet,
  17. filter,
  18. isMap,
  19. slice,
  20. isEqual,
  21. isUndefined
  22. } from 'lodash';
  23. import memoizeOne from 'memoize-one';
  24. import { ArrayElement } from '../utils/type';
  25. import { BaseCheckboxProps } from '../checkbox/checkboxFoundation';
  26. import BaseFoundation, { DefaultAdapter } from '../base/foundation';
  27. import { strings, numbers } from './constants';
  28. import { mergeQueries, flattenColumns, filterColumns } from './utils';
  29. import { pullAll, withOrderSort } from '../utils/array';
  30. export interface BaseColumnProps<RecordType> {
  31. align?: BaseAlign;
  32. children?: Array<BaseColumnProps<RecordType>>;
  33. className?: string;
  34. colSpan?: number;
  35. dataIndex?: string;
  36. defaultFilteredValue?: any[];
  37. defaultSortOrder?: BaseSortOrder;
  38. filterChildrenRecord?: boolean;
  39. filterDropdown?: any;
  40. filterDropdownProps?: Record<string, any>;
  41. filterDropdownVisible?: boolean;
  42. filterIcon?: any;
  43. filterMultiple?: boolean;
  44. filteredValue?: any[];
  45. filters?: BaseFilter[];
  46. fixed?: BaseFixed;
  47. key?: string | number;
  48. onCell?: BaseOnCell<RecordType>;
  49. onFilter?: BaseOnFilter<RecordType>;
  50. onFilterDropdownVisibleChange?: BaseOnFilterDropdownVisibleChange;
  51. onHeaderCell?: BaseOnHeaderCell<RecordType>;
  52. render?: (...args: any[]) => any;
  53. renderFilterDropdownItem?: (...args: any[]) => any;
  54. sortChildrenRecord?: boolean;
  55. sortOrder?: BaseSortOrder;
  56. sorter?: BaseSorter<RecordType>;
  57. title?: any;
  58. useFullRender?: boolean;
  59. width?: string | number
  60. }
  61. export interface TableAdapter<RecordType> extends DefaultAdapter {
  62. resetScrollY: () => void;
  63. setSelectedRowKeys: (selectedRowKeys: BaseRowKeyType[]) => void;
  64. setDisabledRowKeys: (disabledRowKeys: BaseRowKeyType[]) => void;
  65. setCurrentPage: (currentPage: number) => void;
  66. setPagination: (pagination: BasePagination) => void;
  67. setGroups: (groups: Map<string, RecordType[]>) => void;
  68. setDataSource: (dataSource: RecordType[]) => void;
  69. setExpandedRowKeys: (expandedRowKeys: BaseRowKeyType[]) => void;
  70. setQuery: (query?: BaseColumnProps<RecordType>) => void;
  71. setQueries: (queries: BaseColumnProps<RecordType>[]) => void;
  72. setFlattenData: (flattenData: RecordType[]) => void;
  73. setAllRowKeys: (allRowKeys: BaseRowKeyType[]) => void;
  74. setHoveredRowKey: (hoveredRowKey: BaseRowKeyType) => void;
  75. setCachedFilteredSortedDataSource: (filteredSortedDataSource: RecordType[]) => void;
  76. setCachedFilteredSortedRowKeys: (filteredSortedRowKeys: BaseRowKeyType[]) => void;
  77. getCurrentPage: () => number;
  78. getCurrentPageSize: () => number;
  79. getCachedFilteredSortedDataSource: () => RecordType[];
  80. getCachedFilteredSortedRowKeys: () => BaseRowKeyType[];
  81. getCachedFilteredSortedRowKeysSet: () => Set<BaseRowKeyType>;
  82. notifyFilterDropdownVisibleChange: (visible: boolean, dataIndex: string) => void;
  83. notifyChange: (changeInfo: { pagination: BasePagination; filters: BaseChangeInfoFilter<RecordType>[]; sorter: BaseChangeInfoSorter<RecordType>; extra: any }) => void;
  84. notifyExpand: (expanded?: boolean, record?: BaseIncludeGroupRecord<RecordType>, mouseEvent?: any) => void;
  85. notifyExpandedRowsChange: (expandedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
  86. notifySelect: (record?: BaseIncludeGroupRecord<RecordType>, selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
  87. notifySelectAll: (selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], changedRows?: BaseIncludeGroupRecord<RecordType>[], e?: any) => void;
  88. notifySelectInvert: (record?: RecordType[], selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
  89. notifySelectionChange: (selectedRowKeys: BaseRowKeyType[], selectedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
  90. isAnyColumnFixed: (columns?: BaseColumnProps<RecordType>[]) => boolean;
  91. useFixedHeader: () => boolean;
  92. setHeadWidths: (headWidths: Array<BaseHeadWidth>, index?: number) => void;
  93. getHeadWidths: (index?: number) => number[];
  94. getCellWidths: (flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) => number[];
  95. mergedRowExpandable: (record: RecordType) => boolean;
  96. isAnyColumnUseFullRender: (columns: BaseColumnProps<RecordType>[]) => boolean;
  97. getNormalizeColumns: () => (columns: BaseColumnProps<RecordType>[], children: any) => BaseColumnProps<RecordType>[];
  98. getHandleColumns: () => (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[];
  99. getMergePagination: () => (pagination: BasePagination) => BasePagination;
  100. setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void
  101. }
  102. class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
  103. memoizedWithFnsColumns: (
  104. queries: BaseColumnProps<RecordType>[],
  105. cachedColumns: BaseColumnProps<RecordType>[],
  106. rowSelectionUpdate: boolean,
  107. hideExpandedColumn: boolean,
  108. bodyHasScrollBar: boolean,
  109. ) => BaseColumnProps<RecordType>[];
  110. memoizedFilterColumns: (columns: BaseColumnProps<RecordType>[], ignoreKeys?: string[]) => BaseColumnProps<RecordType>[];
  111. memoizedFlattenFnsColumns: (columns: BaseColumnProps<RecordType>[], childrenColumnName?: string) => BaseColumnProps<RecordType>[];
  112. memoizedPagination: (pagination: BasePagination) => BasePagination;
  113. /**
  114. * update columns in place, and use default values as initial values if the sorting and filtering columns have no values
  115. */
  116. static initColumnsFilteredValueAndSorterOrder(columns: BaseColumnProps<unknown>[]) {
  117. columns.forEach(column => {
  118. TableFoundation.initFilteredValue(column);
  119. TableFoundation.initSorterOrder(column);
  120. });
  121. return columns;
  122. }
  123. /**
  124. * init filteredValue of filtering column, use defaultFilteredValue or [] when it is undefined
  125. */
  126. static initFilteredValue(column: BaseColumnProps<unknown>) {
  127. const { defaultFilteredValue, filteredValue, filters } = column;
  128. const hasFilter = Array.isArray(filters) && filters.length;
  129. if (hasFilter && isUndefined(filteredValue)) {
  130. if (Array.isArray(defaultFilteredValue) && defaultFilteredValue.length) {
  131. column.filteredValue = defaultFilteredValue;
  132. } else {
  133. column.filteredValue = [];
  134. }
  135. }
  136. }
  137. /**
  138. * init sortOrder of sorting column, use defaultSortOrder or [] when it is undefined
  139. */
  140. static initSorterOrder(column: BaseColumnProps<unknown>) {
  141. const { defaultSortOrder, sortOrder, sorter } = column;
  142. if (sorter && isUndefined(sortOrder)) {
  143. if (!isUndefined(defaultSortOrder)) {
  144. column.sortOrder = defaultSortOrder;
  145. } else {
  146. column.sortOrder = false;
  147. }
  148. }
  149. }
  150. constructor(adapter: TableAdapter<RecordType>) {
  151. super({ ...adapter });
  152. /**
  153. * memoized function list
  154. */
  155. const handleColumns: (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[] = this._adapter.getHandleColumns();
  156. const mergePagination: (pagination: BasePagination) => BasePagination = this._adapter.getMergePagination();
  157. this.memoizedWithFnsColumns = memoizeOne(handleColumns, isEqual);
  158. this.memoizedFilterColumns = memoizeOne(filterColumns);
  159. this.memoizedFlattenFnsColumns = memoizeOne(flattenColumns);
  160. this.memoizedPagination = memoizeOne(mergePagination, isEqual);
  161. }
  162. init() {
  163. const dataSource = [...this.getProp('dataSource')];
  164. const { queries } = this._adapter.getStates();
  165. const filteredSortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
  166. const pageData = this.getCurrentPageData(filteredSortedDataSource);
  167. this.setAdapterPageData(pageData);
  168. this.initExpandedRowKeys(pageData);
  169. this.initSelectedRowKeys(pageData);
  170. // cache dataSource after mount, and then calculate it on demand
  171. this.setCachedFilteredSortedDataSource(filteredSortedDataSource);
  172. }
  173. initExpandedRowKeys({ groups }: { groups?: Map<string, RecordType[]> } = {}) {
  174. const {
  175. defaultExpandAllRows,
  176. defaultExpandedRowKeys = [],
  177. expandedRowKeys: propExpandedRowKeys = [],
  178. dataSource = [],
  179. expandAllRows,
  180. defaultExpandAllGroupRows,
  181. expandAllGroupRows,
  182. } = this.getProps();
  183. const expandedRowKeys: BaseRowKeyType[] = [];
  184. if (defaultExpandAllRows || expandAllRows) {
  185. this._addNoDuplicatedItemsToArr(
  186. expandedRowKeys,
  187. this.getAllRowKeys(dataSource),
  188. groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
  189. );
  190. } else if (defaultExpandAllGroupRows || expandAllGroupRows) {
  191. this._addNoDuplicatedItemsToArr(
  192. expandedRowKeys,
  193. groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
  194. );
  195. } else if (Array.isArray(defaultExpandedRowKeys) && defaultExpandedRowKeys.length) {
  196. this._addNoDuplicatedItemsToArr(expandedRowKeys, defaultExpandedRowKeys);
  197. } else if (Array.isArray(propExpandedRowKeys) && propExpandedRowKeys.length) {
  198. this._addNoDuplicatedItemsToArr(expandedRowKeys, propExpandedRowKeys);
  199. }
  200. this._adapter.setExpandedRowKeys(expandedRowKeys);
  201. }
  202. initSelectedRowKeys({ disabledRowKeys }: { disabledRowKeys?: BaseRowKeyType[] }) {
  203. const rowSelection = this.getProp('rowSelection');
  204. const rowKeys: BaseRowKeyType[] = [];
  205. if (rowSelection) {
  206. const selectedRowKeys = get(rowSelection, 'selectedRowKeys');
  207. const defaultSelectedRowKeys = get(rowSelection, 'defaultSelectedRowKeys');
  208. if (Array.isArray(selectedRowKeys)) {
  209. this._addNoDuplicatedItemsToArr(rowKeys, selectedRowKeys);
  210. } else if (Array.isArray(defaultSelectedRowKeys)) {
  211. this._addNoDuplicatedItemsToArr(rowKeys, defaultSelectedRowKeys);
  212. }
  213. if (Array.isArray(disabledRowKeys) && disabledRowKeys.length) {
  214. pull(rowKeys, ...disabledRowKeys);
  215. }
  216. this._adapter.setSelectedRowKeys(rowKeys);
  217. }
  218. }
  219. /**
  220. * Get filtered and sorted data
  221. * @param {Object[]} dataSource
  222. * @param {Object[]} queries
  223. * @returns {Object[]} sortedDataSource
  224. */
  225. getFilteredSortedDataSource(dataSource: RecordType[], queries: BaseColumnProps<RecordType>[]) {
  226. const filteredDataSource = this.filterDataSource(dataSource, queries.filter(
  227. query => {
  228. /**
  229. * 这里无需判断 filteredValue 是否为数组,初始化时它是 `undefined`,点击选择空时为 `[]`
  230. * 初始化时我们应该用 `defaultFilteredValue`,点击后我们应该用 `filteredValue`
  231. *
  232. * There is no need to judge whether `filteredValue` is an array here, because it is `undefined` when initialized, and `[]` when you click to select empty
  233. * When initializing we should use `defaultFilteredValue`, after clicking we should use `filteredValue`
  234. */
  235. const currentFilteredValue = query.filteredValue ? query.filteredValue : query.defaultFilteredValue;
  236. return (
  237. isFunction(query.onFilter) &&
  238. Array.isArray(query.filters) &&
  239. query.filters.length &&
  240. Array.isArray(currentFilteredValue) &&
  241. currentFilteredValue.length
  242. );
  243. }
  244. ));
  245. const sortedDataSource = this.sortDataSource(filteredDataSource, queries.filter(query => query && isFunction(query.sorter)));
  246. return sortedDataSource;
  247. }
  248. /**
  249. * get current page data
  250. *
  251. * @param {Array} dataSource
  252. * @param {object} pagination
  253. * @param {object} queries
  254. * @returns {{dataSource: RecordType[], groups: Map<string, Set<string>>, pagination: object, disabledRowKeys: string[], queries: BaseColumnProps[], allRowKeys: string[]}}
  255. */
  256. getCurrentPageData(dataSource?: RecordType[], pagination?: BasePagination, queries?: BaseColumnProps<RecordType>[]) {
  257. const filteredSortedDataSource = this._adapter.getCachedFilteredSortedDataSource();
  258. dataSource = dataSource == null ? [...filteredSortedDataSource] : dataSource;
  259. pagination =
  260. pagination == null ? this.getState('pagination') && { ...this.getState('pagination') } : pagination;
  261. queries = queries == null ? [...this.getState('queries')] : queries;
  262. let groups;
  263. if (this.getProp('groupBy') != null) {
  264. const { groups: groupedGroups, dataSource: groupedData } = this.groupDataSource(dataSource);
  265. dataSource = groupedData;
  266. groups = groupedGroups;
  267. }
  268. pagination = this.normalizePagination(pagination, dataSource);
  269. dataSource = this.limitPageDataSource(dataSource, pagination);
  270. const disabledRowKeys = this.getAllDisabledRowKeys(dataSource);
  271. const allRowKeys = this.getAllRowKeys(dataSource);
  272. const pageData: BasePageData<RecordType> = {
  273. dataSource,
  274. groups,
  275. pagination,
  276. disabledRowKeys,
  277. allRowKeys,
  278. queries,
  279. };
  280. return pageData;
  281. }
  282. /**
  283. * group dataSource, return grouped row keys
  284. *
  285. * @param {*[]} dataSource
  286. * @param {Function|string} groupBy
  287. */
  288. groupDataSource(dataSource: RecordType[], groupBy?: BaseGroupBy<RecordType>) {
  289. groupBy = groupBy == null ? this.getProp('groupBy') : groupBy;
  290. const groups = new Map();
  291. const newDataSource = [];
  292. if (groupBy != null) {
  293. each(dataSource, (record, index) => {
  294. const groupKey = typeof groupBy === 'function' ? groupBy(record) : get(record, groupBy);
  295. if (groupKey != null && groupKey !== '') {
  296. const recordKey = this.getRecordKey(record);
  297. let group = groups.get(groupKey);
  298. if (!isSet(group)) {
  299. group = new Set([recordKey]);
  300. groups.set(groupKey, group);
  301. } else {
  302. group.add(recordKey);
  303. }
  304. }
  305. });
  306. }
  307. if (groups && groups.size) {
  308. groups.forEach((set, key) => {
  309. if (isSet(set)) {
  310. set.forEach(realKey => {
  311. newDataSource.push(this._getRecord(realKey));
  312. });
  313. }
  314. });
  315. } else {
  316. newDataSource.push(...dataSource);
  317. }
  318. return { groups, dataSource: newDataSource };
  319. }
  320. /**
  321. * sort data
  322. *
  323. * @param {Array} dataSource
  324. * @param {Array} sorters
  325. * @returns {Array}
  326. */
  327. sortDataSource(dataSource: RecordType[], sorters: BaseSorterInfo<RecordType>[]) {
  328. each(sorters, sorterObj => {
  329. // const sorterObj = last(sorters) || {};
  330. const { sorter, sortOrder, defaultSortOrder, sortChildrenRecord } = sorterObj;
  331. const currentSortOrder = this.isSortOrderValid(sortOrder) ? sortOrder : defaultSortOrder;
  332. if (isFunction(sorter) && (currentSortOrder && strings.SORT_DIRECTIONS.includes(currentSortOrder))) {
  333. if (sortChildrenRecord) {
  334. const childrenRecordName = this.getProp('childrenRecordName');
  335. dataSource =
  336. dataSource &&
  337. dataSource.map(record => {
  338. const children = this._getRecordChildren(record);
  339. if (Array.isArray(children) && children.length) {
  340. return {
  341. ...record,
  342. [childrenRecordName]: this.sortDataSource(children, [sorterObj]),
  343. };
  344. }
  345. return record;
  346. });
  347. }
  348. dataSource.sort(withOrderSort(sorter, currentSortOrder));
  349. return false;
  350. }
  351. return undefined;
  352. });
  353. return dataSource;
  354. }
  355. /**
  356. * set page number
  357. */
  358. setPage = (currentPage: number, currentPageSize: number) => {
  359. currentPage = currentPage || this._adapter.getCurrentPage();
  360. const currentPagination = this.getState('pagination');
  361. const { dataSource, pagination, disabledRowKeys, allRowKeys } = this.getCurrentPageData(null, {
  362. ...currentPagination,
  363. currentPage,
  364. pageSize: currentPageSize,
  365. });
  366. if (!this._pagerIsControlled() && currentPage > 0) {
  367. this._adapter.setDisabledRowKeys(disabledRowKeys);
  368. this._adapter.setAllRowKeys(allRowKeys);
  369. this._adapter.setPagination(pagination);
  370. this._adapter.setDataSource(dataSource);
  371. }
  372. this._notifyChange(pagination);
  373. };
  374. /**
  375. * filter data source
  376. *
  377. * @param {*[]} dataSource
  378. * @param {*[]} filters
  379. * @returns {*[]}
  380. */
  381. filterDataSource(dataSource: RecordType[], filters: BaseChangeInfoFilter<RecordType>[]) {
  382. let filteredData: Map<string, RecordType> | null = null;
  383. let hasValidFilters = false;
  384. const childrenRecordName = this.getProp('childrenRecordName');
  385. each(filters, filterObj => {
  386. const { onFilter, filteredValue, filterChildrenRecord, defaultFilteredValue } = filterObj;
  387. const currentFilteredValue = Array.isArray(filteredValue) ? filteredValue : defaultFilteredValue;
  388. if (typeof onFilter === 'function' && Array.isArray(currentFilteredValue) && currentFilteredValue.length) {
  389. hasValidFilters = true;
  390. if (filteredData === null) {
  391. filteredData = new Map();
  392. } else {
  393. dataSource = Array.from(filteredData && filteredData.values());
  394. filteredData = new Map();
  395. }
  396. each(dataSource, record => {
  397. each(currentFilteredValue, value => {
  398. const childrenRecords = get(record, childrenRecordName);
  399. const recordKey = this.getRecordKey(record);
  400. let filteredChildren;
  401. if (Array.isArray(childrenRecords) && childrenRecords.length && filterChildrenRecord) {
  402. filteredChildren = this.filterDataSource(childrenRecords, [filterObj]);
  403. }
  404. if (Array.isArray(filteredChildren) && filteredChildren.length) {
  405. if (recordKey != null) {
  406. const children = get(filteredData.get(recordKey), childrenRecordName, []);
  407. filteredData.set(recordKey, {
  408. ...record,
  409. [childrenRecordName]: filteredChildren.reduce(
  410. (arr, cur) => {
  411. if (
  412. arr.find((item: any) => this.getRecordKey(item) === this.getRecordKey(cur)) ==
  413. null
  414. ) {
  415. arr.push(cur);
  416. }
  417. return arr;
  418. },
  419. [...children]
  420. ),
  421. });
  422. }
  423. } else if (onFilter(value, record)) {
  424. filteredData.set(recordKey, record);
  425. }
  426. });
  427. });
  428. }
  429. });
  430. if (hasValidFilters) {
  431. dataSource = Array.from(filteredData && filteredData.values());
  432. }
  433. return dataSource;
  434. }
  435. limitPageDataSource(dataSource: RecordType[], pagination: BasePagination) {
  436. dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
  437. pagination = pagination == null ? this.getState('pagination') : pagination;
  438. let pageData = dataSource;
  439. const pageNo = get(pagination, 'currentPage');
  440. if (this.getProp('pagination') !== false && pageNo && dataSource && pagination && !this._pagerIsControlled()) {
  441. const { pageSize = numbers.DEFAULT_PAGE_SIZE } = pagination;
  442. const start = (pageNo - 1) * pageSize;
  443. const end = pageNo * pageSize;
  444. pageData = slice(dataSource, start, end);
  445. }
  446. return pageData;
  447. }
  448. normalizePagination(pagination: BasePagination, dataSource: RecordType[]) {
  449. pagination = pagination == null ? this._getPagination() : pagination;
  450. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  451. const propPagination = this.getProp('pagination');
  452. if (pagination) {
  453. pagination = typeof pagination === 'object' ? { ...pagination } : {};
  454. pagination = merge(
  455. {
  456. total: (dataSource && dataSource.length) || 0,
  457. pageSize: numbers.DEFAULT_PAGE_SIZE,
  458. currentPage: get(propPagination, 'defaultCurrentPage', 1),
  459. position: strings.PAGINATION_POSITIONS[0],
  460. },
  461. pagination
  462. );
  463. if (!this._pagerIsControlled()) {
  464. const total = get(propPagination, 'total', dataSource.length);
  465. const pageSize = get(propPagination, 'pageSize', pagination.pageSize);
  466. const { currentPage } = pagination;
  467. const realTotalPage = Math.ceil(total / pageSize);
  468. pagination.total = total;
  469. if (currentPage > realTotalPage) {
  470. pagination.currentPage = 1;
  471. }
  472. }
  473. }
  474. return pagination;
  475. }
  476. setAdapterPageData(pageData: BasePageData<RecordType> = {}) {
  477. const { pagination, dataSource, disabledRowKeys, allRowKeys, groups } = pageData;
  478. this._adapter.setDisabledRowKeys(disabledRowKeys);
  479. this._adapter.setAllRowKeys(allRowKeys);
  480. this._adapter.setPagination(pagination);
  481. this._adapter.setGroups(groups);
  482. this._adapter.setDataSource(dataSource);
  483. }
  484. /**
  485. * Cache related data when initializing or updating the calculated dataSource
  486. * @param {*} filteredSortedDataSource
  487. */
  488. setCachedFilteredSortedDataSource = (filteredSortedDataSource: RecordType[]) => {
  489. this._adapter.setCachedFilteredSortedDataSource(filteredSortedDataSource);
  490. const filteredSortedRowKeys = this.getAllRowKeys(filteredSortedDataSource);
  491. this._adapter.setCachedFilteredSortedRowKeys(filteredSortedRowKeys);
  492. };
  493. destroy() { }
  494. handleClick(e: any) { }
  495. handleMouseEnter(e: any) { }
  496. handleMouseLeave(e: any) { }
  497. stopPropagation(e: any) {
  498. this._adapter.stopPropagation(e);
  499. }
  500. /**
  501. * Add non-repeating elements to the array itself
  502. * @param {Array} srcArr
  503. * @param {Object} objArrs
  504. */
  505. _addNoDuplicatedItemsToArr(srcArr: any[] = [], ...objArrs: any[]) {
  506. for (const objArr of objArrs) {
  507. if (Array.isArray(objArr)) {
  508. for (const item of objArr) {
  509. if (!srcArr.includes(item)) {
  510. srcArr.push(item);
  511. }
  512. }
  513. }
  514. }
  515. return srcArr;
  516. }
  517. _notifyChange(pagination: BasePagination, filters?: BaseChangeInfoFilter<RecordType>[], sorter?: BaseChangeInfoSorter<RecordType>, extra?: RecordType) {
  518. pagination = pagination == null ? this._getPagination() : pagination;
  519. filters = filters == null ? this._getAllFilters() : filters;
  520. sorter = sorter == null ? this._getAllSorters()[0] as BaseChangeInfoSorter<RecordType> : sorter;
  521. if (get(this.getProp('scroll'), 'scrollToFirstRowOnChange')) {
  522. this._adapter.resetScrollY();
  523. }
  524. this._adapter.notifyChange({
  525. pagination: { ...pagination },
  526. filters: [...filters],
  527. sorter,
  528. extra: { ...extra },
  529. });
  530. }
  531. _rowExpansionIsControlled() {
  532. return Array.isArray(this.getProp('expandedRowKeys'));
  533. }
  534. _pagerIsControlled() {
  535. return get(this.getProp('pagination'), 'currentPage') != null;
  536. }
  537. _selectionIsControlled() {
  538. return Array.isArray(get(this.getProp('rowSelection'), 'selectedRowKeys'));
  539. }
  540. /**
  541. * Determine whether the column sorting is controlled
  542. * Controlled: the column passed the sortOrder prop
  543. * @param {String} dataIndex
  544. * @returns {Boolean}
  545. */
  546. _sorterIsControlled(dataIndex: string) {
  547. // The basis for judgment should be props columns instead of cachedColumns fix#1141
  548. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  549. return Boolean(query && query.sortOrder != null);
  550. }
  551. /**
  552. * Determine whether the column is filtered and controlled
  553. * Controlled: the column passed the filteredValue prop
  554. * @param {String} dataIndex
  555. * @returns {Boolean}
  556. */
  557. _filterIsControlled(dataIndex: string) {
  558. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  559. return Boolean(query && Array.isArray(query.filteredValue));
  560. }
  561. _filterShowIsControlled(dataIndex?: string) {
  562. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  563. return Boolean(query && (query.filterDropdownVisible === true || query.filterDropdownVisible === false));
  564. }
  565. _getSelectedRowKeys() {
  566. const rowSelection = this.getState('rowSelection');
  567. const selectedRowKeys = get(rowSelection, 'selectedRowKeys', []);
  568. return [...selectedRowKeys];
  569. }
  570. _getSelectedRowKeysSet() {
  571. const rowSelection = this.getState('rowSelection');
  572. const selectedRowKeysSet = get(rowSelection, 'selectedRowKeysSet', new Set());
  573. return selectedRowKeysSet;
  574. }
  575. _getDataSource() {
  576. return this.getProp('dataSource') || [];
  577. }
  578. _getRecord(realKey: string | number) {
  579. return find(
  580. this.getProp('dataSource'),
  581. record => realKey != null && realKey !== '' && this.getRecordKey(record) === realKey
  582. );
  583. }
  584. _getRecordChildren(record: RecordType) {
  585. return get(record, this.getProp('childrenRecordName'));
  586. }
  587. _getPagination() {
  588. return this.getState('pagination') || {};
  589. }
  590. _getAllFilters(queries?: BaseColumnProps<RecordType>[]) {
  591. queries = queries || this.getState('queries');
  592. const filters: BaseChangeInfoFilter<RecordType>[] = [];
  593. each(queries, query => {
  594. if (
  595. Array.isArray(query.filteredValue) &&
  596. (query.filteredValue.length || this._filterIsControlled(query.dataIndex))
  597. ) {
  598. filters.push(query);
  599. }
  600. });
  601. return filters;
  602. }
  603. _getAllSorters(queries?: BaseColumnProps<RecordType>[]): BaseColumnProps<RecordType>[] {
  604. queries = queries || this.getState('queries');
  605. return filter(queries, query => query.sorter && query.sortOrder) as BaseColumnProps<RecordType>[];
  606. }
  607. _filterQueries(targetQuery: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
  608. queries = queries == null ? this.getState('queries') : queries;
  609. const filteredQueries: BaseColumnProps<RecordType>[] = [];
  610. const filteredIndexes: number[] = [];
  611. each(queries, (itQuery, index) => {
  612. const flag = some(keys, k => k && targetQuery[k] != null && targetQuery[k] === itQuery[k]);
  613. if (flag) {
  614. filteredQueries.push(itQuery);
  615. filteredIndexes.push(index);
  616. }
  617. });
  618. return { filteredQueries, filteredIndexes };
  619. }
  620. _mergeToQueries(query: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
  621. queries = queries == null ? this.getState('queries') : queries;
  622. queries = [...queries];
  623. query = { ...query };
  624. const { filteredQueries, filteredIndexes } = this._filterQueries(query, queries, keys);
  625. each(filteredQueries, (curQuery, idx) => {
  626. // assign(curQuery, query);
  627. queries[filteredIndexes[idx]] = { ...query };
  628. });
  629. return queries;
  630. }
  631. /**
  632. * get record real key
  633. * @param {RecordType} record
  634. * @returns {string}
  635. */
  636. getRecordKey(record: RecordType): string {
  637. if (!record) {
  638. return undefined;
  639. }
  640. const rowKey = this.getProp('rowKey');
  641. return typeof rowKey === 'function' ? rowKey(record) : get(record, rowKey);
  642. }
  643. isEmpty(dataSource: RecordType[]) {
  644. dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
  645. return !(Array.isArray(dataSource) && dataSource.length > 0);
  646. }
  647. handleSelectRow(realKey: BaseRowKeyType, selected: boolean, e: any) {
  648. this.stopPropagation(e);
  649. if (typeof selected === 'boolean' && realKey != null) {
  650. const selectedRowKeys = this._getSelectedRowKeys();
  651. let foundIdx = -1;
  652. const selectedRow = this.getSelectedRows(null, [realKey])[0];
  653. let selectedRows: BaseIncludeGroupRecord<RecordType>[];
  654. if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
  655. selectedRowKeys.splice(foundIdx, 1);
  656. selectedRows = this.getSelectedRows(null, selectedRowKeys);
  657. if (!this._selectionIsControlled()) {
  658. this._adapter.setSelectedRowKeys(selectedRowKeys);
  659. }
  660. this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
  661. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  662. } else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
  663. selectedRowKeys.push(realKey);
  664. selectedRows = this.getSelectedRows(null, selectedRowKeys);
  665. if (!this._selectionIsControlled()) {
  666. this._adapter.setSelectedRowKeys(selectedRowKeys);
  667. }
  668. this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
  669. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  670. }
  671. }
  672. }
  673. /**
  674. * select all rows
  675. * @param {*} selected The future state of the select all button
  676. * @param {*} e
  677. */
  678. handleSelectAllRow(selected: boolean, e: any) {
  679. this.stopPropagation(e);
  680. if (typeof selected === 'boolean') {
  681. const curSelectedRowKeys = this._getSelectedRowKeys();
  682. let selectedRowKeys = [...curSelectedRowKeys];
  683. const selectedRowKeysSet = this._getSelectedRowKeysSet();
  684. let allRowKeys = [...this._adapter.getCachedFilteredSortedRowKeys()];
  685. const disabledRowKeys = this.getAllDisabledRowKeys();
  686. const disabledRowKeysSet = new Set(disabledRowKeys);
  687. let changedRowKeys;
  688. // Select all, if not disabled && not in selectedRowKeys
  689. if (selected) {
  690. for (const key of allRowKeys) {
  691. if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
  692. selectedRowKeys.push(key);
  693. }
  694. }
  695. allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
  696. changedRowKeys = [...allRowKeys];
  697. } else {
  698. selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
  699. changedRowKeys = [...curSelectedRowKeys];
  700. }
  701. const changedRows = this.getSelectedRows(null, changedRowKeys || []);
  702. const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
  703. if (!this._selectionIsControlled()) {
  704. this._adapter.setSelectedRowKeys(selectedRowKeys);
  705. }
  706. this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
  707. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  708. }
  709. }
  710. /**
  711. * row keys => rows
  712. * @param {*} dataSource
  713. * @param {*} selectedRowKeys
  714. * @param {*} selectedRowKeysSet Recursive optimization
  715. */
  716. getSelectedRows(dataSource: RecordType[], selectedRowKeys: BaseRowKeyType[], selectedRowKeysSet?: Set<BaseRowKeyType>): BaseIncludeGroupRecord<RecordType>[] {
  717. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  718. selectedRowKeys = selectedRowKeys == null ? this._getSelectedRowKeys() : selectedRowKeys;
  719. if (!isSet(selectedRowKeysSet)) {
  720. selectedRowKeysSet = new Set(selectedRowKeys);
  721. }
  722. const childrenRecordName = this.getProp('childrenRecordName');
  723. const selectedRows: BaseIncludeGroupRecord<RecordType>[] = [];
  724. if (
  725. isSet(selectedRowKeysSet) &&
  726. selectedRowKeysSet.size &&
  727. Array.isArray(dataSource) &&
  728. dataSource.length
  729. ) {
  730. // Time complexity optimization, replace the includes operation of array with has of set
  731. selectedRows.push(...dataSource.filter(data => selectedRowKeysSet.has(this.getRecordKey(data))));
  732. if (selectedRows.length < selectedRowKeys.length) {
  733. for (const item of dataSource) {
  734. const children = get(item, childrenRecordName);
  735. if (Array.isArray(children) && children.length) {
  736. const rows = this.getSelectedRows(children, selectedRowKeys, selectedRowKeysSet);
  737. selectedRows.push(...rows);
  738. }
  739. }
  740. }
  741. }
  742. return selectedRows;
  743. }
  744. getAllDisabledRowKeys(dataSource?: RecordType[], getCheckboxProps?: GetCheckboxProps<RecordType>): BaseRowKeyType[] {
  745. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  746. getCheckboxProps =
  747. getCheckboxProps == null ? get(this.getProp('rowSelection'), 'getCheckboxProps') : getCheckboxProps;
  748. const childrenRecordName = this.getProp('childrenRecordName');
  749. const disabledRowKeys: BaseRowKeyType[] = [];
  750. if (Array.isArray(dataSource) && dataSource.length && typeof getCheckboxProps === 'function') {
  751. for (const record of dataSource) {
  752. const props = getCheckboxProps(record);
  753. if (props && props.disabled) {
  754. disabledRowKeys.push(this.getRecordKey(record));
  755. }
  756. const children = get(record, childrenRecordName);
  757. if (Array.isArray(children) && children.length) {
  758. const keys: BaseRowKeyType[] = this.getAllDisabledRowKeys(children, getCheckboxProps);
  759. disabledRowKeys.push(...keys);
  760. }
  761. }
  762. }
  763. return disabledRowKeys;
  764. }
  765. getAllRowKeys(dataSource: RecordType[]): BaseRowKeyType[] {
  766. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  767. const childrenRecordName = this.getProp('childrenRecordName');
  768. const allRowKeys = [];
  769. if (Array.isArray(dataSource) && dataSource.length) {
  770. for (const record of dataSource) {
  771. const childrenRowKeys = [];
  772. const children = get(record, childrenRecordName);
  773. if (Array.isArray(children) && children.length) {
  774. childrenRowKeys.push(...this.getAllRowKeys(children));
  775. }
  776. allRowKeys.push(this.getRecordKey(record), ...childrenRowKeys);
  777. }
  778. }
  779. return allRowKeys;
  780. }
  781. /**
  782. * Check if the selected item is in allRowKeysSet
  783. * @param {Array} selectedRowKeys
  784. * @param {Set} allRowKeysSet
  785. */
  786. hasRowSelected(selectedRowKeys: BaseRowKeyType[], allRowKeysSet: Set<BaseRowKeyType>) {
  787. return Boolean(Array.isArray(selectedRowKeys) &&
  788. selectedRowKeys.length &&
  789. isSet(allRowKeysSet) &&
  790. allRowKeysSet.size &&
  791. selectedRowKeys.filter(key => allRowKeysSet.has(key)).length);
  792. }
  793. /**
  794. * expand processing function
  795. * @param {Boolean} expanded
  796. * @param {String} realKey
  797. * @param {Event} domEvent
  798. */
  799. handleRowExpanded(expanded: boolean, realKey: string, domEvent: any) {
  800. this.stopPropagation(domEvent);
  801. const expandedRowKeys = [...this.getState('expandedRowKeys')];
  802. const index = expandedRowKeys.indexOf(realKey);
  803. const keyIsValid = typeof realKey === 'string' || typeof realKey === 'number';
  804. if (keyIsValid && expanded && index === -1) {
  805. expandedRowKeys.push(realKey);
  806. } else if (keyIsValid && !expanded && index > -1) {
  807. expandedRowKeys.splice(index, 1);
  808. }
  809. if (!this._rowExpansionIsControlled()) {
  810. this._adapter.setExpandedRowKeys(expandedRowKeys);
  811. }
  812. const expandedRows = this.getSelectedRows(null, expandedRowKeys);
  813. let expandedRow = this.getSelectedRows(null, [realKey])[0];
  814. // groups record processing
  815. const groups = this._getGroups();
  816. if (groups) {
  817. // Construct group expandRow
  818. if (groups.has(realKey)) {
  819. expandedRow = { groupKey: realKey };
  820. }
  821. // If expandedRowKeys includes groupKey, add to expandedRows
  822. for (let i = 0, len = expandedRowKeys.length; i < len; i++) {
  823. if (groups.has(realKey)) {
  824. expandedRows.push({ groupKey: expandedRowKeys[i] });
  825. }
  826. }
  827. }
  828. this._adapter.notifyExpand(expanded, expandedRow, domEvent);
  829. this._adapter.notifyExpandedRowsChange(expandedRows);
  830. }
  831. /**
  832. * get state.groups
  833. * @returns {Map|Null}
  834. */
  835. _getGroups() {
  836. const groupBy = this._adapter.getProp('groupBy');
  837. if (groupBy !== null) {
  838. const groups = this._adapter.getState('groups');
  839. return groups;
  840. }
  841. return null;
  842. }
  843. /**
  844. * Determine whether you have selected all except for disabled
  845. * @param {Set} selectedRowKeysSet
  846. * @param {Set} disabledRowKeysSet
  847. * @param {Array} allKeys keys after sorted and filtered
  848. */
  849. allIsSelected(selectedRowKeysSet: Set<BaseRowKeyType>, disabledRowKeysSet: Set<BaseRowKeyType>, allKeys: BaseRowKeyType[]) {
  850. const filteredAllKeys = filter(allKeys, key => key != null && !disabledRowKeysSet.has(key));
  851. if (filteredAllKeys && filteredAllKeys.length) {
  852. for (const key of filteredAllKeys) {
  853. if (key != null && !selectedRowKeysSet.has(key)) {
  854. return false;
  855. }
  856. }
  857. return true;
  858. } else {
  859. return false;
  860. }
  861. }
  862. /**
  863. * This function is not used yet
  864. * @param {*} selectedRowKeys
  865. * @param {*} allKeys
  866. */
  867. allIsNotSelected(selectedRowKeys: BaseRowKeyType[], allKeys: BaseRowKeyType[]) {
  868. for (const key of allKeys) {
  869. if (key != null && Array.isArray(selectedRowKeys) && selectedRowKeys.includes(key)) {
  870. return true;
  871. }
  872. }
  873. return false;
  874. }
  875. formatPaginationInfo(pagination: BasePagination = {}, defaultPageText = '') {
  876. let info = '';
  877. const formatPageText = get(this.getProp('pagination'), 'formatPageText');
  878. const { total, pageSize, currentPage } = pagination;
  879. const currentStart = Math.min((currentPage - 1) * pageSize + 1, total);
  880. const currentEnd = Math.min(currentPage * pageSize, total);
  881. if (formatPageText || (formatPageText !== false && defaultPageText && total > 0)) {
  882. info =
  883. typeof formatPageText === 'function' ?
  884. formatPageText({ currentStart, currentEnd, total }) :
  885. defaultPageText
  886. .replace('${currentStart}', currentStart as any)
  887. .replace('${currentEnd}', currentEnd as any)
  888. .replace('${total}', total as any);
  889. }
  890. return info;
  891. }
  892. toggleShowFilter(dataIndex: string, visible: boolean) {
  893. let filterObj: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
  894. const filterDropdownVisible = visible;
  895. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  896. filterObj = { ...filterObj, filterDropdownVisible };
  897. if (!this._filterShowIsControlled()) {
  898. // this._adapter.setQuery({
  899. // ...filterObj,
  900. // filterDropdownVisible,
  901. // });
  902. }
  903. this._adapter.notifyFilterDropdownVisibleChange(filterDropdownVisible, dataIndex);
  904. }
  905. /**
  906. * Called when the filter changes
  907. * @param {*} dataIndex
  908. * @param {*} data
  909. */
  910. handleFilterSelect(dataIndex: string, data: { filteredValue?: string[] } = {}) {
  911. let query: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
  912. let queries = [...this._adapter.getState('queries')];
  913. const { filteredValue } = data;
  914. query = {
  915. ...query,
  916. filteredValue,
  917. };
  918. queries = mergeQueries(query, queries);
  919. const mergedQueries = this._mergeToQueries(query, null);
  920. const filters = this._getAllFilters(mergedQueries);
  921. if (!this._filterIsControlled(dataIndex)) {
  922. this._adapter.setQueries(queries);
  923. this.handleClickFilterOrSorter(queries);
  924. }
  925. this._notifyChange(null, filters);
  926. }
  927. /**
  928. * Click the sort button to call
  929. * @param {*} column
  930. * @param {*} e
  931. */
  932. handleSort(column: { dataIndex?: string; sortOrder?: BaseSortOrder } = {}, e: any) {
  933. this.stopPropagation(e);
  934. const { dataIndex } = column;
  935. let queries = this.getState('queries');
  936. let curQuery = null;
  937. queries = [...queries];
  938. each(queries, (query, idx, arr) => {
  939. if (query.sorter) {
  940. const sorterObj = { ...query };
  941. const stateSortOrder = get(sorterObj, 'sortOrder');
  942. const defaultSortOrder = get(sorterObj, 'defaultSortOrder', false);
  943. let querySortOrder = this.isSortOrderValid(stateSortOrder) ? stateSortOrder : defaultSortOrder;
  944. if (dataIndex && dataIndex === sorterObj.dataIndex) {
  945. if (querySortOrder === strings.SORT_DIRECTIONS[0]) {
  946. querySortOrder = strings.SORT_DIRECTIONS[1];
  947. } else if (querySortOrder === strings.SORT_DIRECTIONS[1]) {
  948. querySortOrder = false;
  949. } else {
  950. querySortOrder = strings.SORT_DIRECTIONS[0];
  951. }
  952. } else {
  953. // This results in the current click only supports single column sorting
  954. querySortOrder = false;
  955. }
  956. arr[idx] = { ...sorterObj, sortOrder: querySortOrder };
  957. if (dataIndex === sorterObj.dataIndex) {
  958. curQuery = arr[idx];
  959. }
  960. }
  961. });
  962. if (!this._sorterIsControlled(dataIndex)) {
  963. this._adapter.setQueries(queries);
  964. this.handleClickFilterOrSorter(queries);
  965. }
  966. // notify sort event
  967. this._notifyChange(null, null, curQuery, null);
  968. }
  969. /**
  970. * Recalculate the cached data after clicking filter or sorter
  971. * @param {*} queries
  972. */
  973. handleClickFilterOrSorter(queries: BaseColumnProps<RecordType>[]) {
  974. const dataSource = [...this.getProp('dataSource')];
  975. const sortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
  976. this.setCachedFilteredSortedDataSource(sortedDataSource);
  977. const pageData = this.getCurrentPageData(sortedDataSource);
  978. this.setAdapterPageData(pageData);
  979. }
  980. getQuery(dataIndex: string, queries?: BaseColumnProps<RecordType>[]) {
  981. queries = queries || this.getState('queries');
  982. if (dataIndex != null) {
  983. return find(queries, query => query.dataIndex === dataIndex);
  984. }
  985. return undefined;
  986. }
  987. getCellWidths(flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) {
  988. return this._adapter.getCellWidths(flattenedColumns, flattenedWidths, ignoreScrollBarKey);
  989. }
  990. setHeadWidths(headWidths: Array<BaseHeadWidth>, index?: number) {
  991. return this._adapter.setHeadWidths(headWidths, index);
  992. }
  993. getHeadWidths(index: number) {
  994. return this._adapter.getHeadWidths(index);
  995. }
  996. mergedRowExpandable(record: RecordType) {
  997. return this._adapter.mergedRowExpandable(record);
  998. }
  999. setBodyHasScrollbar(bodyHasScrollbar: boolean) {
  1000. this._adapter.setBodyHasScrollbar(bodyHasScrollbar);
  1001. }
  1002. isSortOrderValid = (sortOrder: BaseSortOrder) => strings.SORT_DIRECTIONS.includes(sortOrder as any) || sortOrder === false;
  1003. }
  1004. export type BaseRowKeyType = string | number;
  1005. export interface BasePagination {
  1006. total?: number;
  1007. currentPage?: number;
  1008. pageSize?: number;
  1009. position?: ArrayElement<typeof strings.PAGINATION_POSITIONS>;
  1010. defaultCurrentPage?: number;
  1011. formatPageText?: any
  1012. }
  1013. export interface BaseHeadWidth {
  1014. width: number;
  1015. key: string
  1016. }
  1017. export interface BasePageData<RecordType> {
  1018. dataSource?: RecordType[];
  1019. groups?: Map<string, RecordType[]>;
  1020. pagination?: BasePagination;
  1021. disabledRowKeys?: BaseRowKeyType[];
  1022. allRowKeys?: BaseRowKeyType[];
  1023. queries?: BaseColumnProps<RecordType>[]
  1024. }
  1025. export type GetCheckboxProps<RecordType> = (record?: RecordType) => BaseCheckboxProps;
  1026. export type BaseGroupBy<RecordType> = string | number | BaseGroupByFn<RecordType>;
  1027. export type BaseGroupByFn<RecordType> = (record?: RecordType) => string | number;
  1028. export interface BaseSorterInfo<RecordType> {
  1029. [x: string]: any;
  1030. dataIndex?: string;
  1031. sortOrder?: BaseSortOrder;
  1032. sorter?: BaseSorter<RecordType>
  1033. }
  1034. export type BaseSortOrder = boolean | ArrayElement<typeof strings.SORT_DIRECTIONS>;
  1035. export type BaseSorter<RecordType> = boolean | ((a?: RecordType, b?: RecordType) => number);
  1036. export interface BaseChangeInfoFilter<RecordType> {
  1037. dataIndex?: string;
  1038. value?: any;
  1039. text?: any;
  1040. filters?: BaseFilter[];
  1041. onFilter?: (filteredValue?: any, record?: RecordType) => boolean;
  1042. filteredValue?: any[];
  1043. defaultFilteredValue?: any[];
  1044. children?: BaseFilter[];
  1045. filterChildrenRecord?: boolean
  1046. }
  1047. export interface BaseFilter {
  1048. value?: any;
  1049. text?: any;
  1050. children?: BaseFilter[]
  1051. }
  1052. export type BaseFixed = ArrayElement<typeof strings.FIXED_SET>;
  1053. export type BaseAlign = ArrayElement<typeof strings.ALIGNS>;
  1054. export type BaseOnCell<RecordType> = (record?: RecordType, rowIndex?: number) => BaseOnCellReturnObject;
  1055. export interface BaseOnCellReturnObject {
  1056. [x: string]: any;
  1057. style?: Record<string, any>;
  1058. className?: string;
  1059. onClick?: (e: any) => void
  1060. }
  1061. export type BaseOnFilter<RecordType> = (filteredValue?: any, record?: RecordType) => boolean;
  1062. export type BaseOnFilterDropdownVisibleChange = (visible?: boolean) => void;
  1063. export type BaseOnHeaderCell<RecordType> = (record?: RecordType, columnIndex?: number) => BaseOnHeaderCellReturnObject;
  1064. export interface BaseOnHeaderCellReturnObject {
  1065. [x: string]: any;
  1066. style?: Record<string, any>;
  1067. className?: string;
  1068. onClick?: (e: any) => void
  1069. }
  1070. export interface BaseChangeInfoSorter<RecordType> {
  1071. [x: string]: any;
  1072. dataIndex: string;
  1073. sortOrder: BaseSortOrder;
  1074. sorter: BaseSorter<RecordType>
  1075. }
  1076. export type BaseIncludeGroupRecord<RecordType> = RecordType | { groupKey: string };
  1077. export default TableFoundation;