List.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import BN from 'bn.js';
  2. import React from 'react';
  3. import { ApiProps } from '@polkadot/react-api/types';
  4. import { I18nProps } from '@polkadot/react-components/types';
  5. import { Section } from '@polkadot/joy-utils/react/components';
  6. import translate from './translate';
  7. import Details from './Details';
  8. import { MemberId } from '@joystream/types/members';
  9. import { RouteComponentProps, Redirect } from 'react-router-dom';
  10. import { Pagination, Icon, PaginationProps } from 'semantic-ui-react';
  11. import styled from 'styled-components';
  12. import { withApi } from '@polkadot/react-api';
  13. const StyledPagination = styled(Pagination)`
  14. border-bottom: 1px solid #ddd !important;
  15. `;
  16. type Props = ApiProps & I18nProps & RouteComponentProps & {
  17. firstMemberId: BN;
  18. membersCreated: BN;
  19. match: { params: { page?: string } };
  20. };
  21. type State = Record<any, never>;
  22. const MEMBERS_PER_PAGE = 20;
  23. class Component extends React.PureComponent<Props, State> {
  24. state: State = {};
  25. onPageChange = (e: React.MouseEvent, data: PaginationProps) => {
  26. const { history } = this.props;
  27. history.push(`/members/list/${data.activePage || 1}`);
  28. }
  29. renderPagination (currentPage: number, pagesCount: number) {
  30. return (
  31. <StyledPagination
  32. pointing
  33. secondary
  34. activePage={ currentPage }
  35. ellipsisItem={{ content: <Icon name='ellipsis horizontal' />, icon: true }}
  36. firstItem={{ content: <Icon name='angle double left' />, icon: true }}
  37. lastItem={{ content: <Icon name='angle double right' />, icon: true }}
  38. prevItem={{ content: <Icon name='angle left' />, icon: true }}
  39. nextItem={{ content: <Icon name='angle right' />, icon: true }}
  40. totalPages={ pagesCount }
  41. onPageChange={ this.onPageChange }
  42. />
  43. );
  44. }
  45. render () {
  46. const {
  47. firstMemberId,
  48. membersCreated,
  49. match: { params: { page } },
  50. api
  51. } = this.props;
  52. const membersCount = membersCreated.toNumber();
  53. const pagesCount = Math.ceil(membersCount / MEMBERS_PER_PAGE) || 1;
  54. const currentPage = Math.min(parseInt(page || '1'), pagesCount);
  55. if (currentPage.toString() !== page) {
  56. return <Redirect to={ `/members/list/${currentPage}` } />;
  57. }
  58. const ids: MemberId[] = [];
  59. if (membersCount > 0) {
  60. const firstId = firstMemberId.toNumber() + (currentPage - 1) * MEMBERS_PER_PAGE;
  61. const lastId = Math.min(firstId + MEMBERS_PER_PAGE, membersCount) - 1;
  62. for (let i = firstId; i <= lastId; i++) {
  63. ids.push(api.createType('MemberId', i));
  64. }
  65. }
  66. return (
  67. <Section
  68. title={`Members (${membersCount})`}
  69. pagination={ (pagesCount > 1 && this.renderPagination(currentPage, pagesCount)) || undefined }>
  70. {
  71. membersCount === 0
  72. ? <em>No registered members yet.</em>
  73. : (
  74. <div className='ui huge relaxed middle aligned divided list ProfilePreviews'>
  75. {ids.map((id, i) =>
  76. <Details {...this.props} key={i} memberId={id} preview />
  77. )}
  78. </div>
  79. )
  80. }
  81. </Section>
  82. );
  83. }
  84. }
  85. export default translate(withApi(Component));