pagination.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import {Component} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {Query} from 'history';
  5. import PropTypes from 'prop-types';
  6. import Button from 'app/components/button';
  7. import ButtonBar from 'app/components/buttonBar';
  8. import {IconChevron} from 'app/icons';
  9. import {t} from 'app/locale';
  10. import {callIfFunction} from 'app/utils/callIfFunction';
  11. import parseLinkHeader from 'app/utils/parseLinkHeader';
  12. const defaultProps: DefaultProps = {
  13. size: 'small',
  14. onCursor: (cursor: string, path: string, query: Query, _direction: number) => {
  15. browserHistory.push({
  16. pathname: path,
  17. query: {...query, cursor},
  18. });
  19. },
  20. };
  21. type DefaultProps = {
  22. size?: 'zero' | 'xsmall' | 'small';
  23. onCursor?: (cursor: string, path: string, query: Query, _direction: number) => void;
  24. };
  25. type Props = DefaultProps & {
  26. className?: string;
  27. pageLinks: string | null | undefined;
  28. to?: string;
  29. };
  30. class Pagination extends Component<Props> {
  31. static contextTypes = {
  32. location: PropTypes.object,
  33. };
  34. static defaultProps = defaultProps;
  35. render() {
  36. const {className, onCursor, pageLinks, size} = this.props;
  37. if (!pageLinks) {
  38. return null;
  39. }
  40. const location = this.context.location;
  41. const path = this.props.to || location.pathname;
  42. const query = location.query;
  43. const links = parseLinkHeader(pageLinks);
  44. const previousDisabled = links.previous.results === false;
  45. const nextDisabled = links.next.results === false;
  46. return (
  47. <div className={className}>
  48. <ButtonBar merged>
  49. <Button
  50. icon={<IconChevron direction="left" size="sm" />}
  51. aria-label={t('Previous')}
  52. size={size}
  53. disabled={previousDisabled}
  54. onClick={() => {
  55. callIfFunction(onCursor, links.previous.cursor, path, query, -1);
  56. }}
  57. />
  58. <Button
  59. icon={<IconChevron direction="right" size="sm" />}
  60. aria-label={t('Next')}
  61. size={size}
  62. disabled={nextDisabled}
  63. onClick={() => {
  64. callIfFunction(onCursor, links.next.cursor, path, query, 1);
  65. }}
  66. />
  67. </ButtonBar>
  68. </div>
  69. );
  70. }
  71. }
  72. export default styled(Pagination)`
  73. display: flex;
  74. align-items: center;
  75. justify-content: flex-end;
  76. margin: 20px 0 0 0;
  77. `;