Dashboard.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 { withCalls } from '@polkadot/react-api/hoc';
  6. import { Option } from '@polkadot/types';
  7. import { BlockNumber, Balance } from '@polkadot/types/interfaces';
  8. import { Label, Icon } from 'semantic-ui-react';
  9. import { formatNumber, formatBalance } from '@polkadot/util';
  10. import Section from '@polkadot/joy-utils/react/components/Section';
  11. import { queryToProp } from '@polkadot/joy-utils/functions/misc';
  12. import { ElectionStage, Seat } from '@joystream/types/council';
  13. import translate from './translate';
  14. import { RouteProps } from 'react-router-dom';
  15. type Props = RouteProps & ApiProps & I18nProps & {
  16. bestNumber?: BN;
  17. activeCouncil?: Seat[];
  18. termEndsAt?: BlockNumber;
  19. autoStart?: boolean;
  20. newTermDuration?: BN;
  21. candidacyLimit?: BN;
  22. councilSize?: BN;
  23. minCouncilStake?: Balance;
  24. minVotingStake?: Balance;
  25. announcingPeriod?: BlockNumber;
  26. votingPeriod?: BlockNumber;
  27. revealingPeriod?: BlockNumber;
  28. round?: BN;
  29. stage?: Option<ElectionStage>;
  30. };
  31. type State = Record<any, never>;
  32. class Dashboard extends React.PureComponent<Props, State> {
  33. state: State = {};
  34. renderCouncil () {
  35. const p = this.props;
  36. const { activeCouncil = [] } = p;
  37. const title = `Council ${activeCouncil.length > 0 ? '' : '(not elected)'}`;
  38. return <Section title={title}>
  39. <Label.Group color='grey' size='large'>
  40. <Label>
  41. Council members
  42. <Label.Detail>{activeCouncil.length}</Label.Detail>
  43. </Label>
  44. <Label>
  45. <Icon name='flag checkered'/>
  46. Term ends at block #
  47. <Label.Detail>{formatNumber(p.termEndsAt)}</Label.Detail>
  48. </Label>
  49. </Label.Group>
  50. </Section>;
  51. }
  52. renderElection () {
  53. const { bestNumber, round, stage } = this.props;
  54. let stageName: string | undefined;
  55. let stageEndsAt: BlockNumber | undefined;
  56. if (stage && stage.isSome) {
  57. const stageValue = stage.value as ElectionStage;
  58. stageEndsAt = stageValue.value as BlockNumber; // contained value
  59. stageName = stageValue.type; // name of Enum variant
  60. }
  61. let leftBlocks: BN | undefined;
  62. if (stageEndsAt && bestNumber) {
  63. leftBlocks = stageEndsAt.sub(bestNumber);
  64. }
  65. const isRunning: boolean = stage !== undefined && stage.isSome;
  66. const stateClass = `JoyElection--${isRunning ? '' : 'Not'}Running`;
  67. const stateText = `is ${isRunning ? '' : 'not'} running`;
  68. const title = <>Election (<span className={stateClass}>{stateText}</span>)</>;
  69. return <Section title={title}>
  70. <Label.Group color='grey' size='large'>
  71. <Label>
  72. <Icon name='target'/>
  73. Election round #
  74. <Label.Detail>{formatNumber(round)}</Label.Detail>
  75. </Label>
  76. {isRunning && <>
  77. <Label>
  78. Stage
  79. <Label.Detail>{stageName}</Label.Detail>
  80. </Label>
  81. <Label>
  82. Blocks left
  83. <Label.Detail>{formatNumber(leftBlocks)}</Label.Detail>
  84. </Label>
  85. <Label>
  86. <Icon name='flag checkered'/>
  87. Stage ends at block #
  88. <Label.Detail>{formatNumber(stageEndsAt)}</Label.Detail>
  89. </Label>
  90. </>}
  91. </Label.Group>
  92. </Section>;
  93. }
  94. renderConfig () {
  95. const p = this.props;
  96. const isAutoStart = (p.autoStart || false).valueOf();
  97. return <Section title='Configuration'>
  98. <Label.Group color='grey' size='large'>
  99. <Label>
  100. Auto-start elections
  101. <Label.Detail>{isAutoStart ? 'Yes' : 'No'}</Label.Detail>
  102. </Label>
  103. <Label>
  104. New term duration
  105. <Label.Detail>{formatNumber(p.newTermDuration)}</Label.Detail>
  106. </Label>
  107. <Label>
  108. Candidacy limit
  109. <Label.Detail>{formatNumber(p.candidacyLimit)}</Label.Detail>
  110. </Label>
  111. <Label>
  112. Council size
  113. <Label.Detail>{formatNumber(p.councilSize)}</Label.Detail>
  114. </Label>
  115. <Label>
  116. Min. council stake
  117. <Label.Detail>{formatBalance(p.minCouncilStake)}</Label.Detail>
  118. </Label>
  119. <Label>
  120. Min. voting stake
  121. <Label.Detail>{formatBalance(p.minVotingStake)}</Label.Detail>
  122. </Label>
  123. </Label.Group>
  124. <Label.Group color='grey' size='large'>
  125. <Label>
  126. Announcing period
  127. <Label.Detail>{formatNumber(p.announcingPeriod)} blocks</Label.Detail>
  128. </Label>
  129. <Label>
  130. Voting period
  131. <Label.Detail>{formatNumber(p.votingPeriod)} blocks</Label.Detail>
  132. </Label>
  133. <Label>
  134. Revealing period
  135. <Label.Detail>{formatNumber(p.revealingPeriod)} blocks</Label.Detail>
  136. </Label>
  137. </Label.Group>
  138. </Section>;
  139. }
  140. render () {
  141. return (
  142. <div className='JoySections'>
  143. {this.renderCouncil()}
  144. {this.renderElection()}
  145. {this.renderConfig()}
  146. </div>
  147. );
  148. }
  149. }
  150. // inject the actual API calls automatically into props
  151. export default translate(
  152. withCalls<Props>(
  153. queryToProp('derive.chain.bestNumber'),
  154. queryToProp('query.council.activeCouncil'),
  155. queryToProp('query.council.termEndsAt'),
  156. queryToProp('query.councilElection.autoStart'),
  157. queryToProp('query.councilElection.newTermDuration'),
  158. queryToProp('query.councilElection.candidacyLimit'),
  159. queryToProp('query.councilElection.councilSize'),
  160. queryToProp('query.councilElection.minCouncilStake'),
  161. queryToProp('query.councilElection.minVotingStake'),
  162. queryToProp('query.councilElection.announcingPeriod'),
  163. queryToProp('query.councilElection.votingPeriod'),
  164. queryToProp('query.councilElection.revealingPeriod'),
  165. queryToProp('query.councilElection.stage'),
  166. queryToProp('query.councilElection.round')
  167. )(Dashboard)
  168. );