From 69bc18d053d3e42f889e8198d2dc80d85a3e2e51 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 3 Oct 2019 09:54:27 +0200 Subject: [PATCH] Rework query components (no refs) (#1688) * Rework query components (no refs) * Fix raw storage queries * Alphabetical --- packages/app-storage/src/Query.tsx | 41 +-- packages/app-storage/src/Selection/Consts.tsx | 96 +++---- .../app-storage/src/Selection/Modules.tsx | 250 +++++++----------- packages/app-storage/src/Selection/Raw.tsx | 78 +++--- packages/app-storage/src/index.tsx | 2 +- 5 files changed, 181 insertions(+), 286 deletions(-) diff --git a/packages/app-storage/src/Query.tsx b/packages/app-storage/src/Query.tsx index 27c601b1e5..de5313a039 100644 --- a/packages/app-storage/src/Query.tsx +++ b/packages/app-storage/src/Query.tsx @@ -2,20 +2,20 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { RenderFn, DefaultProps, ComponentRenderer } from '@polkadot/react-api/with/types'; import { I18nProps } from '@polkadot/react-components/types'; +import { ConstValue } from '@polkadot/react-components/InputConsts/types'; import { QueryTypes, StorageEntryPromise, StorageModuleQuery } from './types'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; -import { Compact } from '@polkadot/types'; import { Button, Labelled } from '@polkadot/react-components'; import { withCallDiv } from '@polkadot/react-api'; import valueToText from '@polkadot/react-params/valueToText'; +import { Compact, Data, Option } from '@polkadot/types'; import { isU8a, u8aToHex, u8aToString } from '@polkadot/util'; import translate from './translate'; -import { RenderFn, DefaultProps, ComponentRenderer } from '@polkadot/react-api/with/types'; -import { ConstValue } from '@polkadot/react-components/InputConsts/types'; interface Props extends I18nProps { onRemove: (id: number) => void; @@ -65,16 +65,14 @@ function createComponent (type: string, Component: React.ComponentType, def return { Component, // In order to replace the default component during runtime we can provide a RenderFn to create a new 'plugged' component - render: (createComponent: RenderFn): React.ComponentType => { - return renderHelper(createComponent, defaultProps); - }, + render: (createComponent: RenderFn): React.ComponentType => + renderHelper(createComponent, defaultProps), // In order to modify the parameters which are used to render the default component, we can use this method - refresh: (swallowErrors: boolean, contentShorten: boolean): React.ComponentType => { - return renderHelper( + refresh: (swallowErrors: boolean, contentShorten: boolean): React.ComponentType => + renderHelper( (value: any): React.ReactNode => valueToText(type, value, swallowErrors, contentShorten), defaultProps - ); - } + ) }; } @@ -93,12 +91,23 @@ function getCachedComponent (query: QueryTypes): CacheInstance { } else { const values: any[] = params.map(({ value }): any => value); - // render function to create an element for the query results which is plugged to the api - renderHelper = withCallDiv('subscribe', { - paramName: 'params', - paramValid: true, - params: [key, ...values] - }); + if (isU8a(key)) { + // subscribe to the raw key here + renderHelper = withCallDiv('rpc.state.subscribeStorage', { + paramName: 'params', + paramValid: true, + params: [[key]], + transform: ([data]: Option[]): Option => data + }); + } else { + // render function to create an element for the query results which is plugged to the api + renderHelper = withCallDiv('subscribe', { + paramName: 'params', + paramValid: true, + params: [key, ...values] + }); + } + type = key.creator && key.creator.meta ? typeToString(key) : 'Data'; diff --git a/packages/app-storage/src/Selection/Consts.tsx b/packages/app-storage/src/Selection/Consts.tsx index c119af4a32..61480be0b2 100644 --- a/packages/app-storage/src/Selection/Consts.tsx +++ b/packages/app-storage/src/Selection/Consts.tsx @@ -5,84 +5,54 @@ import { ConstantCodec } from '@polkadot/api-metadata/consts/types'; import { I18nProps } from '@polkadot/react-components/types'; import { ConstValue } from '@polkadot/react-components/InputConsts/types'; -import { ApiProps } from '@polkadot/react-api/types'; import { ComponentProps } from '../types'; -import React from 'react'; -import { Button, InputConsts, TxComponent } from '@polkadot/react-components'; -import { withApi, withMulti } from '@polkadot/react-api'; +import React, { useContext, useState } from 'react'; +import { ApiContext } from '@polkadot/react-api'; +import { Button, InputConsts } from '@polkadot/react-components'; import translate from '../translate'; -interface Props extends ComponentProps, ApiProps, I18nProps {} +interface Props extends ComponentProps, I18nProps {} -interface State { - value: ConstValue; -} - -class Consts extends TxComponent { - private defaultValue: ConstValue; - - public state: State; - - public constructor (props: Props) { - super(props); - - const { api } = this.props; +function Consts ({ onAdd, t }: Props): React.ReactElement { + const { api } = useContext(ApiContext); + const [defaultValue] = useState((): ConstValue => { const section = Object.keys(api.consts)[0]; const method = Object.keys(api.consts[section])[0]; - this.defaultValue = { + return { meta: (api.consts[section][method] as ConstantCodec).meta, method, section }; - this.state = { - value: this.defaultValue - }; - } + }); + const [value, setValue] = useState(defaultValue); - public render (): React.ReactNode { - const { api, t } = this.props; - const { value: { method, section } } = this.state; - const meta = (api.consts[section][method] as ConstantCodec).meta; + const _onAdd = (): void => onAdd({ isConst: true, key: value }); - return ( -
-
- -
-
-
-
- ); - } + const { method, section } = value; + const meta = (api.consts[section][method] as ConstantCodec).meta; - private onAdd = (): void => { - const { onAdd } = this.props; - const { value } = this.state; - - onAdd({ isConst: true, key: value }); - } - - private onChangeConst = (value: ConstValue): void => { - this.setState({ value }); - } + return ( +
+
+ +
+
+
+
+ ); } -export default withMulti( - Consts, - translate, - withApi -); +export default translate(Consts); diff --git a/packages/app-storage/src/Selection/Modules.tsx b/packages/app-storage/src/Selection/Modules.tsx index 5c9d637f30..950e1ef353 100644 --- a/packages/app-storage/src/Selection/Modules.tsx +++ b/packages/app-storage/src/Selection/Modules.tsx @@ -5,181 +5,115 @@ import { TypeDef } from '@polkadot/types/types'; import { I18nProps } from '@polkadot/react-components/types'; import { RawParams } from '@polkadot/react-params/types'; -import { ApiProps } from '@polkadot/react-api/types'; import { ComponentProps, StorageEntryPromise } from '../types'; -import React from 'react'; +import React, { useContext, useState } from 'react'; import { getTypeDef } from '@polkadot/types'; -import { Button, InputStorage, TxComponent } from '@polkadot/react-components'; +import { Button, InputStorage } from '@polkadot/react-components'; import Params from '@polkadot/react-params'; -import { withApi, withMulti } from '@polkadot/react-api'; +import { ApiContext } from '@polkadot/react-api'; import { isNull, isUndefined } from '@polkadot/util'; import translate from '../translate'; -interface Props extends ComponentProps, ApiProps, I18nProps {} +interface Props extends ComponentProps, I18nProps {} -interface State { - isLinked: boolean; - isValid: boolean; - key: StorageEntryPromise; - defaultValues?: RawParams | null; - values: RawParams; - params: { type: TypeDef }[]; +type ParamsType = { type: TypeDef }[]; + +function areParamsValid (values: RawParams): boolean { + return values.reduce( + (isValid: boolean, value): boolean => ( + isValid && + !isUndefined(value) && + !isUndefined(value.value) && + value.isValid), + true + ); } -class Modules extends TxComponent { - private defaultValue: any; +function Modules ({ onAdd, t }: Props): React.ReactElement { + const { api } = useContext(ApiContext); + const [{ defaultValues, isLinked, key, params }, setKey] = useState<{ defaultValues: RawParams | undefined | null; isLinked: boolean; key: StorageEntryPromise; params: ParamsType }>({ defaultValues: undefined, isLinked: false, key: api.query.timestamp.now, params: [] }); + const [{ isValid, values }, setValues] = useState<{ isValid: boolean; values: RawParams }>({ isValid: true, values: [] }); - public state: State; - - public constructor (props: Props) { - super(props); - - const { api } = this.props; - - this.defaultValue = api.query.timestamp.now; - this.state = { - isLinked: false, - isValid: true, - key: this.defaultValue, - values: [], - params: [] - }; - } - - public render (): React.ReactNode { - const { t } = this.props; - const { isValid, key: { creator: { method, section, meta } }, defaultValues, params } = this.state; - - return ( -
-
- - -
-
-
-
- ); - } - - private nextState (newState: Partial): void { - this.setState( - (prevState: State): Pick => { - const { key = prevState.key, values = prevState.values } = newState; - - const areParamsValid = (): boolean => { - return values.reduce( - (isValid: boolean, value): boolean => ( - isValid && - !isUndefined(value) && - !isUndefined(value.value) && - value.isValid), - true - ); - }; - - if (key.creator.meta.type.isDoubleMap) { - const key1 = key.creator.meta.type.asDoubleMap.key1.toString(); - const key2 = key.creator.meta.type.asDoubleMap.key2.toString(); - - return { - defaultValues: this.getDefaultValues(), - isValid: values.length === 2 && areParamsValid(), - key, - params: [ - { type: getTypeDef(key1) }, - { type: getTypeDef(key2) } - ], - values - }; - } - - const isMap = key.creator.meta.type.isMap; - const isLinked = isMap && key.creator.meta.type.asMap.linked.isTrue; - const isValid = values.length === (isMap ? 1 : 0) && areParamsValid(); - - return { - defaultValues: null, - isLinked, - isValid, - key, - params: isMap - ? [{ - type: getTypeDef( - isLinked - ? `Option<${key.creator.meta.type.asMap.key.toString()}>` - : key.creator.meta.type.asMap.key.toString() - ) - }] - : [], - values - }; - } - ); - } - - private getDefaultValues = (): RawParams | null => { - const { api } = this.props; - const { key } = this.state; - - if (key.creator.section === 'session') { - return [ - { - isValid: true, - value: api.consts.session.dedupKeyPrefix.toHex() - } - ]; - } - return null; - } - - private onAdd = (): void => { - const { onAdd } = this.props; - const { isLinked, key, values } = this.state; - - onAdd({ + const _onAdd = (): void => { + isValid && onAdd({ isConst: false, key, params: values.filter(({ value }): boolean => !isLinked || !isNull(value)) }); - } - - private onChangeKey = (key: StorageEntryPromise): void => { - this.nextState({ - isValid: false, - key, - values: [], - params: [] + }; + const _onChangeValues = (values: RawParams): void => { + setValues({ + isValid: ( + key.creator.meta.type.isDoubleMap + ? values.length === 2 + : values.length === (key.creator.meta.type.isMap ? 1 : 0) + ) && areParamsValid(values), + values }); - } + }; + const _onChangeKey = (key: StorageEntryPromise): void => { + const isMap = key.creator.meta.type.isMap; + const isLinked = isMap && key.creator.meta.type.asMap.linked.isTrue; - private onChangeParams = (values: RawParams = []): void => { - this.nextState({ values }); - } + setKey({ + defaultValues: key.creator.section === 'session' + ? [{ + isValid: true, + value: api.consts.session.dedupKeyPrefix.toHex() + }] + : null, + isLinked, + key, + params: key.creator.meta.type.isDoubleMap + ? [ + { type: getTypeDef(key.creator.meta.type.asDoubleMap.key1.toString()) }, + { type: getTypeDef(key.creator.meta.type.asDoubleMap.key2.toString()) } + ] + : isMap + ? [{ + type: getTypeDef( + isLinked + ? `Option<${key.creator.meta.type.asMap.key.toString()}>` + : key.creator.meta.type.asMap.key.toString() + ) + }] + : [] + }); + + _onChangeValues([]); + }; + + const { creator: { method, section, meta } } = key; + + return ( +
+
+ + +
+
+
+
+ ); } -export default withMulti( - Modules, - translate, - withApi -); +export default translate(Modules); diff --git a/packages/app-storage/src/Selection/Raw.tsx b/packages/app-storage/src/Selection/Raw.tsx index 64df312c09..0d97cf1033 100644 --- a/packages/app-storage/src/Selection/Raw.tsx +++ b/packages/app-storage/src/Selection/Raw.tsx @@ -5,8 +5,8 @@ import { I18nProps } from '@polkadot/react-components/types'; import { ComponentProps } from '../types'; -import React from 'react'; -import { Button, Input, TxComponent } from '@polkadot/react-components'; +import React, { useState } from 'react'; +import { Button, Input } from '@polkadot/react-components'; import translate from '../translate'; import { u8aToU8a } from '@polkadot/util'; @@ -14,60 +14,42 @@ import { Compact } from '@polkadot/types'; interface Props extends ComponentProps, I18nProps {} -interface State { - isValid: boolean; - key: Uint8Array; -} +function Raw ({ onAdd, t }: Props): React.ReactElement { + const [{ isValid, key }, setValue] = useState<{ isValid: boolean; key: Uint8Array }>({ isValid: false, key: new Uint8Array([]) }); -class Raw extends TxComponent { - public state: State = { - isValid: false, - key: new Uint8Array([]) + const _onAdd = (): void => { + isValid && onAdd({ isConst: false, key }); }; - - public render (): React.ReactNode { - const { t } = this.props; - const { isValid } = this.state; - - return ( -
-
- -
-
-
-
- ); - } - - private onAdd = (): void => { - const { onAdd } = this.props; - const { key } = this.state; - - onAdd({ isConst: false, key }); - } - - private onChangeKey = (key: string): void => { + const _onChangeKey = (key: string): void => { const u8a = u8aToU8a(key); const isValid = u8a.length !== 0; - this.setState({ + setValue({ isValid, key: Compact.addLengthPrefix(u8a) }); - } + }; + + return ( +
+
+ +
+
+
+
+ ); } export default translate(Raw); diff --git a/packages/app-storage/src/index.tsx b/packages/app-storage/src/index.tsx index 4140ffde1b..f17eb6302c 100644 --- a/packages/app-storage/src/index.tsx +++ b/packages/app-storage/src/index.tsx @@ -18,7 +18,7 @@ interface Props extends AppProps, I18nProps {} function StorageApp ({ basePath }: Props): React.ReactElement { const [queue, setQueue] = useState([]); - const _onAdd = (query: QueryTypes): void => setQueue([query].concat(queue)); + const _onAdd = (query: QueryTypes): void => setQueue([query, ...queue]); const _onRemove = (id: number): void => setQueue(queue.filter((item): boolean => item.id !== id)); return (