foundation.ts 48 KB

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