Droptdown functional (#1731)

This commit is contained in:
Jaco Greeff 2019-10-18 10:24:03 +02:00 committed by GitHub
parent 9ffe02f492
commit 2f3117dc05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 144 deletions

View File

@ -7,7 +7,7 @@ import { ContractInfo } from '@polkadot/types/interfaces';
import { I18nProps } from '@polkadot/react-components/types';
import { ApiProps } from '@polkadot/react-api/types';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Option } from '@polkadot/types';
import { withCalls } from '@polkadot/react-api';
import { InfoForInput } from '@polkadot/react-components';
@ -21,68 +21,47 @@ interface Props extends ApiProps, I18nProps {
onChange: (isValid: boolean) => void;
}
interface State {
isStored: boolean;
isValidAddr: boolean;
isValid: boolean;
}
class ValidateAddr extends React.PureComponent<Props, State> {
public state: State = {
isStored: false,
isValidAddr: false,
isValid: false
};
public static getDerivedStateFromProps ({ address, contracts_contractInfoOf, onChange }: Props): State {
let isValidAddr = false;
function ValidateAddr ({ address, contracts_contractInfoOf, onChange, t }: Props): React.ReactElement<Props> | null {
const [isAddress, setIsAddress] = useState(false);
const [isStored, setIsStored] = useState(false);
useEffect((): void => {
try {
keyring.decodeAddress(address || '');
isValidAddr = true;
setIsAddress(true);
} catch (error) {
// ignore
setIsAddress(false);
}
}, [address]);
const isStored = (
(!!contracts_contractInfoOf && contracts_contractInfoOf.isSome)
// (!!contract_codeHashOf && contract_codeHashOf.isSome)
);
const isValid = isValidAddr && isStored;
useEffect((): void => {
setIsStored(!!contracts_contractInfoOf && contracts_contractInfoOf.isSome);
}, [contracts_contractInfoOf]);
// FIXME Really not convinced this is the correct place to do this type of callback?
onChange(isValid);
useEffect((): void => {
onChange(isAddress && isStored);
}, [isAddress, isStored]);
return {
isStored,
isValidAddr,
isValid
};
if (isStored || !isAddress) {
return null;
}
public render (): React.ReactNode {
const { t } = this.props;
const { isValid, isValidAddr } = this.state;
if (isValid || !isValidAddr) {
return null;
}
return (
<InfoForInput type='error'>
{
isValidAddr
? t('Unable to find deployed contract code at the specified address')
: t('The value is not in a valid address format')
}
</InfoForInput>
);
}
return (
<InfoForInput type='error'>
{
isAddress
? t('Unable to find deployed contract code at the specified address')
: t('The value is not in a valid address format')
}
</InfoForInput>
);
}
export default translate(
withCalls<Props>(
['query.contracts.contractInfoOf', { fallbacks: ['query.contract.contractInfoOf'], paramName: 'address' }]
['query.contracts.contractInfoOf', {
fallbacks: ['query.contract.contractInfoOf'],
paramName: 'address'
}]
)(ValidateAddr)
);

View File

@ -4,7 +4,7 @@
import { BareProps } from './types';
import React from 'react';
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import SUIButton from 'semantic-ui-react/dist/commonjs/elements/Button/Button';
import SUIDropdown, { DropdownProps } from 'semantic-ui-react/dist/commonjs/modules/Dropdown/Dropdown';
@ -39,110 +39,76 @@ interface Props<Option> extends BareProps {
withLabel?: boolean;
}
class Dropdown<Option> extends React.PureComponent<Props<Option>> {
// Trigger the update on mount - ensuring that the onChange (as described below)
// is trigerred.
public componentDidMount (): void {
this.componentDidUpdate({} as unknown as Props<Option>);
}
// Here we update the component user with the initial value of the dropdown. In a number of
// these (e.g. Accounts) the list of available values are managed by the component itself,
// and there are defaults set (i.e. for accounts the last one used)
public componentDidUpdate (prevProps: Props<Option>): void {
const { defaultValue, value } = this.props;
const startValue = isUndefined(value)
? defaultValue
: value;
const prevStart = isUndefined(prevProps.value)
? prevProps.defaultValue
: prevProps.value;
if (startValue !== prevStart) {
this.onChange(null as any, {
value: startValue
});
}
}
public render (): React.ReactNode {
const { allowAdd = false, className, defaultValue, dropdownClassName, help, isButton, isDisabled, isError, isMultiple, label, labelExtra, onSearch, options, placeholder, renderLabel, searchInput, style, withEllipsis, withLabel, value } = this.props;
const dropdown = (
<SUIDropdown
allowAdditions={allowAdd}
className={dropdownClassName}
button={isButton}
compact={isButton}
disabled={isDisabled}
error={isError}
floating={isButton}
multiple={isMultiple}
onAddItem={this.onAddItem}
onBlur={this.onBlur}
onChange={this.onChange}
onClose={this.onClose}
options={options}
placeholder={placeholder}
renderLabel={renderLabel}
search={onSearch || allowAdd}
searchInput={searchInput}
selection
value={
isUndefined(value)
? defaultValue
: value
}
/>
);
return isButton
? (
<SUIButton.Group primary>
{dropdown}
</SUIButton.Group>
)
: (
<Labelled
className={classes('ui--Dropdown', className)}
help={help}
label={label}
labelExtra={labelExtra}
style={style}
withEllipsis={withEllipsis}
withLabel={withLabel}
>
{dropdown}
</Labelled>
);
}
private onAddItem = (_: React.SyntheticEvent<HTMLElement>, { value }: DropdownProps): void => {
const { onAdd } = this.props;
function Dropdown<Option> ({ allowAdd = false, className, defaultValue, dropdownClassName, help, isButton, isDisabled, isError, isMultiple, label, labelExtra, onAdd, onBlur, onChange, onClose, onSearch, options, placeholder, renderLabel, searchInput, style, transform, withEllipsis, withLabel, value }: Props<Option>): React.ReactElement<Props<Option>> {
const [stateValue, setStateValue] = useState<any>();
const _onAdd = (_: React.SyntheticEvent<HTMLElement>, { value }: DropdownProps): void =>
onAdd && onAdd(value);
}
private onBlur = (): void => {
const { onBlur } = this.props;
onBlur && onBlur();
}
private onChange = (_: React.SyntheticEvent<HTMLElement>, { value }: DropdownProps): void => {
const { onChange, transform } = this.props;
const _onChange = (_: React.SyntheticEvent<HTMLElement> | null, { value }: DropdownProps): void => {
setStateValue(value);
onChange && onChange(
transform
? transform(value)
: value
);
}
};
private onClose = (): void => {
const { onClose } = this.props;
useEffect((): void => {
const newValue = isUndefined(value)
? defaultValue
: value;
onClose && onClose();
}
// only update parent if we have had something changed
if (JSON.stringify({ v: newValue }) !== JSON.stringify({ v: stateValue })) {
_onChange(null, { value: newValue });
}
}, [defaultValue, stateValue, value]);
const dropdown = (
<SUIDropdown
allowAdditions={allowAdd}
className={dropdownClassName}
button={isButton}
compact={isButton}
disabled={isDisabled}
error={isError}
floating={isButton}
multiple={isMultiple}
onAddItem={_onAdd}
onBlur={onBlur}
onChange={_onChange}
onClose={onClose}
options={options}
placeholder={placeholder}
renderLabel={renderLabel}
search={onSearch || allowAdd}
searchInput={searchInput}
selection
value={stateValue}
/>
);
return isButton
? (
<SUIButton.Group primary>
{dropdown}
</SUIButton.Group>
)
: (
<Labelled
className={classes('ui--Dropdown', className)}
help={help}
label={label}
labelExtra={labelExtra}
style={style}
withEllipsis={withEllipsis}
withLabel={withLabel}
>
{dropdown}
</Labelled>
);
}
export default styled(Dropdown)`