Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.27 KB | None | 0 0
  1. import React, { useState, useEffect, useRef } from "react";
  2. //import makeData from "../makeData";
  3. import { useTableState } from "react-table";
  4. import Table from "../TransactionPanelTable";
  5.  
  6. // Simulate a server
  7. const getServerData = async ({ filters, sortBy, pageSize, pageIndex }) => {
  8. await new Promise(resolve => setTimeout(resolve, 500));
  9.  
  10. // Ideally, you would pass this info to the server, but we'll do it here for convenience
  11. const filtersArr = Object.entries(filters);
  12.  
  13. // Get our base data
  14. let rows = [];
  15.  
  16. rows.push({
  17. transaction_seq: 5418862,
  18. record_count: 300,
  19. user_id: "test",
  20. updated_at: "09-MAY-19 10.01.45.371373000 PM",
  21. duration: 5.7
  22. });
  23.  
  24. // Apply Filters
  25. if (filtersArr.length) {
  26. rows = rows.filter(row =>
  27. filtersArr.every(([key, value]) => row[key].includes(value))
  28. );
  29. }
  30.  
  31. // Apply Sorting
  32. if (sortBy.length) {
  33. const [{ id, desc }] = sortBy;
  34. rows = [...rows].sort(
  35. (a, b) => (a[id] > b[id] ? 1 : a[id] === b[id] ? 0 : -1) * (desc ? -1 : 1)
  36. );
  37. }
  38.  
  39. // Get page counts
  40. const pageCount = Math.ceil(rows.length / pageSize);
  41. const rowStart = pageSize * pageIndex;
  42. const rowEnd = rowStart + pageSize;
  43.  
  44. // Get the current page
  45. rows = rows.slice(rowStart, rowEnd);
  46.  
  47. return {
  48. rows,
  49. pageCount
  50. };
  51. };
  52.  
  53. export default function({ infinite }) {
  54. const [checkedMap, setCheckedMap] = useState(new Map());
  55. const [data, setData] = useState([]);
  56. const [loading, setLoading] = useState(false);
  57. const currentRequestRef = useRef();
  58.  
  59. const fetchData = async () => {
  60. setLoading(true);
  61.  
  62. // We can use a ref to disregard any outdated requests
  63. const id = Date.now();
  64. currentRequestRef.current = id;
  65.  
  66. // Call our server for the data
  67. const { rows, pageCount } = await getServerData({
  68. filters,
  69. sortBy,
  70. pageSize,
  71. pageIndex
  72. });
  73.  
  74. let newMap = new Map();
  75. rows.forEach(row => newMap.set(row, false));
  76. setCheckedMap(newMap);
  77.  
  78. // If this is an outdated request, disregard the results
  79. if (currentRequestRef.current !== id) {
  80. return;
  81. }
  82.  
  83. // Set the data and pageCount
  84. setData(rows);
  85. setState(old => ({
  86. ...old,
  87. pageCount
  88. }));
  89.  
  90. setLoading(false);
  91. };
  92.  
  93. const handleCheckedChange = row => {
  94. let modifiedMap = checkedMap;
  95. modifiedMap.set(row, !checkedMap.get(row));
  96. setCheckedMap(modifiedMap);
  97. console.log(checkedMap);
  98. };
  99.  
  100. const columns = [
  101. {
  102. Header: "Transaction(s)",
  103. className: "left",
  104. columns: [
  105. {
  106. id: "checkbox",
  107. accessor: "checkbox",
  108. key: "transaction_seq",
  109. Cell: ({ original }) => {
  110. return (
  111. <input
  112. type="checkbox"
  113. className="checkbox"
  114. checked={checkedMap.get(original)} //again, use a key
  115. onChange={() => handleCheckedChange(original)}
  116. />
  117. );
  118. },
  119.  
  120. sortable: false,
  121. width: 45
  122. },
  123. {
  124. Header: "Transaction Sequence",
  125. accessor: "transaction_seq",
  126. id: "transaction_seq",
  127. minWidth: 200,
  128. maxWidth: 300
  129. },
  130. {
  131. Header: "Record count",
  132. accessor: "record_count",
  133. width: 300
  134. },
  135. {
  136. Header: "User Id",
  137. accessor: "user_id",
  138. width: 300
  139. },
  140. {
  141. Header: "Updated At",
  142. accessor: "updated_at",
  143. width: 400
  144. },
  145. {
  146. Header: "Duration",
  147. accessor: "duration",
  148. width: 400
  149. }
  150. ]
  151. }
  152. ];
  153.  
  154. // Make a new controllable table state instance
  155. const state = useTableState({ pageCount: 0 });
  156.  
  157. const [{ sortBy, filters, pageIndex, pageSize }, setState] = state;
  158.  
  159. // When sorting, filters, pageSize, or pageIndex change, fetch new data
  160. useEffect(() => {
  161. fetchData();
  162. }, [sortBy, filters, pageIndex, pageSize]);
  163.  
  164. return (
  165. <React.Fragment>
  166. <Table
  167. {...{
  168. data,
  169. checkedMap,
  170. columns,
  171. infinite,
  172. state, // Pass the state to the table
  173. loading,
  174. manualSorting: true, // Manual sorting
  175. manualFilters: true, // Manual filters
  176. manualPagination: true, // Manual pagination
  177. disableMultiSort: true, // Disable multi-sort
  178. disableGrouping: true, // Disable grouping
  179. debug: true
  180. }}
  181. />
  182. </React.Fragment>
  183. );
  184. }
  185.  
  186. import styled, { css } from "styled-components";
  187. import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
  188. import { FixedSizeList as List } from "react-window";
  189. import {
  190. useTable,
  191. useColumns,
  192. useRows,
  193. useFilters,
  194. useSortBy,
  195. useExpanded,
  196. usePagination,
  197. useFlexLayout
  198. } from "react-table";
  199.  
  200. const Table = styled.div`
  201. display: block;
  202. border-radius: 5px;
  203. border: solid 1px #ddd;
  204. overflow-x: auto;
  205. `;
  206.  
  207. const RowBase = styled.div`
  208. display: flex;
  209. border-bottom: solid 1px #ddd;
  210.  
  211. :last-child {
  212. border-bottom: 0;
  213. }
  214. `;
  215.  
  216. const Row = styled(RowBase)`
  217. ${props =>
  218. props.even &&
  219. css`
  220. background: rgba(42, 117, 146, 0.12);
  221. `}
  222. `;
  223.  
  224. const HeaderRow = styled(RowBase)`
  225. background: rgba(42, 117, 146, 1);
  226. border-bottom: solid 1px rgba(0, 0, 0, 0.2);
  227. color: white;
  228. `;
  229.  
  230. const Pagination = styled(RowBase)`
  231. background: rgba(42, 117, 146, 1);
  232. color: white;
  233. `;
  234.  
  235. const Cell = styled.div`
  236. border-right: solid 1px rgba(0, 0, 0, 0.1);
  237. padding: 0.6rem;
  238.  
  239. :last-child {
  240. border-right: 0;
  241. }
  242. `;
  243.  
  244. const Header = styled(Cell)`
  245. font-weight: bold;
  246.  
  247. ${props => {
  248. const width = (props.sortedIndex + 1) * 5;
  249. return (
  250. props.sorted &&
  251. (props.sortedDesc
  252. ? css`
  253. box-shadow: inset 0 ${width}px hsla(0, 100%, 40%);
  254. `
  255. : css`
  256. box-shadow: inset 0 -${width}px hsl(55, 100%, 50%);
  257. `)
  258. );
  259. }};
  260. `;
  261.  
  262. const Button = styled.button`
  263. font-size: 1rem;
  264. padding: 0.5rem 0.7rem;
  265. background: white;
  266. border-radius: 5px;
  267. cursor: pointer;
  268.  
  269. :disabled {
  270. opacity: 0.3;
  271. }
  272. `;
  273.  
  274. const Select = styled.select`
  275. appearance: none;
  276. background: white;
  277. border: 0;
  278. margin: 0;
  279. color: black;
  280. font-size: 1rem;
  281. border-radius: 5px;
  282. padding: 0.5rem 0.7rem;
  283. border: 0;
  284. cursor: pointer;
  285. `;
  286.  
  287. const Input = styled.input`
  288. font-size: 1rem;
  289. padding: 0.5rem 0.7rem;
  290. background: white;
  291. border-radius: 5px;
  292. border: 1px solid rgba(0, 0, 0, 0.2);
  293. max-width: 100%;
  294. `;
  295.  
  296. const useInfiniteScroll = ({
  297. enabled,
  298. sortBy,
  299. filters,
  300. pageIndex,
  301. pageSize
  302. }) => {
  303. const listRef = useRef();
  304. const [scrollToIndex, setScrollToIndex] = useState(0);
  305. const [rowHeight, setRowHeight] = useState(40);
  306. const [height, setHeight] = useState(500);
  307. const [overscan, setOverscan] = useState(25);
  308.  
  309. useEffect(() => {
  310. if (!enabled) {
  311. return;
  312. }
  313. if (listRef.current) {
  314. listRef.current.scrollToItem(scrollToIndex, "start");
  315. }
  316. }, [scrollToIndex]);
  317.  
  318. useEffect(() => {}, []);
  319.  
  320. useLayoutEffect(() => {
  321. if (!enabled) {
  322. return;
  323. }
  324. if (listRef.current) {
  325. listRef.current.scrollToItem(0, "start");
  326. }
  327. }, [sortBy, filters]);
  328.  
  329. return {
  330. listRef,
  331. scrollToIndex,
  332. setScrollToIndex,
  333. rowHeight,
  334. setRowHeight,
  335. height,
  336. setHeight,
  337. overscan,
  338. setOverscan
  339. };
  340. };
  341.  
  342. export default function MyTable({ loading, infinite, ...props }) {
  343. const instance = useTable(
  344. {
  345. ...props
  346. },
  347. useColumns,
  348. useRows,
  349. useFilters,
  350. useSortBy,
  351. useExpanded,
  352. usePagination,
  353. useFlexLayout
  354. );
  355.  
  356. const {
  357. getTableProps,
  358. headerGroups,
  359. rows,
  360. getRowProps,
  361. pageOptions,
  362. page,
  363. state: [{ pageIndex, pageSize, sortBy, filters }],
  364. gotoPage,
  365. prepareRow,
  366. previousPage,
  367. nextPage,
  368. setPageSize,
  369. canPreviousPage,
  370. canNextPage
  371. } = instance;
  372.  
  373. const { listRef, rowHeight, height, overscan } = useInfiniteScroll({
  374. enabled: infinite,
  375. sortBy,
  376. filters,
  377. pageIndex,
  378. pageSize
  379. });
  380.  
  381. let tableBody;
  382.  
  383. const renderRow = (row, index, style = {}) => {
  384. if (!row) {
  385. return (
  386. <Row {...{ style, even: index % 2 }}>
  387. <Cell>Loading more...</Cell>
  388. </Row>
  389. );
  390. }
  391. prepareRow(row);
  392. return (
  393. <Row {...row.getRowProps({ style, even: index % 2 })}>
  394. {row.cells.map(cell => {
  395. const isPivot = row.groupByID === cell.column.id;
  396. const showAggregate = row.subRows && !isPivot;
  397. return (
  398. <Cell {...cell.getCellProps()}>
  399. {showAggregate ? (
  400. cell.column.aggregate ? (
  401. cell.render("Aggregated")
  402. ) : null
  403. ) : (
  404. <span>
  405. {isPivot ? (
  406. <span
  407. style={{
  408. cursor: "pointer",
  409. paddingLeft: `${row.depth * 2}rem`,
  410. paddingRight: "1rem",
  411. whiteSpace: "nowrap"
  412. }}
  413. onClick={() => row.toggleExpanded()}
  414. />
  415. ) : null}
  416. {cell.render("Cell")}
  417. {isPivot ? <span> ({row.subRows.length})</span> : null}
  418.  
  419. <checkbox />
  420. </span>
  421. )}
  422. </Cell>
  423. );
  424. })}
  425. </Row>
  426. );
  427. };
  428.  
  429. if (infinite) {
  430. tableBody = (
  431. <List
  432. ref={listRef}
  433. height={height}
  434. itemCount={rows.length + 1}
  435. itemSize={rowHeight}
  436. overscanCount={overscan}
  437. scrollToAlignment="start"
  438. {...getRowProps()}
  439. >
  440. {({ index, style }) => {
  441. const row = rows[index];
  442. return renderRow(row, index, style);
  443. }}
  444. </List>
  445. );
  446. } else {
  447. tableBody =
  448. page && page.length ? page.map((row, i) => renderRow(row, i)) : null;
  449. }
  450.  
  451. let pagination;
  452.  
  453. pagination = pageOptions.length ? (
  454. <Pagination {...getRowProps()}>
  455. <Cell>
  456. <Button onClick={() => previousPage()} disabled={!canPreviousPage}>
  457. Previous
  458. </Button>{" "}
  459. <Button onClick={() => nextPage()} disabled={!canNextPage}>
  460. Next
  461. </Button>{" "}
  462. <span>
  463. Page{" "}
  464. <strong>
  465. {pageIndex + 1} of {pageOptions.length}
  466. </strong>{" "}
  467. </span>
  468. <span>
  469. | Go to page:{" "}
  470. <Input
  471. type="number"
  472. defaultValue={pageIndex + 1}
  473. onChange={e => {
  474. const page = e.target.value ? Number(e.target.value) - 1 : 0;
  475. gotoPage(page);
  476. }}
  477. style={{ width: "100px" }}
  478. />
  479. </span>{" "}
  480. <Select
  481. value={pageSize}
  482. onChange={e => {
  483. setPageSize(Number(e.target.value));
  484. }}
  485. >
  486. {[10, 20, 30, 40, 50].map(pageSize => (
  487. <option key={pageSize} value={pageSize}>
  488. Show {pageSize}
  489. </option>
  490. ))}
  491. </Select>{" "}
  492. <Button onClick={() => reprocessConfirmation()}>Reprocess</Button>
  493. </Cell>
  494. </Pagination>
  495. ) : null;
  496.  
  497. function reprocessConfirmation() {
  498. let confirmation = window.confirm("Do you want to reprocess transaction");
  499. if (confirmation === true) console.log("OK");
  500. else console.log("CANCEL");
  501. }
  502.  
  503. return (
  504. <React.Fragment>
  505. <Table {...getTableProps()}>
  506. {headerGroups.map(headerGroup => (
  507. <HeaderRow {...headerGroup.getRowProps()}>
  508. {headerGroup.headers.map(column => (
  509. <Header
  510. {...column.getHeaderProps()}
  511. sorted={column.sorted}
  512. sortedDesc={column.sortedDesc}
  513. sortedIndex={column.sortedIndex}
  514. >
  515. <div>
  516. <span {...column.getSortByToggleProps()}>
  517. {column.render("Header")}
  518. </span>{" "}
  519. </div>
  520. {column.canFilter ? <div>{column.render("Filter")}</div> : null}
  521. </Header>
  522. ))}
  523. </HeaderRow>
  524. ))}
  525. {tableBody}
  526. <Row {...getRowProps()}>
  527. {loading ? (
  528. <Cell>
  529. <strong>Loading...</strong>
  530. </Cell>
  531. ) : (
  532. <Cell>{rows.length} Total Records</Cell>
  533. )}
  534. </Row>
  535. {pagination}
  536. </Table>
  537. </React.Fragment>
  538. );
  539. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement