diff --git a/cli/package.json b/cli/package.json index 608346669f..2dbd532144 100644 --- a/cli/package.json +++ b/cli/package.json @@ -35,7 +35,7 @@ "@types/mocha": "^5.2.7", "@types/node": "^10.17.18", "chai": "^4.2.0", - "eslint": "^5.16.0", + "eslint": "^7.6.0", "eslint-config-oclif": "^3.1.0", "eslint-config-oclif-typescript": "^0.1.0", "globby": "^10.0.2", diff --git a/devops/eslint-config/index.js b/devops/eslint-config/index.js index ec66d60e13..cd0e0e8cb8 100644 --- a/devops/eslint-config/index.js +++ b/devops/eslint-config/index.js @@ -43,7 +43,7 @@ module.exports = { // should prefer using 'debug' package at least to allow control of // output verbosity if logging to console. 'no-console': 'off', - '@typescript-eslint/camelcase': 'off', + 'camelcase': 'off', '@typescript-eslint/class-name-casing': 'off', "@typescript-eslint/naming-convention": [ "error", diff --git a/devops/eslint-config/package.json b/devops/eslint-config/package.json index 495eca6c8d..6d3d79eabe 100644 --- a/devops/eslint-config/package.json +++ b/devops/eslint-config/package.json @@ -17,14 +17,15 @@ }, "homepage": "https://github.com/joystream/joystream#readme", "peerDependencies": { - "eslint": ">= 5" + "eslint": "^7.6.0" }, "dependencies": { - "@typescript-eslint/parser": "^2.34.0", + "@typescript-eslint/eslint-plugin": "3.8.0", + "@typescript-eslint/parser": "3.8.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-prettier": "^3.1.3", - "eslint-plugin-react": "^7.16.0", - "eslint-plugin-react-hooks": "^2.3.0", + "eslint-plugin-react": "^7.20.5", + "eslint-plugin-react-hooks": "^4.0.8", "eslint-config-standard": "^14.1.1", "eslint-plugin-standard": "^4.0.1", "eslint-plugin-promise": "^4.2.1", diff --git a/package.json b/package.json index d96ad7c7b9..105037ba6d 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,14 @@ "tests/network-tests", "cli", "types", - "pioneer", - "pioneer/packages/*", "storage-node", "storage-node/packages/*", "devops/eslint-config", - "devops/prettier-config" + "devops/prettier-config", + "pioneer", + "pioneer/packages/apps*", + "pioneer/packages/page*", + "pioneer/packages/react*" ], "resolutions": { "@polkadot/api": "1.26.1", @@ -36,7 +38,7 @@ "devDependencies": { "husky": "^4.2.5", "prettier": "2.0.2", - "eslint": "^5.16.0" + "eslint": "^7.6.0" }, "husky": { "hooks": { diff --git a/pioneer/.123trigger b/pioneer/.123trigger index 7ed6ff82de..553d62ba4d 100644 --- a/pioneer/.123trigger +++ b/pioneer/.123trigger @@ -1 +1,2 @@ -5 +11 +0.45.2 diff --git a/pioneer/.dockerignore b/pioneer/.dockerignore index 3c3629e647..1c8c93fa2d 100644 --- a/pioneer/.dockerignore +++ b/pioneer/.dockerignore @@ -1 +1,3 @@ node_modules +build +.git diff --git a/pioneer/.env-example b/pioneer/.env-example new file mode 100644 index 0000000000..0b0cd09dcf --- /dev/null +++ b/pioneer/.env-example @@ -0,0 +1,4 @@ +# You can define all your ENV in such a file and run docker as: +# docker run ... --env-file .env ... +WS_URL=ws://localhost:9944 +POLKADOT_UI_SAMPLE=42 diff --git a/pioneer/.eslintignore b/pioneer/.eslintignore index 779cb10d5f..e24e58eaba 100644 --- a/pioneer/.eslintignore +++ b/pioneer/.eslintignore @@ -1,4 +1,17 @@ **/build/* **/coverage/* **/node_modules/* +packages/old-apps/* +packages/joy-members/* +packages/joy-election/* +packages/joy-forum/* +packages/joy-help/* +packages/joy-media/* +packages/joy-pages/* +packages/joy-proposals/* +packages/joy-roles/* +packages/joy-settings/* +packages/joy-utils/* +packages/joy-utils-old/* +.eslintrc.js i18next-scanner.config.js diff --git a/pioneer/.eslintrc.js b/pioneer/.eslintrc.js index 47800d47a6..ada8259c1e 100644 --- a/pioneer/.eslintrc.js +++ b/pioneer/.eslintrc.js @@ -1,5 +1,5 @@ // At some point don't depend on @polkadot rules and use @joystream/eslint-config -const base = require('@polkadot/dev-react/config/eslint'); +const base = require('@polkadot/dev/config/eslint'); // add override for any (a metric ton of them, initial conversion) module.exports = { @@ -13,7 +13,6 @@ module.exports = { rules: { ...base.rules, '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/camelcase': 'off', 'react/prop-types': 'off', 'new-cap': 'off', '@typescript-eslint/interface-name-prefix': 'off', @@ -21,6 +20,7 @@ module.exports = { // why only required in VSCode!?!? is eslint plugin not working like eslint commandline? // Or are we having to add this because of new versions of eslint-config-* ? 'no-console': 'off', + 'header/header': 'off' // Temporary disable polkadot's rule }, // isolate pioneer from monorepo eslint rules root: true diff --git a/pioneer/.gitignore b/pioneer/.gitignore index f24119b7cf..9f92cfdb84 100644 --- a/pioneer/.gitignore +++ b/pioneer/.gitignore @@ -10,13 +10,16 @@ tmp/ .env.test.local .env.production.local .npmrc +.yarn/* +!.yarn/releases +!.yarn/plugins +.pnp.* cc-test-reporter package-lock.json npm-debug.log* yarn-debug.log* yarn-error.log* !patches/** -.idea/ # Built Joystream types: packages/joy-types/lib/ diff --git a/pioneer/.stylelintrc b/pioneer/.stylelintrc new file mode 100644 index 0000000000..9393792fe4 --- /dev/null +++ b/pioneer/.stylelintrc @@ -0,0 +1,7 @@ +{ + "extends": [ + "stylelint-config-recommended", + "stylelint-config-styled-components" + ], + "defaultSeverity": "warning" +} diff --git a/pioneer/CHANGELOG.md b/pioneer/CHANGELOG.md index 07acbeb0ef..6ffcc70be7 100644 --- a/pioneer/CHANGELOG.md +++ b/pioneer/CHANGELOG.md @@ -1,4 +1,358 @@ -# 0.36.1 +# CHANGELOG + +## 0.51.1 Jul 27, 2020 + +- Support for Acala chain and types (Thanks to https://github.com/aniiantt) +- First batch of i18n for Arabic (Thanks to https://github.com/nightwolf3) +- Update for Polkadot council thresholds +- Council motion adjustment to cater for current and previous generations +- Adjust imminent proposals to not need own type adjustments +- Cleanup voting totals to only take free into account +- Support JSON v3 formats with kdf +- Always display time left in countdowns, not blocks +- Adjust progress component to be circular +- Rename "Deposit" button to "Send" button (less confusion) +- Ensure new generation tip cancel works for council & users +- Split council votes in backing & number of votes +- Adjust council motions to have the correct max display for nay votes +- Adjust payout toggles with increasing day increments +- Adjust button formats & layouts +- Adjust council slashing params to cater for current generation +- Fixed for keyboard locale detection +- Don't allow display in an iframe + +## 0.50.1 Jul 20, 2020 + +- Adjust CSPs for Electron (Thanks to https://github.com/EthWorks) +- Move delegation column to badge (Thanks to https://github.com/Tbaut) +- Display costs for preimage calls +- Add buttons for bid/unbid on Society +- Allow tip endorsements while in countdown +- Flatten events to group by same-kind in the same block +- Adjust identity validation to check for whitespacing +- Allow the use of VecFixed params with type detection/inputs +- Adjust controller changing to filter when stash === controller (no error, but warn) +- Allow the poll module via Governance proxy +- Expand proxy detection to deep-inspect batched calls +- Ensure various APIs are available (filtering) before attempting to render +- Ensure tooltips are correctly displayed on account hovers +- Cleanup council display for candidates +- Cleanup and simplify QR import logic (& always set genesisHash, even when not supplied) +- Always set genesisHash when accounts are derived +- Adjust breakpoints for `AccountName` via `AddressShort` +- Cleanup SUI dependencies with unused components, Progress, Responsive, Toggle +- Adjust module bundling splits, remove unused libraries & fonts +- Remove unmaintained page-123code (& references) +- Don't display finalized blocks when grandpa is not available + +## 0.49.1 Jul 13, 2020 + +- Update Subscan links with supported chains (https://github.com/carumusan) +- Enhance Electron desktop with CSP & best practices (Thanks to https://github.com/EthWorks) +- Activate Electron update feature by default (Thanks to https://github.com/EthWorks) +- Use external browser for embedded links in Electron (Thanks to https://github.com/EthWorks) +- Add testing around Electron features (Thanks to https://github.com/EthWorks) +- Support democracy account delegation (Thanks to https://github.com/Tbaut) +- Don't filter selected on multi account selector (Thanks to https://github.com/Tbaut) +- Add support for Polkadot denomination poll +- Allow input & display of OpaqueCall type from multisig +- Indicate own nominees on targets page (re-added with badges) +- Re-add indicator for own nominators in staking targets +- Add `?filter=` query param support on staking URLs +- Add generator for Kusama society designs +- Handle OpaqueCall in inputs and well as displays (multisig) +- Small layout adjustments for address display components +- Performance improvements on wrapped styles, component libraries +- Add support for display detected ASCII bytes as text +- Adjust type injection to override on-connect API defaults +- Adjust attestation display with no-balance filters + +## 0.48.1 Jul 6, 2020 + +- Fix for electron package build (Thanks to https://github.com/EthWorks) +- Allow for setting of sub identities via account action +- Adjust known account icons (Society & Treasury) +- Add Westend chain to Subscan link generator +- Display a warning with extensions and no injected accounts +- Retrieve all tips at once and sort by closing +- Fix identity set dialogs to never pass empty fields +- Optimize favorites retrieval & selection for staking (shared between) +- Support new registrar ProxyType in the signer +- Hide funds unbonding when non bonded +- Add withdraw action to staking menu (as available) +- Fix InputAddress component with state change warnings +- Bump to latest API and utilities + +## 0.47.1 Jul 1, 2020 + +- Update zh translation (Thanks to https://github.com/dushaobindoudou) +- Add DataHighway Harbour testnet endpoint (Thanks to https://github.com/ltfschoen) +- Small I18N key fix (Thanks to https://github.com/ltfschoen) +- Allow for Electron auto-update on Mac (Thanks to https://github.com/EthWorks) +- Swap to default conviction of 1x (Thanks to https://github.com/Tbaut) +- Make preimage hash selectable on FF (Thanks to https://github.com/Tbaut) +- show unbonding value in staking actions (Thanks to https://github.com/Tbaut) +- Default (via toggle) to only last 25% of eras for payouts +- Allow retracting of tips by proposer +- Allow tipping with new Substrate types (dual old/new support) +- Enable the full retrieval of all Map/Doublemap entries +- Support correct display of vesting with locks (& unlock via account) +- Adjust on-chain identity inputs with field validation +- Enable grouping of democracy locks by type +- Resolve identity links starting with https://twitter +- Display voted & unvoted council motions, referendums & tips +- Adjust toggles for file/bytes uploads +- Correct handling of recursive param structures in extrinsics +- Swap icons to use font-awesome directly, including official components +- Additional small UI cleanups and fixes + +## 0.46.1 Jun 22, 2020 + +- I18n for es (Thanks to https://github.com/wimel) +- Support for importing mini secrets via QR (Thanks to https://github.com/hanwencheng) +- Update SubstrateTEE types (Thanks to https://github.com/brenzi) +- Support for multisig calls with new weight parameters +- Split sign and send updates in the signer modal for better UI tracking +- Hide zero nonce of accounts/contracts pages +- Display API extrinsic construction errors in the extrinsics app +- Do not display signer proxies when there are none matching against accounts +- Sort recovery addresses to align with the Substrate implementation +- Check for funded controller on bonding +- Suggest max values for bonding (& bonding extra), adjusting checks +- Handle isForceEra to adjust era displays +- Display candidacy bond on council submission +- Adjust AddressMni & AddressSmall components to take advantage of bigger screens +- Display referendum & treasury tips voting status +- Add tips close buttons & countdown timer +- Disabled nominations via targets when in election +- Expand targets page to include waiting validators (full overview of all) +- Apply shared filters (name, toggles) on all validator lists +- Display balances in account view sidebar +- Adjust signer dialog ith split sign/send (better status displays) +- Adjust proxy checks for sudo calls to closer align with Polkadot +- Apply i18n caching, with no reload on translation page +- Add "Apply" i18n button to reflect editing changes in the UI +- Support Tuple inputs (params/extrinsics) for custom names +- `@polkadot/api` 1.20.1 +- `@polkadot/util` 2.15.1 + +## 0.45.2 Jun 16, 2020 + +- I18n for ja (Thanks to https://github.com/SotaWatanabe) +- I18n for pt (thanks to https://github.com/laurogripa) +- I18n for ru (Thanks to https://github.com/illlefr4u) +- Update Encointer types (thanks to https://github.com/brenzi) +- Improve Electron app security settings (Thanks to https://github.com/EthWorks) +- Rework signer dialog to cater for proxies (and multisig/proxy combinations) +- Construct payouts with oldest eras first (expire first) +- Show outstanding multisig approvals on accounts page +- Allow for addition of proxied accounts (access to proxy account only) +- Change claims to handle no statements required (new module now on Kusama) +- Publish docker image on release +- update collective calls to handle weights enhancements for latest Substrate +- Allow for tip endorsements with 0 value +- add Centrifuge live as a connection option +- Adjust Polkascan links with current active chains +- When collective proposal is in close state, hide vote buttons +- Cleanup technical committee display (header alignment) +- Adjust IPFS/IPNS network extraction for local gateways +- `@polkadot/api` 1.19.1 +- `@polkadot/util` 2.14.1 + +## 0.44.1 Jun 10, 2020 + +- Publish electron images on release (Thanks to https://github.com/EthWorks) +- Adjust with latest Arcardia types (Thanks to https://github.com/ETeissonniere) +- Extensions and fixes to the russian translations (Thanks to https://github.com/illlefr4u) +- Rewrite of the contracts app (Thanks to https://github.com/kwingram25) +- New types for SubstrateTEE (Thanks to https://github.com/brenzi) +- Adjust for new Polkadot CC1 & Kusama types +- Cater for new multisig module location +- Filter multisig signatories based on approvals, set final state based on threshold +- Adapt QR codes to cater for hashing on large payloads +- Adjust collective extrinsics to cater for weight & lengths +- Allow bonding with full free amount (this fixes bonding for vesting) +- Fixes for Kusama as well as Polkadot claims +- Allow Polkadot CC1 links to Polkascan & Subscan +- Update Polkascan links with new formats +- Don't display era progress when Forcing `isForceNone` +- Overall styling adjustments +- Cater for `{kusama,polkadot,westend}.dotapps.io` redirects +- `@polkadot/api` 1.18.1 +- `@polkadot/util` 2.13.1 + +## 0.43.1 May 26, 2020 + +- Support for Polkadot CC1 Claims (Thanks to https://github.com/amaurymartiny & https://github.com/Tbaut) +- Small typo fixes (Thanks to https://github.com/Swader) +- updates to russian translation (Thanks to https://github.com/illlefr4u) +- Adjustments to Electron build support (Thanks to https://github.com/EthWorks) +- Support for Polkadot CC1 types & RPC endpoints +- Detect & support new proposal close process in Substrate +- Adjust checks for on-click validator (immediate isActive) +- `@polkadot/api` 1.16.1 +- `@polkadot/util` 2.11.1 + +## 0.42.1 May 22, 2020 + +- Adjust Subscan proposal links (Thanks to https://github.com/illlefr4u) +- Add environment suport for docker images (Thanks to https://github.com/chevdor) +- Adjust overflows on small screens (Thanks to https://github.com/dushaobindoudou) +- Add links to Polkaassembly (Thanks to https://github.com/Tbaut) +- Address popup with detailed info (Thanks to https://github.com/kwingram25) +- Add Russian translation (Thanks to https://github.com/gregzaitsev) +- Russian translation adjustments (Thanks to https://github.com/illlefr4u) +- Add Nodle RPC endpoint (Thanks to https://github.com/ETeissonniere) +- Update Kulupu types (Thanks to https://github.com/sorpaas) +- Update Edgeware types (Thanks to https://github.com/drewstone) +- Update Encointer types (Thanks to https://github.com/brenzi) +- Update node-template types (Thanks to https://github.com/shawntabrizi) +- Update node-template types (Thanks to https://github.com/JoshOrndorff) +- Higher default contracts gas limit (Thanks to https://github.com/Stefie) +- Add block number display to event overview (Thanks to https://github.com/danforbes) +- Basic Electron support (Thanks to https://github.com/EthWorks) +- Documentation around IPFS pinning (Thanks to https://github.com/chevdor) +- Added IPFS/IPNS publishing (ipns via dotapps.io) +- Support for multisig wallets +- Ledger address on-wallet display option +- Add support for new per-staker payouts +- Allow for "best" selection in staking +- Simplified nominator & validator creation flows +- Display >64 nominators on staking pages (clipped payouts) +- Remove tooltips on staking and elsewhere (large number causes performance issues) +- Council isMember checks uses council in addition to elections +- Allow closing of council proposals +- Expand Treasury proposal inline in council (for approve/reject) +- Expand external proposals in council (preimage lookups) +- Allow for sudo with unchecked weight +- Adjust referendums to display turnout and sentiment +- Add columar modals with extra info +- Add table summaries with totals for free, bonded & stash payouts +- Add images to metadata update dropdowns +- Ecdsa keypair support +- Display delegations in voting breakdowns +- Adjust registrar modal with per-account filters +- Add i18n linting script +- Add i18n editor with translation file generator +- Custom i18n loader with caching +- Add JS sample for storage key generation +- Misc UI fixes & adjustments throughout +- Allow for tabes with aliasses (on renames) & redirects +- Align types and calls with latest substrate + +## 0.41.1 Apr 20, 2020 + +- Fix for searching child identities on parent name (Thanks to https://github.com/krogla) +- Support chains with no balances module (Thanks to https://github.com/Voxelot) +- Add out-of-the-box support for Encointer (Thanks to https://github.com/brenzi) +- Add ava.do endpoint for Kusama (Thanks to https://github.com/Swader) +- Show remaining time on staking payout actions, link payouts from actions +- Display per-validator nominators on waiting list +- Add support for Treasury tipping (display of available & creation) +- Adjust display of passing/failing calcs in democracy (incl. no display when other side is 0) +- Enable use of `system_chainType` to detect development chains +- Adjust Expander display for balances as used in accounts +- Adjust formatting outputs (via cleanup) for state queries +- Cleanup nowrap on Extender as part of tables +- Optimize retrieval of old-style validator/nominator payouts (not full historyDepth) +- Optimize AccountName with caching & when used in lists (no lookup information attached, but not shown) +- Optimize IdentityIcon with removal of extra queries +- Optimize Transfers, no unneeded useEffect +- Cleanups, remove unused components with no references (dropped in earlier refactoring) +- More components to functional, specific focus on TxModal extends +- Bumps to all @polkadot/* packages for latest support everywhere + +## 0.40.1 Apr 9, 2020 + +- Swap voting to aye/nay toggles (Thanks to https://github.com/Lowhearth) +- Cater for chains where no tip is present (Thanks to https://github.com/Sushisource) +- Export chain-specific settings via QR (thanks to https://github.com/hanwencheng) +- Improve support for WS_URL usage (Thanks to https://github.com/chevdor) +- Add out-of-the-box support for Centrifuge (Thanks to https://github.com/philipstanislaus) +- Cleanup docker image construction (Thanks to https://github.com/philipstanislaus) +- Add out-of-the-box support for node template (Thanks to https://github.com/JoshOrndorff) +- Text cleanups (Thanks to https://github.com/x5engine) +- Text cleanups (Thanks to https://github.com/ltfschoen) +- update Parachains to support latest Polkadot (Thanks to https://github.com/kwingram25) +- Rework multi address inputs (e.g. nominations & council) (Thanks to https://github.com/kwingram25) +- Introduce apps-config as a single source of config information +- Cater for metadata updates to extensions +- Rework explorer layouts, combining extrinsics & events into a single view +- Swap all layouts to be explicitly table-based (instead of table-like) +- Cater for latest Substrate referendum updates +- Allow for fast-tracking proposals +- Time countdowns where applicable, e.g. referendums +- Show referendum pass/fail status as well as change information +- Combine Accounts & Contacts into a single app +- Support for display of parent/child relationships in accounts +- Add ErrorBoundary around components +- Update Westend after reset +- Enable Subscan explorer +- Support for simple payouts on Substrate, with Payouts screen +- Extensive use of useCallback & React.memo for functional components +- Add Expander component for consistent UI +- Loading spinners used consistently +- Specific names for society & treasury addresses +- Cleanup all voting lock, consistent display +- ... loads of other under-the-hood improvements and cleanups + +## 0.39.1 Jan 31, 2020 + +- **Breaking** Drop support for V1 Substrate chains +- Translation into Chinese (Thanks to https://github.com/dushaobindoudou) +- Support for sign-only transactions (Thanks to https://github.com/mzolkiewski) +- Add support for WestEnd testnet +- Add support for social recovery in accounts +- Add counters for all proposal-based apps +- Disable spellcheck on all input fields (privacy) +- Query the paymentInfo API to get weight fee information +- Remove FF warning with https:// -> ws://localhost +- Staking now supports where the controller or stash accounts are not local +- Social app +- Add support for identity setting (via identity module) +- Add support for registrars to hand out identity judgements +- Use both internal and lib hooks as applicable (refactoring) +- Support QR codes (accounts) with optional names +- Cleanup all Modals, simplify +- Adjust balance display formats +- Update to latest libraries (incl. util 2.0 & api 1.0) + +## 0.38.1 + +- Fix summarybar in 123-code (Thanks to https://github.com/anakornk) +- Update Edgeware with correct keys (Thanks to https://github.com/drewstone) +- Add InputAddressMulti inputs, both to council and staking nominators +- Rework all layouts, removing cards for table-ike-layouts +- Technical comittee app +- Allow for external proposal and queued for dispatch in democracy +- Add pre-image support to democracy proposals (including imminent) +- Improved staking page rendering (background) +- Update to latest libraries + +## 0.37.1 + +- Support for Kusama CC3 +- Support for contracts with new ABI v2 (Thanks to https://github.com/kwingram25) +- Support for on-chain nicks +- Speed improvements for the staking pages +- Add account derivation from existing account +- Council voting with runner up & phragmen +- Allow favorites in validators pages +- Rework nominations to take favorites & current into account +- Enhance AddressCard with additional info (incl. vested) +- Move account/address actions to popup menu +- Convert a large number of components to use hooks +- Display validator graphs +- Refactor of backup modal (Thanks to @LukeSugiura) +- Enable language setting options (Thanks to @LukeSugiura) +- Allow for signRaw to be used in the signing toolbox (injected accounts) +- Display account names in status events +- Nomination targets dashboard +- Validator preferences are expressed as commission % as supported by chains +- Account locks are applied on a genesis range (e.g. CC2 & CC3 allow availability) +- ... lots of smaller enhancements & bug fixes + +## 0.36.1 - Api 0.95.1, Util 1.6.1, Extension 0.13.1 - Support latest contracts ABI (via API), incl. rework of contracts UI @@ -20,7 +374,7 @@ - Make the network selection clickable on network name (via bounty) - ... and a number of cleanups all around -# 0.35.1 +## 0.35.1 - Api 0.91.1, Util 1.2.1, Extension 0.10.1 - Support for accounts added via Qr (for instance, the Parity Signer) @@ -33,7 +387,7 @@ - Fix account derivation with `///password` - Lots of component & maintainability cleanups -# 0.34.1 +## 0.34.1 - Kusama support - Full support for Substrate 2.x & Polkadot 0.5.0 networks @@ -42,7 +396,7 @@ - Basic Council, Parachains & Treasury apps - Moved ui-* packages to react-* -# 0.33.1 +## 0.33.1 - Allow for externally injected accounts (i.e. via extension, polkadot-js & SingleSource) - Links to extrnisics & addresses on Polkascan @@ -60,39 +414,39 @@ - Latest @polkadot/util & @polkadot/api - A large number of optimizations and smaller fixes -# 0.32.1 +## 0.32.1 - Support for Substrate 1.0 release & metadata v4 - @polkadot/api 0.77.1 -# 0.31.1 +## 0.31.1 - Cleanups, fixes and features around the poc-4 staking module - Number of UI enhancements -# 0.30.1 +## 0.30.1 - Staking page indicator for offline nodes (count & block) - Rework page tabs and content layouts - Cleanup of all UI summary headers - Emberic Elem support (replaces Dried Danta) -# 0.29.1 +## 0.29.1 - @polkadot/util & @polkadot/api 0.75.1 -# 0.28.1 +## 0.28.1 - Support for substrate 1.0-rc -# 0.27.1 +## 0.27.1 - Bring in new staking & nominating functions - Swap default keyring accounts (on creation) to sr25519 - New faster crypto algorithms - Misc. bug fixes all around -# 0.26.1 +## 0.26.1 - Swap keyring to HDKD derivation, mnemonic keys are now not backwards compatible with those created earlier. (Defaults are still for ed25519) - Swap crypto to new WASM-backed version (and remove libsodium dependency) @@ -100,23 +454,23 @@ - New mobile-friendly sidebar - Fix issues with nominating (old non-bonds interface) -# 0.25.1 +## 0.25.1 - Swap to publishing -beta.x on merge (non-breaking testing) - # 0.24.1 + ## 0.24.1 Storage now handles Option type properly - # 0.23.1 + ## 0.23.1 JavaScript console introduced -# 0.22.1 +## 0.22.1 - Use new Compact transaction format - this requires the latest binaries from either Polkadot or Substrate -# 0.21.1 +## 0.21.1 - PoC-3 support with latest Substrate master & Polkadot master - Add support for Charred Cherry (Substrate) and Alexander (Polkadot) testnets diff --git a/pioneer/I18N.md b/pioneer/I18N.md new file mode 100644 index 0000000000..112e3b81ff --- /dev/null +++ b/pioneer/I18N.md @@ -0,0 +1,22 @@ +# I18N + +The apps UI allows all strings to be translated. Additionally it has a basic UI that allows for the creation of the required translation files, which will give an overview on the progress for a specific language. + +## Updating translations + +To update translations, the following process is required. + +- launch the apps UI, either locally or via https://polkadot.js.org/apps +- explicitly navigate to the i18n page, https://polkadot.js.org/apps/#/settings/i18n + +Here you will find a dropdown of all the available languages and all the modules that maps to the UI. On a single screen you will be able to see all the available strings for a specific module. + +- adjust any strings as required +- once completed with the changes, click the `Generate translation.json` button to download the translation file +- this file can now be added to the repo with a PR to https://github.com/polkadot-js/apps/tree/master/packages/apps/public/locales + +## Adding a new language (if not in dropdown above) + +The process is similar for the above, but does require a new folder with the language identifier to be added. Create [packages/apps/public/locales/](https://github.com/polkadot-js/apps/tree/master/packages/apps/public/locales) folder with an empty `translation.json` (containing only `{}`). After addition of the folder, run `yarn build:i18n` and then the new language will be available for update as per the process in the previous section. + +In addition to the language folder, the language also needs to be added to the dropdown for available languages, this can be found in [packages/apps-config/src/settings.languages.ts](https://github.com/polkadot-js/apps/blob/master/packages/apps-config/src/settings/languages.ts) diff --git a/pioneer/README.md b/pioneer/README.md index 2e54f5f110..b1640de317 100644 --- a/pioneer/README.md +++ b/pioneer/README.md @@ -11,16 +11,17 @@ This can be accessed as a hosted application via [https://testnet.joystream.org] The repo is split into a number of packages, each representing an application. These are - - [apps](packages/apps/) This is the main entry point. It handles the selection sidebar and routing to the specific application being displayed. -- [app-accounts](packages/app-accounts/) A basic account management app. -- [app-address-book](packages/app-address-book/) A basic address management app. -- [app-explorer](packages/app-explorer/) A simple block explorer. It only shows the most recent blocks, updating as they become available. -- [app-extrinsics](packages/app-extrinsics/) Submission of extrinsics to a node. -- [app-js](packages/app-js/) An online code editor with [@polkadot-js/api](https://github.com/polkadot-js/api/tree/master/packages/api) access to the currently connected node. -- [app-settings](packages/app-settings/) A basic settings management app, allowing choice of language, node to connect to, and theme -- [app-staking](packages/app-staking/) A basic staking management app, allowing staking and nominations. -- [app-storage](packages/app-storage/) A simple node storage query application. Multiple queries can be queued and updates as new values become available. -- [app-toolbox](packages/app-toolbox/) Submission of raw data to RPC endpoints and utility hashing functions. -- [app-transfer](packages/app-transfer/) A basic account management app, allowing transfer of Units/DOTs between accounts. +- [apps-electron](packages/apps-electron/) Desktop app running [apps](packages/apps/). +- [page-accounts](packages/page-accounts/) A basic account management app. +- [page-address-book](packages/page-address-book/) A basic address management app. +- [page-explorer](packages/page-explorer/) A simple block explorer. It only shows the most recent blocks, updating as they become available. +- [page-extrinsics](packages/page-extrinsics/) Submission of extrinsics to a node. +- [page-js](packages/page-js/) An online code editor with [@polkadot-js/api](https://github.com/polkadot-js/api/tree/master/packages/api) access to the currently connected node. +- [page-settings](packages/page-settings/) A basic settings management app, allowing choice of language, node to connect to, and theme +- [page-staking](packages/page-staking/) A basic staking management app, allowing staking and nominations. +- [page-storage](packages/page-storage/) A simple node storage query application. Multiple queries can be queued and updates as new values become available. +- [page-toolbox](packages/page-toolbox/) Submission of raw data to RPC endpoints and utility hashing functions. +- [page-transfer](packages/page-transfer/) A basic account management app, allowing transfer of Units/DOTs between accounts. In addition the following libraries are also included in the repo. These are to be moved to the [@polkadot/ui](https://github.com/polkadot-js/ui/) repository once it reaches a base level of stability and usability. (At this point with the framework being tested on the apps above, it makes development easier having it close) diff --git a/pioneer/babel.config.js b/pioneer/babel.config.js index 92ce3bd506..5b479645c9 100644 --- a/pioneer/babel.config.js +++ b/pioneer/babel.config.js @@ -1,4 +1,5 @@ -module.exports = { - extends: '@polkadot/dev-react/config/babel', - sourceType: 'unambiguous' -}; +// Copyright 2017-2020 @polkadot/apps authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +module.exports = require('@polkadot/dev/config/babel'); diff --git a/pioneer/docker/nginx.conf b/pioneer/docker/nginx.conf new file mode 100644 index 0000000000..dce1ffbd61 --- /dev/null +++ b/pioneer/docker/nginx.conf @@ -0,0 +1,27 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + gzip on; + include /etc/nginx/conf.d/*.conf; +} diff --git a/pioneer/env.sh b/pioneer/env.sh new file mode 100755 index 0000000000..e01e134aad --- /dev/null +++ b/pioneer/env.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# This script is used when the docker container starts and does the magic to +# bring the ENV variables to the generated static UI. + +TARGET=./env-config.js + +# Recreate config file +echo -n > $TARGET + +declare -a vars=( + "WS_URL" + "SAMPLE" +) + +echo "window.process_env = {" >> $TARGET +for VAR in ${vars[@]}; do + echo " $VAR: \"${!VAR}\"," >> $TARGET +done +echo "}" >> $TARGET diff --git a/pioneer/i18next-scanner.config.js b/pioneer/i18next-scanner.config.js index fedbd1b1a4..62c25d27da 100644 --- a/pioneer/i18next-scanner.config.js +++ b/pioneer/i18next-scanner.config.js @@ -1,7 +1,44 @@ +// Copyright 2017-2020 @polkadot/apps authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + const fs = require('fs'); const path = require('path'); const typescript = require('typescript'); +const findPackages = require('./scripts/findPackages'); + +function transform (file, enc, done) { + const { ext } = path.parse(file.path); + + if (ext === '.tsx') { + const content = fs.readFileSync(file.path, enc); + + const { outputText } = typescript.transpileModule(content, { + compilerOptions: { + target: 'es2018' + }, + fileName: path.basename(file.path) + }); + + const parserHandler = (key, options) => { + options.defaultValue = key; + + if (process.platform !== 'win32') { + options.ns = /packages\/(.*?)\/src/g.exec(file.path)[1].replace('page-', 'app-'); + } else { + options.ns = /packages\\(.*?)\\src/g.exec(file.path)[1].replace('page-', 'app-'); + } + + this.parser.set(key, options); + }; + + this.parser.parseFuncFromString(outputText, parserHandler); + } + + done(); +} + module.exports = { input: [ 'packages/*/src/**/*.{ts,tsx}', @@ -10,80 +47,27 @@ module.exports = { '!packages/*/src/i18n/**', '!**/node_modules/**' ], - output: './', options: { debug: true, + defaultLng: 'en', func: { - list: ['t', 'i18next.t', 'i18n.t'], - extensions: ['.tsx'] - }, - trans: { - component: 'Trans' + extensions: ['.tsx', '.ts'], + list: ['t', 'i18next.t', 'i18n.t'] }, + keySeparator: false, // key separator lngs: ['en'], - defaultLng: 'en', - ns: [ - 'app-123code', - 'app-accounts', - 'app-address-book', - 'app-claims', - 'app-contracts', - 'app-council', - 'app-dashboard', - 'app-democracy', - 'app-explorer', - 'app-extrinsics', - 'app-generic-asset', - 'app-js', - 'app-parachains', - 'app-settings', - 'app-staking', - 'app-storage', - 'app-sudo', - 'app-toolbox', - 'app-transfer', - 'app-treasury', - 'apps', - 'apps-routing', - 'react-api', - 'react-components', - 'react-params', - 'react-query', - 'react-signer', - 'ui' - ], - defaultNs: 'ui', + ns: findPackages().map(({ dir }) => dir.replace('page-', 'app-')), + nsSeparator: false, // namespace separator resource: { - loadPath: 'packages/apps/public/locales/{{lng}}/{{ns}}.json', - savePath: 'packages/apps/public/locales/{{lng}}/{{ns}}.json', jsonIndent: 2, - lineEnding: '\n' + lineEnding: '\n', + loadPath: 'packages/apps/public/locales/{{lng}}/{{ns}}.json', + savePath: 'packages/apps/public/locales/{{lng}}/{{ns}}.json' }, - nsSeparator: false, // namespace separator - keySeparator: false // key separator - }, - transform: function transform (file, enc, done) { - const { ext } = path.parse(file.path); - - if (ext === '.tsx') { - const content = fs.readFileSync(file.path, enc); - - const { outputText } = typescript.transpileModule(content, { - compilerOptions: { - target: 'es2018' - }, - fileName: path.basename(file.path) - }); - - const parserHandler = (key, options) => { - options.defaultValue = key; - options.ns = /packages\/(.*?)\/src/g.exec(file.path)[1]; - this.parser.set(key, options); - }; - - this.parser.parseFuncFromString(outputText, parserHandler); + trans: { + component: 'Trans' } - - done(); - } + }, + output: './', + transform }; diff --git a/pioneer/jest.config.js b/pioneer/jest.config.js index 643163e06d..342de2be88 100644 --- a/pioneer/jest.config.js +++ b/pioneer/jest.config.js @@ -1,17 +1,26 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const config = require('@polkadot/dev-react/config/jest'); +// Copyright 2017-2020 @polkadot/apps authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +const config = require('@polkadot/dev/config/jest'); + const findPackages = require('./scripts/findPackages'); -const internalModules = findPackages().reduce((modules, { dir, name }) => { - modules[`${name}(.*)$`] = `/packages/${dir}/src/$1`; +const internalModules = findPackages() + .filter(({ name }) => !['@polkadot/apps'].includes(name)) + .reduce((modules, { dir, name }) => { + modules[`${name}(.*)$`] = `/packages/${dir}/src/$1`; - return modules; -}, {}); + return modules; + }, {}); module.exports = Object.assign({}, config, { moduleNameMapper: { ...internalModules, - '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object', - '\\.(css|less)$': 'empty/object' - } + '\\.(css|less)$': 'empty/object', + '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object' + }, + transformIgnorePatterns: [ + '/node_modules' + ] }); diff --git a/pioneer/lerna.json b/pioneer/lerna.json index 717f6b57c5..be98869ad3 100644 --- a/pioneer/lerna.json +++ b/pioneer/lerna.json @@ -10,5 +10,5 @@ "packages": [ "packages/*" ], - "version": "0.37.0-beta.63" + "version": "0.51.1" } diff --git a/pioneer/package.json b/pioneer/package.json index b368a86819..b050147ce3 100644 --- a/pioneer/package.json +++ b/pioneer/package.json @@ -1,5 +1,6 @@ { - "version": "0.37.0-beta.63", + "version": "0.51.1", + "license": "Apache-2", "private": true, "engines": { "node": ">=12.18.0", @@ -8,70 +9,78 @@ "homepage": ".", "name": "pioneer", "scripts": { - "analyze": "yarn run build && cd packages/apps && yarn run source-map-explorer build/main.*.js", - "build": "yarn run build:code && yarn run build:i18n", - "build:code": "NODE_ENV=production polkadot-dev-build-ts", - "build:i18n": "i18next-scanner --config i18next-scanner.config.js", + "analyze": "yarn clean && BUILD_ANALYZE=1 yarn run build:code && yarn source-map-explorer packages/apps/build/main.*.js", + "build": "yarn run build:i18n && yarn run build:code", + "build:code": "NODE_ENV=production node ./scripts/dev-build-ts.js", + "build:i18n": "i18next-scanner --config i18next-scanner.config.js && node ./scripts/i18nSort.js", + "build:www": "rm -rf packages/apps/build && mkdir -p packages/apps/build && yarn run build:i18n && cd packages/apps && NODE_ENV=production webpack --config webpack.config.js", "docs": "echo \"skipping docs\"", "clean": "polkadot-dev-clean-build", "clean:i18n": "rm -rf packages/apps/public/locales/en && mkdir -p packages/apps/public/locales/en", "lint": "eslint --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty", + "lint:css": "stylelint './packages/**/src/**/*.tsx'", "lint-only-errors": "eslint --quiet --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty", "lint-autofix": "eslint --fix --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty", "postinstall": "polkadot-dev-yarn-only", "test": "echo \"skipping tests\"", "vanitygen": "node packages/app-accounts/scripts/vanitygen.js", - "start": "cd packages/apps && webpack --config webpack.config.js", + "start": "yarn clean && cd packages/apps && webpack --config webpack.config.js", "generate-schemas": "json2ts -i packages/joy-types/src/schemas/role.schema.json -o packages/joy-types/src/schemas/role.schema.ts", "build-storybook": "build-storybook -c .storybook", "storybook": "start-storybook -s ./packages/apps/public -p 3001" }, "devDependencies": { - "@babel/core": "^7.7.0", - "@babel/runtime": "^7.7.1", - "@babel/cli": "^7.7.4", - "@polkadot/dev-react": "^0.32.0-beta.13", - "@polkadot/ts": "^0.1.84", - "@polkadot/dev": "^0.32.0-beta.15", + "@babel/core": "^7.10.5", + "@babel/register": "^7.10.5", + "@babel/runtime": "^7.10.5", + "@pinata/sdk": "^1.1.10", + "@polkadot/dev": "^0.55.28", + "@polkadot/ts": "^0.3.29", + "@types/bn.js": "^4.11.6", + "@types/chart.js": "^2.9.23", + "@types/file-saver": "^2.0.1", + "@types/i18next": "^13.0.0", + "@types/jest": "^26.0.7", + "@types/react-beautiful-dnd": "^13.0.0", + "@types/react-copy-to-clipboard": "^4.3.0", + "@types/react-dom": "^16.9.8", + "@types/react-router-dom": "^5.1.5", + "@types/react-tooltip": "^4.2.4", + "@types/store": "^2.0.2", + "@types/styled-components": "^5.1.1", + "@types/styled-theming": "^2.2.4", + "concurrently": "^5.2.0", + "devtron": "^1.4.0", + "dnslink-cloudflare": "^2.0.4", + "electron": "^9.1.1", + "electron-builder": "^22.8.0", + "electron-builder-notarize": "^1.2.0", + "i18next-scanner": "^2.11.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "source-map-explorer": "^2.4.2", + "stylelint": "^13.6.1", + "stylelint-config-recommended": "^3.0.0", + "stylelint-config-styled-components": "^0.1.1", + "terser-webpack-plugin": "^3.0.7", + "webpack": "^4.44.0", + "webpack-cli": "^3.3.12", + "webpack-merge": "^4.2.2", + "webpack-plugin-serve": "^1.0.1", + "//": "Joystream-specific", + "react-i18next": "^11.7.0", "@storybook/addon-knobs": "^5.2.5", "@storybook/addon-storysource": "^5.2.5", - "@types/jest": "^24.0.22", - "@types/react-router-dom": "^5.1.4", - "@types/yup": "^0.26.36", - "autoprefixer": "^9.7.1", - "empty": "^0.10.1", - "html-loader": "^0.5.5", - "i18next-scanner": "^2.10.3", + "@storybook/addon-actions": "^5.2.5", + "@storybook/addon-console": "^1.2.1", + "@storybook/react": "^5.2.5", "json-schema-to-typescript": "^7.1.0", - "markdown-loader": "^5.1.0", - "postcss": "^7.0.21", - "postcss-clean": "^1.1.0", - "postcss-flexbugs-fixes": "^4.1.0", - "postcss-import": "^12.0.0", - "postcss-loader": "^3.0.0", - "postcss-nested": "^4.2.1", - "postcss-sass": "^0.4.1", - "postcss-simple-vars": "^5.0.0", - "precss": "^4.0.0", - "source-map-explorer": "^2.0.1", "storybook-react-router": "^1.0.8", - "ts-jest": "^24.1.0", - "tsconfig-paths-webpack-plugin": "^3.2.0", - "webpack": "^4.33.0", - "typescript": "3.7.2", - "cpx": "^1.5.0", - "eslint-config-semistandard": "^15.0.0", - "eslint-config-standard": "^14.1.1", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.1" + "typescript": "^3.9.7", + "eslint-plugin-header": "^3.0.0", + "eslint-plugin-sort-destructure-keys": "^1.3.5" }, "dependencies": { - "@polkadot/ui-settings": "^0.47.0-beta.3", - "@storybook/addon-actions": "^5.2.5", - "@storybook/addon-console": "^1.2.1", - "@storybook/react": "^5.2.5", "@types/lodash": "^4.14.138", "@types/marked": "^0.7.0", "ajv": "^6.10.2", diff --git a/pioneer/packages/app-123code/README.md b/pioneer/packages/app-123code/README.md deleted file mode 100644 index fe01a1661a..0000000000 --- a/pioneer/packages/app-123code/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# @polkadot/app-123code - -A simple template to get started with adding an "app" to this UI. It contains the bare minimum for a nicely hackable app (if you just want to code _somewhere_) and the steps needed to create, add and register an new app that appears in the UI. - -## adding an app - -If you want to add a new app to the UI, this is the place to start. - -1. Duplicate this `app-123code` folder and give it an appropriate name, in this case we will select `app-example` to keep things clear. -2. Edit the `apps-example/package.json` app description, i.e. the name, author and relevant overview. - -And we have the basic app source setup, time to get the tooling correct. - -3. Add the new app to the TypeScript config in root, `tsconfig.json`, i.e. an entry such as `"@polkadot/app-example/*": [ "packages/app-example/src/*" ],` - -At this point the app should be buildable, but not quite reachable. The final step is to add it to the actual sidebar in `apps`. - -4. In `apps-routing/src` duplicate the `123code.ts` file to `example.ts` and edit it with the appropriate information, including the hash link, name and icon (any icon name from semantic-ui-react/font-awesome 4 should be appropriate). -5. In the above description file, the `isHidden` field needs to be toggled to make it appear - the base template is hidden by default. -6. Finally add the `template` to the `apps-routing/src/index.ts` file at the appropriate place for both full and light mode (either optional) - -Yes. After all that we have things hooked up. Run `yarn start` and your new app (non-coded) should show up. Now start having fun and building something great. diff --git a/pioneer/packages/app-123code/src/AccountSelector.tsx b/pioneer/packages/app-123code/src/AccountSelector.tsx deleted file mode 100644 index 289b60b869..0000000000 --- a/pioneer/packages/app-123code/src/AccountSelector.tsx +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import React, { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import { Bubble, InputAddress } from '@polkadot/react-components'; -import { AccountIndex, Balance, Nonce } from '@polkadot/react-query'; - -interface Props { - className?: string; - onChange: (accountId: string | null) => void; -} - -function AccountSelector ({ className, onChange }: Props): React.ReactElement { - const [accountId, setAccountId] = useState(null); - - useEffect((): void => onChange(accountId), [accountId]); - - return ( -
- -
- - - - - - - - - -
-
- ); -} - -export default styled(AccountSelector)` - align-items: flex-end; - - .summary { - text-align: center; - } -`; diff --git a/pioneer/packages/app-123code/src/SummaryBar.tsx b/pioneer/packages/app-123code/src/SummaryBar.tsx deleted file mode 100644 index 9242644597..0000000000 --- a/pioneer/packages/app-123code/src/SummaryBar.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { AccountId } from '@polkadot/types/interfaces'; -import { BareProps, I18nProps } from '@polkadot/react-components/types'; - -import BN from 'bn.js'; -import React, { useContext } from 'react'; -import { ApiContext, withCalls } from '@polkadot/react-api'; -import { Bubble, IdentityIcon } from '@polkadot/react-components'; -import { formatBalance, formatNumber } from '@polkadot/util'; - -import translate from './translate'; - -interface Props extends BareProps, I18nProps { - balances_totalIssuance?: BN; - chain_bestNumber?: BN; - chain_bestNumberLag?: BN; - staking_validators?: AccountId[]; -} - -function SummaryBar ({ balances_totalIssuance, chain_bestNumber, chain_bestNumberLag, staking_validators }: Props): React.ReactElement { - const { api, systemChain, systemName, systemVersion } = useContext(ApiContext); - - return ( - -
- - {systemName} v{systemVersion} - - - {systemChain} - - - {api.runtimeVersion.implName} v{api.runtimeVersion.implVersion} - - - {formatNumber(chain_bestNumber)} ({formatNumber(chain_bestNumberLag)} lag) - - {staking_validators && ( - { - staking_validators.map((accountId, index): React.ReactNode => ( - - )) - } - )} - - {formatBalance(balances_totalIssuance)} - -
-
- ); -} - -// inject the actual API calls automatically into props -export default translate( - withCalls( - 'derive.chain.bestNumber', - 'derive.chain.bestNumberLag', - 'derive.staking.validators', - 'query.balances.totalIssuance' - )(SummaryBar) -); diff --git a/pioneer/packages/app-123code/src/Transfer.tsx b/pioneer/packages/app-123code/src/Transfer.tsx deleted file mode 100644 index 35ccce6f8b..0000000000 --- a/pioneer/packages/app-123code/src/Transfer.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import BN from 'bn.js'; -import React, { useState } from 'react'; -import { Button, InputAddress, InputBalance, TxButton } from '@polkadot/react-components'; - -import Summary from './Summary'; - -interface Props { - accountId?: string | null; -} - -export default function Transfer ({ accountId }: Props): React.ReactElement { - const [amount, setAmount] = useState(null); - const [recipientId, setRecipientId] = useState(null); - - return ( -
-

transfer

-
-
- - - - - -
- Make a transfer from any account you control to another account. Transfer fees and per-transaction fees apply and will be calculated upon submission. -
-
- ); -} diff --git a/pioneer/packages/app-123code/src/index.tsx b/pioneer/packages/app-123code/src/index.tsx deleted file mode 100644 index de0de71b2c..0000000000 --- a/pioneer/packages/app-123code/src/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -// some types, AppProps for the app and I18nProps to indicate -// translatable strings. Generally the latter is quite "light", -// `t` is inject into props (see the HOC export) and `t('any text') -// does the translation -import { AppProps, I18nProps } from '@polkadot/react-components/types'; - -// external imports (including those found in the packages/* -// of this repo) -import React, { useState } from 'react'; - -// local imports and components -import AccountSelector from './AccountSelector'; -import SummaryBar from './SummaryBar'; -import Transfer from './Transfer'; -import translate from './translate'; - -// define our internal types -interface Props extends AppProps, I18nProps {} - -function App ({ className }: Props): React.ReactElement { - const [accountId, setAccountId] = useState(null); - - return ( - // in all apps, the main wrapper is setup to allow the padding - // and margins inside the application. (Just from a consistent pov) -
- - - -
- ); -} - -export default translate(App); diff --git a/pioneer/packages/app-claims/src/Claim.tsx b/pioneer/packages/app-claims/src/Claim.tsx deleted file mode 100644 index 7e46c5fff9..0000000000 --- a/pioneer/packages/app-claims/src/Claim.tsx +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { Option } from '@polkadot/types'; -import { BalanceOf, EthereumAddress } from '@polkadot/types/interfaces'; -import { I18nProps } from '@polkadot/react-components/types'; - -import React, { useContext, useEffect, useState } from 'react'; -import styled from 'styled-components'; -import { ApiContext } from '@polkadot/react-api'; -import { Button, Card } from '@polkadot/react-components'; -import { formatBalance } from '@polkadot/util'; - -import translate from './translate'; -import { addrToChecksum } from './util'; - -interface Props extends I18nProps { - button: React.ReactNode; - ethereumAddress: EthereumAddress | null; -} - -function Claim ({ button, className, ethereumAddress, t }: Props): React.ReactElement | null { - const { api } = useContext(ApiContext); - const [claimValue, setClaimValue] = useState(null); - const [claimAddress, setClaimAddress] = useState(null); - const [isBusy, setIsBusy] = useState(false); - - const _fetchClaim = (address: EthereumAddress): void => { - setIsBusy(true); - - api.query.claims - .claims>(address) - .then((claim): void => { - setClaimValue(claim.unwrapOr(null)); - setIsBusy(false); - }) - .catch((): void => setIsBusy(false)); - }; - - useEffect((): void => { - if (ethereumAddress !== claimAddress) { - setClaimAddress(ethereumAddress); - ethereumAddress && _fetchClaim(ethereumAddress); - } - }, [ethereumAddress]); - - if (isBusy || !claimAddress) { - return null; - } - - const hasClaim = claimValue && claimValue.gten(0); - - return ( - -
- {t('Your Ethereum account')} -

{addrToChecksum(claimAddress.toString())}

- {hasClaim && claimValue - ? ( - <> - {t('has a valid claim for')} -

{formatBalance(claimValue)}

- {button} - - ) - : ( - <> - {t('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')} - - )} -
-
- ); -} - -export default translate( - styled(Claim)` - font-size: 1.15rem; - display: flex; - flex-direction: column; - justify-content: center; - min-height: 12rem; - align-items: center; - margin: 0 1rem; - - h3 { - font-family: monospace; - font-size: 1.5rem; - max-width: 100%; - margin: 0.5rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - h2 { - margin: 0.5rem 0 2rem; - font-family: monospace; - font-size: 2.5rem; - font-weight: 200; - } - ` -); diff --git a/pioneer/packages/app-claims/src/index.tsx b/pioneer/packages/app-claims/src/index.tsx deleted file mode 100644 index ff07892784..0000000000 --- a/pioneer/packages/app-claims/src/index.tsx +++ /dev/null @@ -1,259 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -// Copyright 2017-2019 @polkadot/app-123code authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { Compact } from '@polkadot/types'; -import { Balance, EcdsaSignature, EthereumAddress } from '@polkadot/types/interfaces'; -import { AppProps, I18nProps } from '@polkadot/react-components/types'; -import { ApiProps } from '@polkadot/react-api/types'; - -import React from 'react'; -import { Trans } from 'react-i18next'; -import styled from 'styled-components'; -import CopyToClipboard from 'react-copy-to-clipboard'; -import { withApi, withMulti } from '@polkadot/react-api'; -import { Button, Card, Columar, Column, InputAddress, Tooltip } from '@polkadot/react-components'; -import { InputNumber } from '@polkadot/react-components/InputNumber'; -import TxModal, { TxModalState, TxModalProps } from '@polkadot/react-components/TxModal'; -import { u8aToHex, u8aToString } from '@polkadot/util'; -import { decodeAddress } from '@polkadot/util-crypto'; - -import ClaimDisplay from './Claim'; -import { recoverFromJSON } from './util'; - -import translate from './translate'; - -enum Step { - Account = 0, - Sign = 1, - Claim = 2, -} - -interface Props extends AppProps, ApiProps, I18nProps, TxModalProps {} - -interface State extends TxModalState { - didCopy: boolean; - ethereumAddress: EthereumAddress | null; - claim?: Balance | null; - signature?: EcdsaSignature | null; - step: Step; -} - -const Payload = styled.pre` - cursor: copy; - font-family: monospace; - border: 1px dashed #c2c2c2; - background: #fafafa; - padding: 1rem; - width: 100%; - margin: 1rem 0; - white-space: normal; - word-break: break-all; -`; - -const Signature = styled.textarea` - font-family: monospace; - padding: 1rem; - border: 1px solid rgba(34, 36, 38, 0.15); - border-radius: 0.25rem; - margin: 1rem 0; - resize: none; - width: 100%; - - &::placeholder { - color: rgba(0, 0, 0, 0.5); - } - - &:-ms-input-placeholder { - color: rgba(0, 0, 0, 0.5); - } - - &::-ms-input-placeholder { - color: rgba(0, 0, 0, 0.5); - } -`; - -class App extends TxModal { - constructor (props: Props) { - super(props); - - this.defaultState = { - ...this.defaultState, - claim: null, - didCopy: false, - ethereumAddress: null, - signature: null, - step: 0 - }; - this.state = this.defaultState; - } - - public componentDidUpdate (): void { - if (this.state.didCopy) { - setTimeout((): void => { - this.setState({ didCopy: false }); - }, 1000); - } - } - - public render (): React.ReactNode { - const { api, systemChain = '', t } = this.props; - const { accountId, didCopy, ethereumAddress, signature, step } = this.state; - - const payload = accountId - ? ( - u8aToString(Compact.stripLengthPrefix(api.consts.claims.prefix.toU8a(true))) + - u8aToHex(decodeAddress(accountId), -1, false) - ) - : ''; - - return ( -
-
-

- claim your {InputNumber.units} tokens -

- - - -

{t('1. Select your {{chain}} account', { - replace: { - chain: systemChain - } - })}

- - {(step === Step.Account) && ( - -
- ); - } - - protected isDisabled = (): boolean => { - const { accountId, signature } = this.state; - - return !accountId || !signature; - } - - protected isUnsigned = (): boolean => true; - - protected submitLabel = (): React.ReactNode => this.props.t('Redeem'); - - protected txMethod = (): string => 'claims.claim'; - - protected txParams = (): [string | null, EcdsaSignature | null] => { - const { accountId, signature } = this.state; - - return [ - accountId ? accountId.toString() : null, - signature || null - ]; - } - - protected onChangeAccount = (accountId: string | null): void => { - this.setState(({ step }: State): Pick => { - return { - ...( - step > Step.Account - ? this.defaultState - : {} - ), - accountId - }; - }); - } - - protected onChangeSignature = (event: React.SyntheticEvent): void => { - const { value: signatureJson } = event.target as HTMLInputElement; - - this.setState(({ step }: State): Pick => ({ - ...( - step > Step.Sign - ? { step: Step.Sign } - : {} - ), - ...recoverFromJSON(signatureJson) - })); - } - - private onCopy = (): void => { - this.setState({ didCopy: true }); - } - - private setStep = (step: Step): () => void => - (): void => { - this.setState({ step }); - } -} - -export default withMulti( - App, - translate, - withApi -); diff --git a/pioneer/packages/app-claims/src/util.spec.ts b/pioneer/packages/app-claims/src/util.spec.ts deleted file mode 100644 index a3d46b8a62..0000000000 --- a/pioneer/packages/app-claims/src/util.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017-2019 @polkadot/react-components authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { hexToU8a } from '@polkadot/util'; - -import { publicToAddr } from './util'; - -describe('publicToAddr', (): void => { - it('converts a publicKey to address', (): void => { - expect( - publicToAddr( - hexToU8a( - '0x836b35a026743e823a90a0ee3b91bf615c6a757e2b60b9e1dc1826fd0dd16106f7bc1e8179f665015f43c6c81f39062fc2086ed849625c06e04697698b21855e' - ) - ) - ).toEqual('0x0BED7ABd61247635c1973eB38474A2516eD1D884'); - }); -}); diff --git a/pioneer/packages/app-council/src/Motions/Motion.tsx b/pioneer/packages/app-council/src/Motions/Motion.tsx deleted file mode 100644 index 5836091b54..0000000000 --- a/pioneer/packages/app-council/src/Motions/Motion.tsx +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2017-2019 @polkadot/app-democracy authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { Proposal as ProposalType, Votes } from '@polkadot/types/interfaces'; -import { I18nProps } from '@polkadot/react-components/types'; - -import BN from 'bn.js'; -import React from 'react'; -import { Option } from '@polkadot/types'; - -import { ActionItem, InputAddress, Labelled, Voting } from '@polkadot/react-components'; -import { withCalls, withMulti } from '@polkadot/react-api'; - -import translate from '../translate'; - -interface Props extends I18nProps { - chain_bestNumber?: BN; - hash: string; - proposal: ProposalType | null; - votes: Votes | null; -} - -function Motion ({ className, hash, proposal, t, votes }: Props): React.ReactElement | null { - if (!proposal || !votes) { - return null; - } - - const { ayes, index, nays, threshold } = votes; - - return ( - - } - expandNested - idNumber={index} - proposal={proposal} - > -
-

{t('ayes ({{ayes}}/{{threshold}} to approve)', { - replace: { - ayes: ayes.length, - threshold: threshold.toString() - } - })}

- {ayes.map((address, index): React.ReactNode => ( - - - - ))} -

{t('nays ({{nays}})', { - replace: { - nays: nays.length - } - })}

- {nays.map((address, index): React.ReactNode => ( - - - - ))} -
-
- ); -} - -export default withMulti( - Motion, - translate, - withCalls( - ['query.council.proposalOf', { - paramName: 'hash', - propName: 'proposal', - transform: (value: Option): ProposalType | null => - value.unwrapOr(null) - }], - ['query.council.voting', { - paramName: 'hash', - propName: 'votes', - transform: (value: Option): Votes | null => - value.unwrapOr(null) - }] - ) -); diff --git a/pioneer/packages/app-council/src/Motions/Propose.tsx b/pioneer/packages/app-council/src/Motions/Propose.tsx deleted file mode 100644 index 13ece235ac..0000000000 --- a/pioneer/packages/app-council/src/Motions/Propose.tsx +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2017-2019 @polkadot/ui-staking authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { ApiProps } from '@polkadot/react-api/types'; -import { Call, Proposal } from '@polkadot/types/interfaces'; - -import BN from 'bn.js'; -import React from 'react'; -import { createType } from '@polkadot/types'; -import { Button, Extrinsic, InputNumber } from '@polkadot/react-components'; -import TxModal, { TxModalState, TxModalProps } from '@polkadot/react-components/TxModal'; -import { withCalls, withMulti } from '@polkadot/react-api'; - -import translate from '../translate'; - -interface Props extends TxModalProps, ApiProps { - memberCount: number; -} - -interface State extends TxModalState { - method: Call | null; - threshold: BN | null; -} - -class Propose extends TxModal { - constructor (props: Props) { - super(props); - - this.defaultState = { - ...this.defaultState, - method: null, - threshold: props.memberCount ? new BN((props.memberCount / 2) + 1) : null - }; - this.state = this.defaultState; - } - - public static getDerivedStateFromProps ({ memberCount }: Props, { threshold }: State): Pick | null { - if (!threshold && memberCount > 0) { - const simpleMajority = new BN((memberCount / 2) + 1); - - return { threshold: simpleMajority }; - } - - return null; - } - - protected headerText = (): string => this.props.t('Propose a council motion'); - - protected txMethod = (): string => 'council.propose'; - - protected txParams = (): [BN | null, ...Proposal[]] => { - const { method, threshold } = this.state; - - return [ - threshold, - ...(method ? [createType('Proposal', method)] : []) - ]; - } - - protected isDisabled = (): boolean => { - const { memberCount = 0 } = this.props; - const { accountId, method, threshold } = this.state; - - const hasThreshold = !!threshold && threshold.gtn(0) && threshold.ltn(memberCount + 1); - const hasMethod = !!method; - - return !accountId || !hasMethod || !hasThreshold; - } - - protected renderTrigger = (): React.ReactNode => { - const { t } = this.props; - - return ( - - + ); + } + + private maxValue (bitLength?: number): BN { + return new BN(2).pow(new BN(bitLength || DEFAULT_BITLENGTH)).subn(1); + } + + private isValidBitLength (value: BN, bitLength?: number): boolean { + return value.bitLength() <= (bitLength || DEFAULT_BITLENGTH); + } + + private isValidNumber (input: BN, bitLength: number = DEFAULT_BITLENGTH): boolean { + const { maxValue, withMax } = this.props; + const maxBN = this.maxValue(bitLength); + + if ( + input.lt(new BN(0)) || + !input.lt(maxBN) || + !this.isValidBitLength(input, bitLength) || + (withMax && maxValue !== undefined && maxValue.gtn(0) && input.gt(maxValue)) + ) { + return false; + } + + return true; + } + + private regex = (): RegExp => { + const { isDecimal, isSi } = this.props; + return new RegExp( + (isSi || isDecimal) + ? `^(0|[1-9]\\d*)(\\${KEYS.DECIMAL}\\d*)?$` + : '^(0|[1-9]\\d*)$' + ); + } + + private onChange = (value: string): void => { + const { bitLength, onChange } = this.props; + const { siUnit } = this.state; + + try { + const valueBN = this.inputValueToBn(value, siUnit); + const isValid = this.isValidNumber(valueBN, bitLength); + + this.setState({ isValid, value, valueBN }); + + onChange && onChange( + isValid + ? valueBN + : undefined + ); + } catch (error) { + console.error(error); + } + } + + private onKeyDown = (event: React.KeyboardEvent): void => { + const { isPreKeyDown } = this.state; + + if (KEYS_PRE.includes(event.key)) { + this.setState({ isPreKeyDown: true }); + return; + } + + if (event.key.length === 1 && !isPreKeyDown) { + const { selectionStart: i, selectionEnd: j, value } = event.target as HTMLInputElement; + const newValue = `${value.substring(0, i || 0)}${event.key}${value.substring(j || 0)}`; + + if (!this.regex().test(newValue)) { + event.preventDefault(); + } + } + } + + private onKeyUp = (event: React.KeyboardEvent): void => { + if (KEYS_PRE.includes(event.key)) { + this.setState({ isPreKeyDown: false }); + } + } + + private onPaste = (event: React.ClipboardEvent): void => { + const { value: newValue } = event.target as HTMLInputElement; + + if (!this.regex().test(newValue)) { + event.preventDefault(); + } + } + + private selectSiUnit = (siUnit: string): void => { + this.setState((prevState: State): Pick => { + const { bitLength, onChange } = this.props; + const valueBN = this.inputValueToBn(prevState.value, siUnit); + const isValid = this.isValidNumber(valueBN, bitLength); + + onChange && onChange( + isValid + ? prevState.valueBN + : undefined + ); + + return { + isValid, + siUnit, + valueBN + }; + }); + } + + private setToMaxValue = (): void => { + this.setState((prevState: State): Pick => { + const { bitLength, maxValue, onChange } = this.props; + const { siUnit = prevState.siUnit } = this.state; + + if (!maxValue) { + return {}; + } + + const isValid = this.isValidNumber(maxValue, bitLength); + + onChange && onChange( + isValid + ? maxValue + : undefined + ); + + return { + value: this.bnToInputValue(maxValue, siUnit), + valueBN: maxValue, + isValid + }; + }); + } + + private inputValueToBn = (value: string, siUnit?: string): BN => { + const [siPower, basePower, siUnitPower] = this.getSiPowers(siUnit); + + // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec + const isDecimalValue = value.match(/^(\d+)\.(\d+)$/); + + if (isDecimalValue) { + if (siUnitPower - isDecimalValue[2].length < -basePower) { + return new BN(-1); + } + + const div = new BN(value.replace(/\.\d*$/, '')); + const modString = value.replace(/^\d+\./, ''); + const mod = new BN(modString); + + return div + .mul(TEN.pow(siPower)) + .add(mod.mul(TEN.pow(new BN(basePower + siUnitPower - modString.length)))); + } else { + return new BN(value.replace(/[^\d]/g, '')) + .mul(TEN.pow(siPower)); + } + } + + private bnToInputValue = (bn: BN, siUnit?: string): string => { + const [siPower] = this.getSiPowers(siUnit); + + const base = TEN.pow(siPower); + const div = bn.div(base); + const mod = bn.mod(base); + + return `${ + div.gt(ZERO) ? div.toString() : '0' + }${ + mod.gt(ZERO) + ? ((): string => { + const padding = Math.max( + mod.toString().length, + base.toString().length - div.toString().length, + bn.toString().length - div.toString().length + ); + + return `.${mod.toString(10, padding).replace(/0*$/, '')}`; + })() + : '' + }`; + } + + private getSiPowers = (siUnit = this.state.siUnit): [BN, number, number] => { + const { isSi } = this.props; + + const basePower = isSi ? formatBalance.getDefaults().decimals : 0; + const siUnitPower = isSi ? formatBalance.findSi(siUnit).power : 0; + + return [new BN(basePower + siUnitPower), basePower, siUnitPower]; + } +} + +export { + InputNumber +}; + +export default translate(InputNumber); diff --git a/pioneer/packages/old-apps/react-components/src/InputRpc/SelectMethod.tsx b/pioneer/packages/old-apps/react-components/src/InputRpc/SelectMethod.tsx new file mode 100644 index 0000000000..27b2fb4e66 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputRpc/SelectMethod.tsx @@ -0,0 +1,48 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { RpcMethod } from '@polkadot/jsonrpc/types'; +import { DropdownOptions } from '../util/types'; +import { BareProps } from '../types'; + +import React from 'react'; + +import map from '@polkadot/jsonrpc'; + +import Dropdown from '../Dropdown'; +import { classes } from '../util'; + +interface Props extends BareProps { + isError?: boolean; + onChange: (value: RpcMethod) => void; + options: DropdownOptions; + value: RpcMethod; +} + +function transform ({ value }: Props): (method: string) => RpcMethod { + return function (method: string): RpcMethod { + return map[value.section].methods[method]; + }; +} + +export default function SelectMethod (props: Props): React.ReactElement | null { + const { className, isError, onChange, options, style, value } = props; + + if (!options.length) { + return null; + } + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputRpc/SelectSection.tsx b/pioneer/packages/old-apps/react-components/src/InputRpc/SelectSection.tsx new file mode 100644 index 0000000000..68fde3e09a --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputRpc/SelectSection.tsx @@ -0,0 +1,35 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { RpcMethod } from '@polkadot/jsonrpc/types'; +import { DropdownOptions } from '../util/types'; +import { BareProps } from '../types'; + +import React from 'react'; + +import Dropdown from '../Dropdown'; +import { classes } from '../util'; + +interface Props extends BareProps { + defaultValue?: string; + isError?: boolean; + onChange: (value: string) => void; + options: DropdownOptions; + value: RpcMethod; +} + +export default function SelectSection ({ className, defaultValue, isError, onChange, options, style, value }: Props): React.ReactElement { + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputRpc/index.tsx b/pioneer/packages/old-apps/react-components/src/InputRpc/index.tsx new file mode 100644 index 0000000000..bbace3b9a0 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputRpc/index.tsx @@ -0,0 +1,88 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +// TODO: We have a lot shared between this and InputExtrinsic & InputStorage + +import { RpcMethod } from '@polkadot/jsonrpc/types'; +import { DropdownOptions } from '../util/types'; +import { I18nProps } from '../types'; + +import '../InputExtrinsic/InputExtrinsic.css'; + +import React, { useContext, useState } from 'react'; +import map from '@polkadot/jsonrpc'; +import { ApiContext } from '@polkadot/react-api'; + +import Labelled from '../Labelled'; +import translate from '../translate'; +import SelectMethod from './SelectMethod'; +import SelectSection from './SelectSection'; +import methodOptions from './options/method'; +import sectionOptions from './options/section'; + +interface Props extends I18nProps { + defaultValue: RpcMethod; + help?: React.ReactNode; + isError?: boolean; + label: React.ReactNode; + onChange?: (value: RpcMethod) => void; + withLabel?: boolean; +} + +function InputRpc ({ className, defaultValue, help, label, onChange, style, withLabel }: Props): React.ReactElement { + const { api } = useContext(ApiContext); + const [optionsMethod, setOptionsMethod] = useState(methodOptions(api, defaultValue.section)); + const [optionsSection] = useState(sectionOptions(api)); + const [value, setValue] = useState((): RpcMethod => defaultValue); + + const _onMethodChange = (newValue: RpcMethod): void => { + if (value.section === newValue.section && value.method === newValue.method) { + return; + } + + // set via callback since the method is a function itself + setValue((): RpcMethod => newValue); + onChange && onChange(newValue); + }; + const _onSectionChange = (section: string): void => { + if (section === value.section) { + return; + } + + const optionsMethod = methodOptions(api, section); + + setOptionsMethod(optionsMethod); + _onMethodChange(map[section].methods[optionsMethod[0].value]); + }; + + return ( +
+ +
+ + +
+
+
+ ); +} + +export default translate(InputRpc); diff --git a/pioneer/packages/old-apps/react-components/src/InputRpc/options/method.tsx b/pioneer/packages/old-apps/react-components/src/InputRpc/options/method.tsx new file mode 100644 index 0000000000..7ef4630c7c --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputRpc/options/method.tsx @@ -0,0 +1,50 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { DropdownOption, DropdownOptions } from '../../util/types'; + +import React from 'react'; +import ApiPromise from '@polkadot/api/promise'; +import map from '@polkadot/jsonrpc'; + +export default function createOptions (api: ApiPromise, sectionName: string): DropdownOptions { + const section = map[sectionName]; + + if (!section || Object.keys((api.rpc as any)[sectionName]).length === 0) { + return []; + } + + return Object + .keys((api.rpc as any)[sectionName]) + .sort() + .filter((value): boolean => { + const { isDeprecated, isHidden, isSubscription } = section.methods[value]; + + return !isDeprecated && !isHidden && !isSubscription; + }) + .map((value): DropdownOption => { + const { description, params } = section.methods[value]; + const inputs = params.map(({ name }): string => name).join(', '); + + return { + className: 'ui--DropdownLinked-Item', + key: `${sectionName}_${value}`, + text: [ +
+ {value}({inputs}) +
, +
+ {description || value} +
+ ], + value + }; + }); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputRpc/options/section.ts b/pioneer/packages/old-apps/react-components/src/InputRpc/options/section.ts new file mode 100644 index 0000000000..417e21ae5c --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputRpc/options/section.ts @@ -0,0 +1,18 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { DropdownOptions } from '../../util/types'; + +import ApiPromise from '@polkadot/api/promise'; + +export default function createOptions (api: ApiPromise): DropdownOptions { + return Object + .keys(api.rpc) + .sort() + .filter((section): boolean => Object.keys((api.rpc as any)[section]).length !== 0) + .map((name): { text: string; value: string } => ({ + text: name, + value: name + })); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputStorage/SelectKey.tsx b/pioneer/packages/old-apps/react-components/src/InputStorage/SelectKey.tsx new file mode 100644 index 0000000000..9cebedb87d --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputStorage/SelectKey.tsx @@ -0,0 +1,51 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { DropdownOptions } from '../util/types'; +import { BareProps } from '../types'; +import { StorageEntryPromise } from './types'; + +import React, { useContext } from 'react'; +import { ApiPromise } from '@polkadot/api'; +import { ApiContext } from '@polkadot/react-api'; + +import Dropdown from '../Dropdown'; +import { classes } from '../util'; + +interface Props extends BareProps { + isError?: boolean; + onChange: (value: StorageEntryPromise) => void; + options: DropdownOptions; + value: StorageEntryPromise; +} + +function transform (api: ApiPromise, { value }: Props): (method: string) => StorageEntryPromise { + return function (method: string): StorageEntryPromise { + return api.query[value.creator.section] + ? api.query[value.creator.section][method] + : value; + }; +} + +export default function SelectKey (props: Props): React.ReactElement | null { + const { api } = useContext(ApiContext); + const { className, isError, onChange, options, style, value } = props; + + if (!options.length) { + return null; + } + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputStorage/SelectSection.tsx b/pioneer/packages/old-apps/react-components/src/InputStorage/SelectSection.tsx new file mode 100644 index 0000000000..6578e0d86e --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputStorage/SelectSection.tsx @@ -0,0 +1,35 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { DropdownOptions } from '../util/types'; +import { BareProps } from '../types'; +import { StorageEntryPromise } from './types'; + +import React from 'react'; + +import Dropdown from '../Dropdown'; +import { classes } from '../util'; + +interface Props extends BareProps { + defaultValue?: StorageEntryPromise; + isError?: boolean; + onChange: (value: string) => void; + options: DropdownOptions; + value: StorageEntryPromise; +} + +export default function SelectSection ({ className, defaultValue, isError, onChange, options, style, value: { creator: { section } } }: Props): React.ReactElement { + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputStorage/index.tsx b/pioneer/packages/old-apps/react-components/src/InputStorage/index.tsx new file mode 100644 index 0000000000..04bb2669f2 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputStorage/index.tsx @@ -0,0 +1,87 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +// TODO: We have a lot shared between this and InputExtrinsic + +import { DropdownOptions } from '../util/types'; +import { I18nProps } from '../types'; +import { StorageEntryPromise } from './types'; + +import '../InputExtrinsic/InputExtrinsic.css'; + +import React, { useContext, useState } from 'react'; +import { ApiContext } from '@polkadot/react-api'; + +import Labelled from '../Labelled'; +import translate from '../translate'; +import SelectKey from './SelectKey'; +import SelectSection from './SelectSection'; +import keyOptions from './options/key'; +import sectionOptions from './options/section'; + +interface Props extends I18nProps { + defaultValue: StorageEntryPromise; + help?: React.ReactNode; + isError?: boolean; + label: React.ReactNode; + onChange?: (value: StorageEntryPromise) => void; + withLabel?: boolean; +} + +function InputStorage ({ className, defaultValue, help, label, onChange, style, withLabel }: Props): React.ReactElement { + const { api } = useContext(ApiContext); + const [optionsMethod, setOptionsMethod] = useState(keyOptions(api, defaultValue.creator.section)); + const [optionsSection] = useState(sectionOptions(api)); + const [value, setValue] = useState((): StorageEntryPromise => defaultValue); + + const _onKeyChange = (newValue: StorageEntryPromise): void => { + if (value.creator.section === newValue.creator.section && value.creator.method === newValue.creator.method) { + return; + } + + // set via callback + setValue((): StorageEntryPromise => newValue); + onChange && onChange(newValue); + }; + const _onSectionChange = (section: string): void => { + if (section === value.creator.section) { + return; + } + + const optionsMethod = keyOptions(api, section); + + setOptionsMethod(optionsMethod); + _onKeyChange(api.query[section][optionsMethod[0].value]); + }; + + return ( +
+ +
+ + +
+
+
+ ); +} + +export default translate(InputStorage); diff --git a/pioneer/packages/old-apps/react-components/src/InputStorage/options/key.tsx b/pioneer/packages/old-apps/react-components/src/InputStorage/options/key.tsx new file mode 100644 index 0000000000..07ad690ca8 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputStorage/options/key.tsx @@ -0,0 +1,62 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { StorageEntry } from '@polkadot/types/primitive/StorageKey'; +import { DropdownOptions, DropdownOption } from '../../util/types'; + +import React from 'react'; +import ApiPromise from '@polkadot/api/promise'; + +export default function createOptions (api: ApiPromise, sectionName: string): DropdownOptions { + const section = api.query[sectionName]; + + if (!section || Object.keys(section).length === 0) { + return []; + } + + return Object + .keys(section) + .sort() + .map((value): DropdownOption => { + const method = section[value] as unknown as StorageEntry; + const type = method.meta.type; + let input = ''; + + if (type.isMap) { + input = type.asMap.key.toString(); + } else if (type.isDoubleMap) { + input = type.asDoubleMap.key1.toString() + ', ' + type.asDoubleMap.key2.toString(); + } + + let output = type.toString(); + + if (type.isDoubleMap) { + output = type.asDoubleMap.value.toString(); + } + + if (method.meta.modifier.isOptional) { + output = `Option<${output}>`; + } + + return { + className: 'ui--DropdownLinked-Item', + key: `${sectionName}_${value}`, + text: [ +
+ {value}({input}): {output} +
, +
+ {(method.meta.documentation[0] || method.meta.name).toString()} +
+ ], + value + }; + }); +} diff --git a/pioneer/packages/old-apps/react-components/src/InputStorage/options/section.ts b/pioneer/packages/old-apps/react-components/src/InputStorage/options/section.ts new file mode 100644 index 0000000000..203a6151b9 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputStorage/options/section.ts @@ -0,0 +1,18 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { DropdownOptions } from '../../util/types'; + +import ApiPromise from '@polkadot/api/promise'; + +export default function createOptions (api: ApiPromise): DropdownOptions { + return Object + .keys(api.query) + .sort() + .filter((name): number => Object.keys(api.query[name]).length) + .map((name): { text: string; value: string } => ({ + text: name, + value: name + })); +} diff --git a/pioneer/packages/react-components/src/InputStorage/types.ts b/pioneer/packages/old-apps/react-components/src/InputStorage/types.ts similarity index 100% rename from pioneer/packages/react-components/src/InputStorage/types.ts rename to pioneer/packages/old-apps/react-components/src/InputStorage/types.ts diff --git a/pioneer/packages/old-apps/react-components/src/InputTags.tsx b/pioneer/packages/old-apps/react-components/src/InputTags.tsx new file mode 100644 index 0000000000..061b070ce3 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/InputTags.tsx @@ -0,0 +1,79 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React from 'react'; +import store from 'store'; + +import Dropdown from './Dropdown'; + +interface Option { + key: string; + text: string; + value: string; +} + +interface Props extends BareProps { + allowAdd?: boolean; + defaultValue?: string[]; + help?: React.ReactNode; + isDisabled?: boolean; + isError?: boolean; + label?: React.ReactNode; + onBlur?: () => void; + onChange?: (value: string[]) => void; + onClose?: () => void; + openOnFocus?: boolean; + placeholder?: string; + searchInput?: {autoFocus: boolean}; + value?: string[]; + withLabel?: boolean; +} + +function loadTags (): string[] { + return store.get('tags') || ['Default']; +} + +function valueToOption (value: string): Option { + return { key: value, text: value, value }; +} + +const tags = loadTags(); +const options = tags.map(valueToOption); + +function saveTags (tags: string[]): void { + store.set('tags', tags); +} + +function onAddTag (value: string): void { + tags.push(value); + options.push(valueToOption(value)); + + saveTags(tags); +} + +export default function InputTags ({ className, defaultValue, help, isDisabled, isError, label, onBlur, onChange, onClose, placeholder, searchInput, value, withLabel }: Props): React.ReactElement { + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Inset.tsx b/pioneer/packages/old-apps/react-components/src/Inset.tsx new file mode 100644 index 0000000000..99096a3890 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Inset.tsx @@ -0,0 +1,154 @@ +// Copyright 2017-2019 @polkadot/app-democracy authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import React, { useState } from 'react'; +import { RouteComponentProps } from 'react-router'; +import { withRouter } from 'react-router-dom'; +import styled from 'styled-components'; + +import Icon from './Icon'; +import { classes } from './util'; + +export interface InsetProps extends RouteComponentProps { + className?: string; + children?: React.ReactNode; + isCollapsible?: boolean; + isError?: boolean; + isSuccess?: boolean; + header?: React.ReactNode; + href?: string | null; + withTopMargin?: boolean; + withBottomMargin?: boolean; +} + +function Inset ({ children, className, header, history, href, isCollapsible, isError, isSuccess, withBottomMargin, withTopMargin }: InsetProps): React.ReactElement | null { + const [isCollapsed, setIsCollapsed] = useState(true); + + if (!children) { + return null; + } + + const _onClick = (): void => { + href && history.push(href); + }; + const _toggleCollapsed = (): void => setIsCollapsed(!isCollapsed); + + return ( +
+ {isCollapsible && ( +
+

{header}

+ +
+ )} +
+ {children} +
+
+ ); +} + +export default withRouter( + styled(Inset)` + & { + box-shadow: 0 3px 3px rgba(0,0,0,.2); + position: relative; + background: #fefefe; + padding: 1rem; + transition: all 0.2s; + display: flex; + flex-direction: column; + + &.bottom-margin { + margin-bottom: 2rem; + } + + &.top-margin { + margin-top: 2rem; + } + + &.error { + background: rgba(255, 0, 0, 0.05); + + &, h1, h2, h3, h4, h5, h6, p { + color: rgba(156, 0, 0) !important; + } + } + + &.success { + border: 1px solid rgb(168, 255, 136); + background: rgba(0, 255, 0, 0.05); + + &, h1, h2, h3, h4, h5, h6, p { + color: rgba(34, 125, 0) !important; + } + } + + .header { + cursor: pointer; + height: 2rem; + width: 100%; + + h3 { + line-height: 2rem; + margin-bottom: 0; + } + + .icon { + height: 4rem; + width: 4rem; + font-size: 2rem; + color: rgba(0,0,0,0.35); + position: absolute; + right: 0; + top: 0; + line-height: 4rem; + transition: all 0.2s; + transform-origin: center center; + + &.collapsed { + transform: rotate(180deg); + } + } + } + + .children { + &.collapsed { + display: none; + } + } + + &.as-link { + cursor: pointer; + + &:hover { + box-shadow: 0 5px 5px rgba(0,0,0,.2); + transform: translateY(-2px); + } + } + } + ` +); diff --git a/pioneer/packages/old-apps/react-components/src/Label.tsx b/pioneer/packages/old-apps/react-components/src/Label.tsx new file mode 100644 index 0000000000..35b677835f --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Label.tsx @@ -0,0 +1,27 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React from 'react'; + +import LabelHelp from './LabelHelp'; + +interface Props extends BareProps { + help?: React.ReactNode; + label?: React.ReactNode; + withEllipsis?: boolean; +} + +export default function Label ({ className, help, label, withEllipsis }: Props): React.ReactElement { + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/LabelHelp.tsx b/pioneer/packages/old-apps/react-components/src/LabelHelp.tsx new file mode 100644 index 0000000000..f51f07d57b --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/LabelHelp.tsx @@ -0,0 +1,50 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React, { useState } from 'react'; +import styled from 'styled-components'; + +import Icon from './Icon'; +import { classes } from './util'; +import Tooltip from './Tooltip'; + +interface Props extends BareProps { + help: React.ReactNode; +} + +function LabelHelp ({ className, help, style }: Props): React.ReactElement { + const [isTooltipOpen, setIsTooltipOpen] = useState(false); + + const _toggleTooltip = (): void => setIsTooltipOpen(!isTooltipOpen); + + return ( +
+ + {isTooltipOpen && ( + + )} +
+ ); +} + +export default styled(LabelHelp)` + cursor: help; + display: inline-block; + line-height: 1rem; + margin: 0 0 0 0.25rem; +`; diff --git a/pioneer/packages/old-apps/react-components/src/Labelled.tsx b/pioneer/packages/old-apps/react-components/src/Labelled.tsx new file mode 100644 index 0000000000..19efba442e --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Labelled.tsx @@ -0,0 +1,153 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React from 'react'; +import styled from 'styled-components'; + +import LabelHelp from './LabelHelp'; +import { classes } from './util'; + +interface Props extends BareProps { + help?: React.ReactNode; + isHidden?: boolean; + isOuter?: boolean; + isSmall?: boolean; + label?: React.ReactNode; + labelExtra?: React.ReactNode; + children: React.ReactNode; + withEllipsis?: boolean; + withLabel?: boolean; +} + +const defaultLabel: React.ReactNode = ( +
 
+); + +const Wrapper = styled.div` + display: block; + position: relative; + + .withEllipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &.label-small { + display: block; + + > label { + margin: 0; + min-width: 0; + padding-right: 0; + } + } + + &:not(.label-small) { + padding-left: 2rem; + + &:not(.label-outer) { + > label, + .labelExtra { + position: absolute; + text-align: left; + top: 0.5rem; + z-index: 1; + } + + > label { + left: 3.55rem; + text-align: left; + } + } + + .labelExtra { + color: rgba(78, 78, 78, .85); + font-weight: 100; + right: 1.75rem; + text-align: right; + } + + > .ui--Labelled-content { + box-sizing: border-box; + flex: 1 1; + min-width: 0; + + .ui.selection.dropdown { + &:not(.floating) { + padding-left: 1.45rem; + padding-top: 1.75rem; + } + + &.floating { + > .dropdown.icon { + top: 1.25rem; + } + + .text { + padding: 0.45rem 0 + } + } + + &.search:not(.multiple) > input.search { + padding-left: 1.45rem; + padding-top: 1.75rem; + } + + > .delete.icon, + > .dropdown.icon, + > .search.icon { + top: 1.75rem; + } + } + + .ui.input > input, + .ui--output { + padding-left: 1.45rem; + padding-top: 1.75rem; + } + + .ui--InputFile, + .ui--Messages { + padding-left: 1.45rem; + padding-top: 2rem; + } + + .ui--Messages { + padding-bottom: 2rem; + } + } + } +`; + +export default function Labelled ({ className, children, help, isHidden, isOuter, isSmall, label = defaultLabel, labelExtra, style, withEllipsis, withLabel = true }: Props): React.ReactElement | null { + if (isHidden) { + return null; + } else if (!withLabel) { + return ( +
{children}
+ ); + } + + return ( + + + {labelExtra &&
{labelExtra}
} +
+ {children} +
+
+ ); +} diff --git a/pioneer/packages/react-components/src/LinkPolkascan.tsx b/pioneer/packages/old-apps/react-components/src/LinkPolkascan.tsx similarity index 100% rename from pioneer/packages/react-components/src/LinkPolkascan.tsx rename to pioneer/packages/old-apps/react-components/src/LinkPolkascan.tsx diff --git a/pioneer/packages/old-apps/react-components/src/LockedVote.tsx b/pioneer/packages/old-apps/react-components/src/LockedVote.tsx new file mode 100644 index 0000000000..e9ba593493 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/LockedVote.tsx @@ -0,0 +1,34 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces'; +import { BareProps } from './types'; + +import React from 'react'; +import { LockedVote } from '@polkadot/react-query'; + +import { classes } from './util'; + +export interface Props extends BareProps { + label?: React.ReactNode; + params?: AccountId | AccountIndex | Address | string | Uint8Array | null; + withLabel?: boolean; +} + +export default function LockedVoteDisplay (props: Props): React.ReactElement | null { + const { params, className, label, style } = props; + + if (!params) { + return null; + } + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Menu.tsx b/pioneer/packages/old-apps/react-components/src/Menu.tsx new file mode 100644 index 0000000000..952ef5d1ec --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Menu.tsx @@ -0,0 +1,16 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import SUIDivider from 'semantic-ui-react/dist/commonjs/elements/Divider/Divider'; +import SUIMenu from 'semantic-ui-react/dist/commonjs/collections/Menu/Menu'; + +type MenuDef = typeof SUIMenu & { + Divider: typeof SUIDivider; +}; + +const Menu: MenuDef = SUIMenu as MenuDef; + +Menu.Divider = SUIDivider; + +export default Menu; diff --git a/pioneer/packages/react-components/src/MessageSignature.tsx b/pioneer/packages/old-apps/react-components/src/MessageSignature.tsx similarity index 100% rename from pioneer/packages/react-components/src/MessageSignature.tsx rename to pioneer/packages/old-apps/react-components/src/MessageSignature.tsx diff --git a/pioneer/packages/react-components/src/Messages.tsx b/pioneer/packages/old-apps/react-components/src/Messages.tsx similarity index 100% rename from pioneer/packages/react-components/src/Messages.tsx rename to pioneer/packages/old-apps/react-components/src/Messages.tsx diff --git a/pioneer/packages/react-components/src/Modal.tsx b/pioneer/packages/old-apps/react-components/src/Modal.tsx similarity index 100% rename from pioneer/packages/react-components/src/Modal.tsx rename to pioneer/packages/old-apps/react-components/src/Modal.tsx diff --git a/pioneer/packages/old-apps/react-components/src/Nonce.tsx b/pioneer/packages/old-apps/react-components/src/Nonce.tsx new file mode 100644 index 0000000000..1f780a69ae --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Nonce.tsx @@ -0,0 +1,31 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces'; +import { BareProps } from './types'; + +import React from 'react'; +import { Nonce } from '@polkadot/react-query'; + +import { classes } from './util'; + +export interface Props extends BareProps { + label?: React.ReactNode; + params?: AccountId | AccountIndex | Address | string | Uint8Array | null; +} + +export default function NonceDisplay ({ className, label, params, style }: Props): React.ReactElement | null { + if (!params) { + return null; + } + + return ( + + ); +} diff --git a/pioneer/packages/react-components/src/OnlineStatus.tsx b/pioneer/packages/old-apps/react-components/src/OnlineStatus.tsx similarity index 100% rename from pioneer/packages/react-components/src/OnlineStatus.tsx rename to pioneer/packages/old-apps/react-components/src/OnlineStatus.tsx diff --git a/pioneer/packages/old-apps/react-components/src/Output.tsx b/pioneer/packages/old-apps/react-components/src/Output.tsx new file mode 100644 index 0000000000..e9c15e9d19 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Output.tsx @@ -0,0 +1,51 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React from 'react'; + +import CopyButton from './CopyButton'; +import Labelled from './Labelled'; +import { classes } from './util'; + +interface Props extends BareProps { + children?: React.ReactNode; + help?: React.ReactNode; + isError?: boolean; + isHidden?: boolean; + isMonospace?: boolean; + label?: React.ReactNode; + value?: any; + withCopy?: boolean; + withLabel?: boolean; +} + +export default function Output ({ className, children, help, isError, isHidden, isMonospace, label, style, value, withCopy = false, withLabel }: Props): React.ReactElement { + return ( + +
+ {value} + {children} + { + withCopy + ? ( + + ) + : null + } +
+
+ ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Params/Call.tsx b/pioneer/packages/old-apps/react-components/src/Params/Call.tsx new file mode 100644 index 0000000000..be3511fb5c --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Params/Call.tsx @@ -0,0 +1,38 @@ +// Copyright 2017-2019 @polkadot/app-extrinsics authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { SubmittableExtrinsicFunction } from '@polkadot/api/types'; +import { Props } from '@polkadot/react-params/types'; + +import React, { useContext } from 'react'; +import { ApiContext } from '@polkadot/react-api'; + +import Extrinsic from './Extrinsic'; + +export default function Call ({ className, isDisabled, isError, label, onChange, onEnter, style, withLabel }: Props): React.ReactElement { + const { api, apiDefaultTx } = useContext(ApiContext); + + const defaultValue = ((): SubmittableExtrinsicFunction<'promise'> => { + try { + return api.tx.balances.transfer; + } catch (error) { + return apiDefaultTx; + } + })(); + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Params/Extrinsic.tsx b/pioneer/packages/old-apps/react-components/src/Params/Extrinsic.tsx new file mode 100644 index 0000000000..8c10e5f182 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Params/Extrinsic.tsx @@ -0,0 +1,51 @@ +// Copyright 2017-2019 @polkadot/app-extrinsics authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Call } from '@polkadot/types/interfaces'; +import { CallFunction } from '@polkadot/types/types'; +import { RawParamOnChange, RawParamOnEnter } from '@polkadot/react-params/types'; +import { BareProps } from '../types'; + +import React from 'react'; + +import BaseExtrinsic from '../Extrinsic'; + +interface Props extends BareProps { + defaultValue: CallFunction; + isDisabled?: boolean; + isError?: boolean; + isPrivate: boolean; + label: React.ReactNode; + onChange?: RawParamOnChange; + onEnter?: RawParamOnEnter; + withLabel?: boolean; +} + +function onChange ({ onChange }: Props): (method?: Call) => void { + return (method?: Call): void => { + onChange && onChange({ + isValid: !!method, + value: method + }); + }; +} + +export default function ExtrinsicDisplay (props: Props): React.ReactElement { + const { className, defaultValue, isDisabled, isError, isPrivate, label, onEnter, style, withLabel } = props; + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Params/Proposal.tsx b/pioneer/packages/old-apps/react-components/src/Params/Proposal.tsx new file mode 100644 index 0000000000..4e098295cc --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Params/Proposal.tsx @@ -0,0 +1,46 @@ +// Copyright 2017-2019 @polkadot/app-extrinsics authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Props, RawParam } from '@polkadot/react-params/types'; + +import React, { useContext } from 'react'; +import { createType } from '@polkadot/types'; +import { ApiContext } from '@polkadot/react-api'; + +import ExtrinsicDisplay from './Extrinsic'; + +function onChange ({ onChange }: Props): (_: RawParam) => void { + return function ({ isValid, value }: RawParam): void { + let proposal = null; + + if (isValid && value) { + proposal = createType('Proposal', value); + } + + onChange && onChange({ + isValid, + value: proposal + }); + }; +} + +export default function ProposalDisplay (props: Props): React.ReactElement { + const { apiDefaultTxSudo } = useContext(ApiContext); + const { className, isDisabled, isError, label, onEnter, style, withLabel } = props; + + return ( + + ); +} diff --git a/pioneer/packages/old-apps/react-components/src/Params/index.ts b/pioneer/packages/old-apps/react-components/src/Params/index.ts new file mode 100644 index 0000000000..a5825b750d --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Params/index.ts @@ -0,0 +1,15 @@ +// Copyright 2017-2019 @polkadot/app-extrinsics authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { ComponentMap } from '@polkadot/react-params/types'; + +import Call from './Call'; +import Proposal from './Proposal'; + +const components: ComponentMap = { + Call, + Proposal +}; + +export default components; diff --git a/pioneer/packages/old-apps/react-components/src/Password.tsx b/pioneer/packages/old-apps/react-components/src/Password.tsx new file mode 100644 index 0000000000..66ac174923 --- /dev/null +++ b/pioneer/packages/old-apps/react-components/src/Password.tsx @@ -0,0 +1,71 @@ +// Copyright 2017-2019 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { BareProps } from './types'; + +import React, { useState } from 'react'; +import { MAX_PASS_LEN } from '@polkadot/ui-keyring/defaults'; + +import { classes } from './util'; +import Button from './Button'; +import Input from './Input'; + +interface Props extends BareProps { + autoFocus?: boolean; + children?: React.ReactNode; + defaultValue?: any; + help?: string; + isDisabled?: boolean; + isError?: boolean; + label?: string; + name?: string; + onChange: (value: string) => void; + onEnter?: () => void; + tabIndex?: number; + value: any; + withLabel?: boolean; +} + +export default function Password ({ autoFocus, children, className, defaultValue, help, isDisabled, isError, label, name, onChange, onEnter, style, tabIndex, value, withLabel }: Props): React.ReactElement { + const [isVisible, setIsVisible] = useState(false); + + const _toggleVisible = (): void => setIsVisible(!isVisible); + + return ( + +