diff --git a/packages/apps-routing/src/index.ts b/packages/apps-routing/src/index.ts index a76080dd98..9003f55026 100644 --- a/packages/apps-routing/src/index.ts +++ b/packages/apps-routing/src/index.ts @@ -17,6 +17,7 @@ import explorer from './explorer'; import extrinsics from './extrinsics'; import gilt from './gilt'; import js from './js'; +import membership from './membership'; import parachains from './parachains'; import poll from './poll'; import rpc from './rpc'; @@ -44,6 +45,7 @@ export default function create (t: TFunction): Routes { treasury(t), bounties(t), techcomm(t), + membership(t), parachains(t), gilt(t), assets(t), diff --git a/packages/apps-routing/src/membership.ts b/packages/apps-routing/src/membership.ts new file mode 100644 index 0000000000..977acce7fb --- /dev/null +++ b/packages/apps-routing/src/membership.ts @@ -0,0 +1,24 @@ +// Copyright 2017-2021 @polkadot/apps-routing authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { TFunction } from 'i18next'; +import type { Route } from './types'; + +import Component, { useCounter } from '@polkadot/app-membership'; + +export default function create (t: TFunction): Route { + return { + Component, + display: { + needsAccounts: true, + needsApi: [ + 'query.membership.members' + ] + }, + group: 'governance', + icon: 'people-carry', + name: 'membership', + text: t('nav.membership', 'Membership', { ns: 'apps-routing' }), + useCounter + }; +} diff --git a/packages/page-membership/.skip-build b/packages/page-membership/.skip-build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/page-membership/.skip-npm b/packages/page-membership/.skip-npm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/page-membership/LICENSE b/packages/page-membership/LICENSE new file mode 100644 index 0000000000..0d381b2e97 --- /dev/null +++ b/packages/page-membership/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/packages/page-membership/README.md b/packages/page-membership/README.md new file mode 100644 index 0000000000..42fd731d84 --- /dev/null +++ b/packages/page-membership/README.md @@ -0,0 +1 @@ +# @polkadot/app-council diff --git a/packages/page-membership/package.json b/packages/page-membership/package.json new file mode 100644 index 0000000000..a4b6449d60 --- /dev/null +++ b/packages/page-membership/package.json @@ -0,0 +1,11 @@ +{ + "name": "@polkadot/app-membership", + "private": true, + "version": "0.89.2-2", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.13.17", + "@polkadot/react-components": "^0.89.2-2", + "@polkadot/react-query": "^0.89.2-2" + } +} diff --git a/packages/page-membership/src/index.tsx b/packages/page-membership/src/index.tsx new file mode 100644 index 0000000000..a9b28cc6b8 --- /dev/null +++ b/packages/page-membership/src/index.tsx @@ -0,0 +1,25 @@ +// Copyright 2017-2021 @polkadot/app-tech-comm authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; + +import App from '@polkadot/app-tech-comm/App'; + +export { default as useCounter } from './useCounter'; + +interface Props { + basePath: string; + className?: string; +} + +function TechComm ({ basePath, className }: Props): React.ReactElement { + return ( + + ); +} + +export default React.memo(TechComm); diff --git a/packages/page-membership/src/useCounter.ts b/packages/page-membership/src/useCounter.ts new file mode 100644 index 0000000000..dfc9c167ad --- /dev/null +++ b/packages/page-membership/src/useCounter.ts @@ -0,0 +1,17 @@ +// Copyright 2017-2021 @polkadot/app-democracy authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Hash } from '@polkadot/types/interfaces'; + +import { useApi, useCall } from '@polkadot/react-hooks'; + +const transformCounter = { + transform: (proposals: Hash[]) => proposals.length +}; + +export default function useCounter (): number { + const { api, isApiReady } = useApi(); + const counter = useCall(isApiReady && api.query.membership?.proposals, undefined, transformCounter) || 0; + + return counter; +} diff --git a/packages/page-tech-comm/src/App.tsx b/packages/page-tech-comm/src/App.tsx new file mode 100644 index 0000000000..eca51b6e42 --- /dev/null +++ b/packages/page-tech-comm/src/App.tsx @@ -0,0 +1,83 @@ +// Copyright 2017-2021 @polkadot/app-tech-comm authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Option } from '@polkadot/types'; +import type { AccountId, Hash } from '@polkadot/types/interfaces'; + +import React, { useMemo } from 'react'; +import { Route, Switch } from 'react-router'; + +import { Tabs } from '@polkadot/react-components'; +import { useApi, useCall, useMembers } from '@polkadot/react-hooks'; +import { isFunction } from '@polkadot/util'; + +import Overview from './Overview'; +import Proposals from './Proposals'; +import { useTranslation } from './translate'; + +interface Props { + basePath: string; + className?: string; + type: 'membership' | 'technicalCommittee'; +} + +const transformPrime = { + transform: (result: Option): AccountId | null => result.unwrapOr(null) +}; + +function TechCommApp ({ basePath, className, type }: Props): React.ReactElement { + const { t } = useTranslation(); + const { api } = useApi(); + const { isMember, members } = useMembers(type); + const prime = useCall(api.query[type].prime, undefined, transformPrime) || null; + const proposals = useCall(api.query[type].proposals); + + const items = useMemo(() => [ + { + isRoot: true, + name: 'overview', + text: t('Overview') + }, + { + name: 'proposals', + text: t('Proposals ({{count}})', { replace: { count: (proposals && proposals.length) || 0 } }) + } + ], [proposals, t]); + + const hidden = useMemo( + () => isFunction(api.query[type].proposals) ? [] : ['proposals'], + [api, type] + ); + + return ( +
+
+ ); +} + +export default React.memo(TechCommApp); diff --git a/packages/page-tech-comm/src/Overview/Summary.tsx b/packages/page-tech-comm/src/Overview/Summary.tsx index 0d2c316dda..cafd1c328f 100644 --- a/packages/page-tech-comm/src/Overview/Summary.tsx +++ b/packages/page-tech-comm/src/Overview/Summary.tsx @@ -8,28 +8,30 @@ import React from 'react'; import { CardSummary, SummaryBox } from '@polkadot/react-components'; import { useApi, useCall } from '@polkadot/react-hooks'; -import { formatNumber } from '@polkadot/util'; +import { formatNumber, isFunction } from '@polkadot/util'; import { useTranslation } from '../translate'; -function Summary ({ className = '', members, proposals }: Props): React.ReactElement { +function Summary ({ className = '', members, proposals, type }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); - const proposalCount = useCall(api.query.technicalCommittee.proposalCount); + const proposalCount = useCall(api.query[type].proposalCount); return ( ('members')}> {formatNumber(members.length)} -
- ('proposals')}> - {formatNumber(proposals?.length)} - - ('total')}> - {formatNumber(proposalCount)} - -
+ {isFunction(api.query[type].proposalCount) && ( +
+ ('proposals')}> + {formatNumber(proposals?.length)} + + ('total')}> + {formatNumber(proposalCount)} + +
+ )}
); } diff --git a/packages/page-tech-comm/src/Overview/index.tsx b/packages/page-tech-comm/src/Overview/index.tsx index 80709af33e..7bc47e42f1 100644 --- a/packages/page-tech-comm/src/Overview/index.tsx +++ b/packages/page-tech-comm/src/Overview/index.tsx @@ -8,13 +8,14 @@ import React from 'react'; import Members from './Members'; import Summary from './Summary'; -function Overview ({ className = '', isMember, members, prime, proposals }: Props): React.ReactElement { +function Overview ({ className = '', isMember, members, prime, proposals, type }: Props): React.ReactElement { return (
| null { +function Close ({ hasFailed, hash, idNumber, members, proposal, type }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const [isOpen, toggleOpen] = useToggle(); const [accountId, setAccountId] = useState(null); const [proposalWeight, proposalLength] = useWeight(proposal); - if (!api.tx.technicalCommittee.close) { + if (!api.tx[type].close) { return null; } @@ -58,13 +59,13 @@ function Close ({ hasFailed, hash, idNumber, members, proposal }: Props): React. accountId={accountId} onStart={toggleOpen} params={ - api.tx.technicalCommittee.close.meta.args.length === 4 + api.tx[type].close.meta.args.length === 4 ? hasFailed ? [hash, idNumber, 0, 0] : [hash, idNumber, proposalWeight, proposalLength] : [hash, idNumber] } - tx={api.tx.technicalCommittee.closeOperational || api.tx.technicalCommittee.close} + tx={api.tx[type].closeOperational || api.tx[type].close} /> diff --git a/packages/page-tech-comm/src/Proposals/Proposal.tsx b/packages/page-tech-comm/src/Proposals/Proposal.tsx index 0140efe0f0..335256e42e 100644 --- a/packages/page-tech-comm/src/Proposals/Proposal.tsx +++ b/packages/page-tech-comm/src/Proposals/Proposal.tsx @@ -22,6 +22,7 @@ interface Props { isMember: boolean; members: string[]; prime?: AccountId | null; + type: 'membership' | 'technicalCommittee'; } const transformProposal = { @@ -32,13 +33,13 @@ const transformVotes = { transform: (optVotes: Option) => optVotes.unwrapOr(null) }; -function Proposal ({ className = '', imageHash, members, prime }: Props): React.ReactElement | null { +function Proposal ({ className = '', imageHash, members, prime, type }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const { allAccounts } = useAccounts(); - const proposal = useCall(api.query.technicalCommittee.proposalOf, [imageHash], transformProposal); - const votes = useCall(api.query.technicalCommittee.voting, [imageHash], transformVotes); - const { hasFailed, isCloseable, isVoteable, remainingBlocks } = useVotingStatus(votes, members.length, 'technicalCommittee'); + const proposal = useCall(api.query[type].proposalOf, [imageHash], transformProposal); + const votes = useCall(api.query[type].voting, [imageHash], transformVotes); + const { hasFailed, isCloseable, isVoteable, remainingBlocks } = useVotingStatus(votes, members.length, type); const [proposalWeight, proposalLength] = useWeight(proposal); const [councilId, isMultiMembers] = useMemo( @@ -99,6 +100,7 @@ function Proposal ({ className = '', imageHash, members, prime }: Props): React. members={members} prime={prime} proposalId={index} + type={type} /> )} {isCloseable && ( @@ -110,6 +112,7 @@ function Proposal ({ className = '', imageHash, members, prime }: Props): React. idNumber={index} members={members} proposal={proposal} + type={type} /> ) : ( @@ -118,13 +121,13 @@ function Proposal ({ className = '', imageHash, members, prime }: Props): React. icon='times' label={t('Close')} params={ - api.tx.technicalCommittee.close?.meta.args.length === 4 + api.tx[type].close?.meta.args.length === 4 ? hasFailed ? [imageHash, index, 0, 0] : [imageHash, index, proposalWeight, proposalLength] : [imageHash, index] } - tx={api.tx.technicalCommittee.closeOperational || api.tx.technicalCommittee.close} + tx={api.tx[type].closeOperational || api.tx[type].close} /> ) )} diff --git a/packages/page-tech-comm/src/Proposals/Propose.tsx b/packages/page-tech-comm/src/Proposals/Propose.tsx index 435a914dfb..74b5eb1e14 100644 --- a/packages/page-tech-comm/src/Proposals/Propose.tsx +++ b/packages/page-tech-comm/src/Proposals/Propose.tsx @@ -14,6 +14,7 @@ import { useTranslation } from '../translate'; interface Props { isMember: boolean; members: string[]; + type: 'membership' | 'technicalCommittee'; } interface ProposalState { @@ -21,7 +22,7 @@ interface ProposalState { proposalLength: number; } -function Propose ({ isMember, members }: Props): React.ReactElement { +function Propose ({ isMember, members, type }: Props): React.ReactElement { const { t } = useTranslation(); const { api, apiDefaultTxSudo } = useApi(); const { isOpen, onClose, onOpen } = useModal(); @@ -87,11 +88,11 @@ function Propose ({ isMember, members }: Props): React.ReactElement { isDisabled={!hasThreshold || !proposal} onStart={onClose} params={ - api.tx.technicalCommittee.propose.meta.args.length === 3 + api.tx[type].propose.meta.args.length === 3 ? [threshold, proposal, proposalLength] : [threshold, proposal] } - tx={api.tx.technicalCommittee.propose} + tx={api.tx[type].propose} /> diff --git a/packages/page-tech-comm/src/Proposals/Voting.tsx b/packages/page-tech-comm/src/Proposals/Voting.tsx index d2e64b914e..dab28c91b6 100644 --- a/packages/page-tech-comm/src/Proposals/Voting.tsx +++ b/packages/page-tech-comm/src/Proposals/Voting.tsx @@ -16,9 +16,10 @@ interface Props { members: string[]; prime?: AccountId | null; proposalId: BN | number; + type: 'membership' | 'technicalCommittee'; } -function Voting ({ hash, members, prime, proposalId }: Props): React.ReactElement | null { +function Voting ({ hash, members, prime, proposalId, type }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const { hasAccounts } = useAccounts(); @@ -52,7 +53,7 @@ function Voting ({ hash, members, prime, proposalId }: Props): React.ReactElemen label={t('Vote Nay')} onStart={toggleVoting} params={[hash, proposalId, false]} - tx={api.tx.technicalCommittee.vote} + tx={api.tx[type].vote} /> ('Vote Aye')} onStart={toggleVoting} params={[hash, proposalId, true]} - tx={api.tx.technicalCommittee.vote} + tx={api.tx[type].vote} /> diff --git a/packages/page-tech-comm/src/Proposals/index.tsx b/packages/page-tech-comm/src/Proposals/index.tsx index 1b431d6c11..2a94e12a1d 100644 --- a/packages/page-tech-comm/src/Proposals/index.tsx +++ b/packages/page-tech-comm/src/Proposals/index.tsx @@ -12,7 +12,7 @@ import { useTranslation } from '../translate'; import Proposal from './Proposal'; import Propose from './Propose'; -function Proposals ({ className = '', isMember, members, prime, proposals }: Props): React.ReactElement { +function Proposals ({ className = '', isMember, members, prime, proposals, type }: Props): React.ReactElement { const { t } = useTranslation(); const headerRef = useRef([ @@ -30,6 +30,7 @@ function Proposals ({ className = '', isMember, members, prime, proposals }: Pro ))}
diff --git a/packages/page-tech-comm/src/index.tsx b/packages/page-tech-comm/src/index.tsx index d4e9418495..68632e2a19 100644 --- a/packages/page-tech-comm/src/index.tsx +++ b/packages/page-tech-comm/src/index.tsx @@ -1,18 +1,9 @@ // Copyright 2017-2021 @polkadot/app-tech-comm authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { Option } from '@polkadot/types'; -import type { AccountId, Hash } from '@polkadot/types/interfaces'; +import React from 'react'; -import React, { useMemo } from 'react'; -import { Route, Switch } from 'react-router'; - -import { Tabs } from '@polkadot/react-components'; -import { useApi, useCall, useMembers } from '@polkadot/react-hooks'; - -import Overview from './Overview'; -import Proposals from './Proposals'; -import { useTranslation } from './translate'; +import App from './App'; export { default as useCounter } from './useCounter'; @@ -21,55 +12,14 @@ interface Props { className?: string; } -const transformPrime = { - transform: (result: Option): AccountId | null => result.unwrapOr(null) -}; - -function TechCommApp ({ basePath, className }: Props): React.ReactElement { - const { t } = useTranslation(); - const { api } = useApi(); - const { isMember, members } = useMembers('technicalCommittee'); - const prime = useCall(api.query.technicalCommittee.prime, undefined, transformPrime) || null; - const proposals = useCall(api.query.technicalCommittee.proposals); - - const items = useMemo(() => [ - { - isRoot: true, - name: 'overview', - text: t('Overview') - }, - { - name: 'proposals', - text: t('Proposals ({{count}})', { replace: { count: (proposals && proposals.length) || 0 } }) - } - ], [proposals, t]); - +function TechComm ({ basePath, className }: Props): React.ReactElement { return ( -
- - - - - - - - - -
+ ); } -export default React.memo(TechCommApp); +export default React.memo(TechComm); diff --git a/packages/page-tech-comm/src/types.ts b/packages/page-tech-comm/src/types.ts index 4d491bcb7a..2bcaae82ed 100644 --- a/packages/page-tech-comm/src/types.ts +++ b/packages/page-tech-comm/src/types.ts @@ -9,4 +9,5 @@ export interface ComponentProps { prime?: AccountId | null; proposals?: Hash[]; members: string[]; + type: 'membership' | 'technicalCommittee'; } diff --git a/packages/react-hooks/src/useMembers.ts b/packages/react-hooks/src/useMembers.ts index 78ed9d9727..9709564203 100644 --- a/packages/react-hooks/src/useMembers.ts +++ b/packages/react-hooks/src/useMembers.ts @@ -17,7 +17,7 @@ const transformMembers = { accounts.map((accountId) => accountId.toString()) }; -export function useMembers (collective: 'council' | 'technicalCommittee' = 'council'): Result { +export function useMembers (collective: 'council' | 'membership' | 'technicalCommittee' = 'council'): Result { const { api } = useApi(); const { allAccounts, hasAccounts } = useAccounts(); const retrieved = useCall(hasAccounts && api.query[collective]?.members, undefined, transformMembers); diff --git a/packages/react-hooks/src/useVotingStatus.ts b/packages/react-hooks/src/useVotingStatus.ts index f5f825d95c..cf20b24a0c 100644 --- a/packages/react-hooks/src/useVotingStatus.ts +++ b/packages/react-hooks/src/useVotingStatus.ts @@ -22,7 +22,7 @@ interface State { const DEFAULT_STATUS = { hasFailed: false, hasPassed: false, isCloseable: false, isVoteable: false, remainingBlocks: null }; -function getStatus (api: ApiPromise, bestNumber: BlockNumber, votes: Votes, numMembers: number, section: 'council' | 'technicalCommittee'): State { +function getStatus (api: ApiPromise, bestNumber: BlockNumber, votes: Votes, numMembers: number, section: 'council' | 'membership' | 'technicalCommittee'): State { if (!votes.end) { return { hasFailed: false, @@ -52,7 +52,7 @@ function getStatus (api: ApiPromise, bestNumber: BlockNumber, votes: Votes, numM }; } -export function useVotingStatus (votes: Votes | null | undefined, numMembers: number, section: 'council' | 'technicalCommittee'): State { +export function useVotingStatus (votes: Votes | null | undefined, numMembers: number, section: 'council' | 'membership' | 'technicalCommittee'): State { const { api } = useApi(); const bestNumber = useBestNumber(); diff --git a/tsconfig.json b/tsconfig.json index f517ecf0fc..26f1bbe025 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -42,6 +42,8 @@ "@polkadot/app-i18n/*": [ "packages/page-i18n/src/*" ], "@polkadot/app-js": [ "packages/page-js/src" ], "@polkadot/app-js/*": [ "packages/page-js/src/*" ], + "@polkadot/app-membership": [ "packages/page-membership/src" ], + "@polkadot/app-membership/*": [ "packages/page-membership/src/*" ], "@polkadot/app-parachains": [ "packages/page-parachains/src" ], "@polkadot/app-parachains/*": [ "packages/page-parachains/src/*" ], "@polkadot/app-poll": [ "packages/page-poll/src" ], diff --git a/yarn.lock b/yarn.lock index e4bb90fd80..d91bcca484 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2327,6 +2327,16 @@ __metadata: languageName: unknown linkType: soft +"@polkadot/app-membership@workspace:packages/page-membership": + version: 0.0.0-use.local + resolution: "@polkadot/app-membership@workspace:packages/page-membership" + dependencies: + "@babel/runtime": ^7.13.17 + "@polkadot/react-components": ^0.89.2-2 + "@polkadot/react-query": ^0.89.2-2 + languageName: unknown + linkType: soft + "@polkadot/app-parachains@workspace:packages/page-parachains": version: 0.0.0-use.local resolution: "@polkadot/app-parachains@workspace:packages/page-parachains"