Ui 2 remove mui from views & shell (#5613)
* Stepper from semantic-ui * Tabs component * ui/Tabs in loadContract * Adapt Dropdown events * Remove direct use of semantic-ui * Remove IconButton & Subheader * Remove IconMenu * ui/List & List.Item * Be explicit in context props
This commit is contained in:
parent
1243728725
commit
7cdddd344b
@ -18,8 +18,8 @@ import React, { PropTypes } from 'react';
|
|||||||
|
|
||||||
import styles from './dappIcon.css';
|
import styles from './dappIcon.css';
|
||||||
|
|
||||||
export default function DappIcon ({ app, className, small }, context) {
|
export default function DappIcon ({ app, className, small }, { api }) {
|
||||||
const { dappsUrl } = context.api;
|
const { dappsUrl } = api;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
|
@ -26,7 +26,9 @@ import styles from './dropdown.css';
|
|||||||
const NAME_ID = ' ';
|
const NAME_ID = ' ';
|
||||||
|
|
||||||
// FIXME: Currently does not display the selected icon alongside
|
// FIXME: Currently does not display the selected icon alongside
|
||||||
export default function Dropdown ({ className, disabled = false, error, fullWidth = true, hint, label, onBlur, onChange, onKeyDown, options, text, value }, context) {
|
export default function Dropdown ({ className, disabled = false, error, fullWidth = true, hint, label, onBlur, onChange, onKeyDown, options, text, value }, { intl }) {
|
||||||
|
const _onChange = (event, { value }) => onChange(event, value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LabelComponent label={ label }>
|
<LabelComponent label={ label }>
|
||||||
<SemanticDropdown
|
<SemanticDropdown
|
||||||
@ -37,7 +39,7 @@ export default function Dropdown ({ className, disabled = false, error, fullWidt
|
|||||||
id={ NAME_ID }
|
id={ NAME_ID }
|
||||||
name={ NAME_ID }
|
name={ NAME_ID }
|
||||||
onBlur={ onBlur }
|
onBlur={ onBlur }
|
||||||
onChange={ onChange }
|
onChange={ _onChange }
|
||||||
onKeyDown={ onKeyDown }
|
onKeyDown={ onKeyDown }
|
||||||
options={ options }
|
options={ options }
|
||||||
placeholder={ parseI18NString(context, hint) }
|
placeholder={ parseI18NString(context, hint) }
|
||||||
|
@ -392,9 +392,8 @@ export default class TypedInput extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeBool = (event) => {
|
onChangeBool = (event, value) => {
|
||||||
console.log('onChangeBool', event.target);
|
this.props.onChange(value === 'true');
|
||||||
this.props.onChange(event.target.value === 'true');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onEthTypeChange = () => {
|
onEthTypeChange = () => {
|
||||||
|
@ -63,7 +63,7 @@ export default class LanguageSelector extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (event, index, locale) => {
|
onChange = (event, locale) => {
|
||||||
this.store.setLocale(locale || event.target.value);
|
this.store.setLocale(locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,5 @@ describe('LanguageSelector', () => {
|
|||||||
it('has locale items', () => {
|
it('has locale items', () => {
|
||||||
expect(select.props().options.length > 0).to.be.true;
|
expect(select.props().options.length > 0).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls localeStore.setLocale when changed', () => {
|
|
||||||
select.simulate('change', { target: { value: 'de' } });
|
|
||||||
expect(localeStore.setLocale).to.have.been.calledWith('de');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
17
js/src/ui/List/Item/index.js
Normal file
17
js/src/ui/List/Item/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './item';
|
24
js/src/ui/List/Item/item.css
Normal file
24
js/src/ui/List/Item/item.css
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.item {
|
||||||
|
.description {
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
}
|
||||||
|
}
|
60
js/src/ui/List/Item/item.js
Normal file
60
js/src/ui/List/Item/item.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { List as SemanticList } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import styles from './item.css';
|
||||||
|
|
||||||
|
export default function Item ({ buttons, className, description, icon, label, onClick, style }) {
|
||||||
|
return (
|
||||||
|
<SemanticList.Item
|
||||||
|
className={ styles.item }
|
||||||
|
onClick={ onClick }
|
||||||
|
style={ style }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
icon && (
|
||||||
|
<SemanticList.Icon>
|
||||||
|
{ icon }
|
||||||
|
</SemanticList.Icon>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<SemanticList.Content>
|
||||||
|
<div className={ styles.label }>
|
||||||
|
{ label }
|
||||||
|
</div>
|
||||||
|
<div className={ styles.description }>
|
||||||
|
{ description }
|
||||||
|
</div>
|
||||||
|
<div className={ styles.buttons }>
|
||||||
|
{ buttons }
|
||||||
|
</div>
|
||||||
|
</SemanticList.Content>
|
||||||
|
</SemanticList.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Item.propTypes = {
|
||||||
|
buttons: PropTypes.any,
|
||||||
|
className: PropTypes.string,
|
||||||
|
description: PropTypes.node,
|
||||||
|
key: PropTypes.any,
|
||||||
|
icon: PropTypes.node,
|
||||||
|
label: PropTypes.node,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
style: PropTypes.object
|
||||||
|
};
|
17
js/src/ui/List/index.js
Normal file
17
js/src/ui/List/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './list';
|
19
js/src/ui/List/list.css
Normal file
19
js/src/ui/List/list.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.list {
|
||||||
|
}
|
58
js/src/ui/List/list.js
Normal file
58
js/src/ui/List/list.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { List as SemanticList } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import LabelComponent from '../Form/LabelComponent';
|
||||||
|
import Item from './Item';
|
||||||
|
|
||||||
|
import styles from './list.css';
|
||||||
|
|
||||||
|
export default function List ({ className, items, label, onClick, style }) {
|
||||||
|
const wrapOnClick = (key) => {
|
||||||
|
return (event) => onClick && onClick(event, key);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LabelComponent label={ label }>
|
||||||
|
<SemanticList className={ `${styles.list} ${className}` }>
|
||||||
|
{
|
||||||
|
items.map(({ buttons, description, icon, key, label }, index) => (
|
||||||
|
<Item
|
||||||
|
buttons={ buttons }
|
||||||
|
description={ description }
|
||||||
|
icon={ icon }
|
||||||
|
key={ key || index }
|
||||||
|
label={ label }
|
||||||
|
onClick={ wrapOnClick(key || index) }
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</SemanticList>
|
||||||
|
</LabelComponent>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List.Item = Item;
|
||||||
|
|
||||||
|
List.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
items: PropTypes.array,
|
||||||
|
label: PropTypes.node,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
style: PropTypes.object
|
||||||
|
};
|
17
js/src/ui/Steps/Step/index.js
Normal file
17
js/src/ui/Steps/Step/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './step';
|
41
js/src/ui/Steps/Step/step.js
Normal file
41
js/src/ui/Steps/Step/step.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { Step as SemanticStep } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
export default function Step ({ className, isActive, isCompleted, label }) {
|
||||||
|
return (
|
||||||
|
<SemanticStep
|
||||||
|
className={ className }
|
||||||
|
completed={ isCompleted }
|
||||||
|
active={ isActive }
|
||||||
|
>
|
||||||
|
<SemanticStep.Content>
|
||||||
|
<SemanticStep.Title>
|
||||||
|
{ label }
|
||||||
|
</SemanticStep.Title>
|
||||||
|
</SemanticStep.Content>
|
||||||
|
</SemanticStep>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Step.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
isActive: PropTypes.bool,
|
||||||
|
isCompleted: PropTypes.bool,
|
||||||
|
label: PropTypes.node
|
||||||
|
};
|
@ -15,35 +15,37 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import { Step, Stepper, StepLabel } from 'material-ui/Stepper';
|
import { Step as SemanticStep } from 'semantic-ui-react';
|
||||||
|
|
||||||
import styles from '../title.css';
|
import Step from './Step';
|
||||||
|
|
||||||
export default function Steps ({ activeStep, steps }) {
|
export default function Steps ({ activeStep, className, steps }) {
|
||||||
if (!steps || steps.length < 2) {
|
if (!steps || steps.length < 2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.steps }>
|
<div className={ className }>
|
||||||
<Stepper activeStep={ activeStep }>
|
<SemanticStep.Group ordered>
|
||||||
{
|
{
|
||||||
steps.map((label, index) => {
|
steps.map((label, index) => (
|
||||||
return (
|
<Step
|
||||||
<Step key={ label.key || index }>
|
isActive={ activeStep === index }
|
||||||
<StepLabel>
|
isCompleted={ activeStep > index }
|
||||||
{ label }
|
key={ label.key || index }
|
||||||
</StepLabel>
|
label={ label.label || label }
|
||||||
</Step>
|
/>
|
||||||
);
|
))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</Stepper>
|
</SemanticStep.Group>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Steps.Step = Step;
|
||||||
|
|
||||||
Steps.propTypes = {
|
Steps.propTypes = {
|
||||||
activeStep: PropTypes.number,
|
activeStep: PropTypes.number,
|
||||||
|
className: PropTypes.string,
|
||||||
steps: PropTypes.array
|
steps: PropTypes.array
|
||||||
};
|
};
|
@ -31,12 +31,12 @@ function render (props = {}) {
|
|||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('ui/Title/Steps', () => {
|
describe('ui/Steps', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
render({ steps: ['stepA', 'stepB'] });
|
render({ steps: ['stepA', 'stepB'] });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the Stepper', () => {
|
it('renders the defaults', () => {
|
||||||
expect(component.find('Stepper').get(0)).to.be.ok;
|
expect(component).to.be.ok;
|
||||||
});
|
});
|
||||||
});
|
});
|
17
js/src/ui/Tabs/Tab/index.js
Normal file
17
js/src/ui/Tabs/Tab/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './tab';
|
41
js/src/ui/Tabs/Tab/tab.js
Normal file
41
js/src/ui/Tabs/Tab/tab.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { Menu } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
export default function Tab ({ isActive, className, index, label, name, onClick, style }) {
|
||||||
|
return (
|
||||||
|
<Menu.Item
|
||||||
|
active={ isActive }
|
||||||
|
index={ index }
|
||||||
|
name={ name }
|
||||||
|
onClick={ onClick }
|
||||||
|
>
|
||||||
|
{ label }
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
index: PropTypes.number,
|
||||||
|
isActive: PropTypes.bool,
|
||||||
|
label: PropTypes.any,
|
||||||
|
name: PropTypes.string,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
style: PropTypes.object
|
||||||
|
};
|
17
js/src/ui/Tabs/index.js
Normal file
17
js/src/ui/Tabs/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './tabs';
|
60
js/src/ui/Tabs/tabs.js
Normal file
60
js/src/ui/Tabs/tabs.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { Menu } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import Tab from './Tab';
|
||||||
|
|
||||||
|
export default function Tabs ({ activeTab, className, tabs, onChange }) {
|
||||||
|
const onTabClick = (event, { index }) => onChange && onChange(event, index);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu
|
||||||
|
className={ className }
|
||||||
|
pointing
|
||||||
|
>
|
||||||
|
{
|
||||||
|
tabs.map((tab, index) => {
|
||||||
|
if (!tab) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = `tab_${index}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
isActive={ activeTab === index }
|
||||||
|
index={ index }
|
||||||
|
key={ key }
|
||||||
|
label={ tab.label || tab }
|
||||||
|
onClick={ onTabClick }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tabs.Tab = Tab;
|
||||||
|
|
||||||
|
Tabs.propTypes = {
|
||||||
|
activeTab: PropTypes.number,
|
||||||
|
className: PropTypes.string,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
tabs: PropTypes.array
|
||||||
|
};
|
@ -18,9 +18,7 @@ import React, { PropTypes } from 'react';
|
|||||||
|
|
||||||
import Progress from '~/ui/Progress';
|
import Progress from '~/ui/Progress';
|
||||||
|
|
||||||
import styles from '../title.css';
|
export default function Waiting ({ activeStep, busy, busySteps, className }) {
|
||||||
|
|
||||||
export default function Waiting ({ activeStep, busy, busySteps }) {
|
|
||||||
const isWaiting = busy || (busySteps || []).includes(activeStep);
|
const isWaiting = busy || (busySteps || []).includes(activeStep);
|
||||||
|
|
||||||
if (!isWaiting) {
|
if (!isWaiting) {
|
||||||
@ -28,7 +26,7 @@ export default function Waiting ({ activeStep, busy, busySteps }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.waiting }>
|
<div className={ className }>
|
||||||
<Progress />
|
<Progress />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -37,5 +35,6 @@ export default function Waiting ({ activeStep, busy, busySteps }) {
|
|||||||
Waiting.propTypes = {
|
Waiting.propTypes = {
|
||||||
activeStep: PropTypes.number,
|
activeStep: PropTypes.number,
|
||||||
busy: PropTypes.bool,
|
busy: PropTypes.bool,
|
||||||
busySteps: PropTypes.array
|
busySteps: PropTypes.array,
|
||||||
|
className: PropTypes.string
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
.title,
|
.title,
|
||||||
.subtitle {
|
.subtitle {
|
||||||
.steps {
|
.steps {
|
||||||
margin: -0.5em 0 -1em 0;
|
margin: 1em 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.waiting {
|
.waiting {
|
||||||
|
@ -19,8 +19,8 @@ import React, { PropTypes } from 'react';
|
|||||||
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
|
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
|
||||||
|
|
||||||
import { Title as ContainerTitle } from '~/ui/Container';
|
import { Title as ContainerTitle } from '~/ui/Container';
|
||||||
|
import Steps from '~/ui/Steps';
|
||||||
|
|
||||||
import Steps from './Steps';
|
|
||||||
import Waiting from './Waiting';
|
import Waiting from './Waiting';
|
||||||
|
|
||||||
import styles from './title.css';
|
import styles from './title.css';
|
||||||
@ -52,12 +52,14 @@ export default function Title ({ activeStep, busy, busySteps, byline, className,
|
|||||||
/>
|
/>
|
||||||
<Steps
|
<Steps
|
||||||
activeStep={ activeStep }
|
activeStep={ activeStep }
|
||||||
|
className={ styles.steps }
|
||||||
steps={ steps }
|
steps={ steps }
|
||||||
/>
|
/>
|
||||||
<Waiting
|
<Waiting
|
||||||
activeStep={ activeStep }
|
activeStep={ activeStep }
|
||||||
busy={ busy }
|
busy={ busy }
|
||||||
busySteps={ busySteps }
|
busySteps={ busySteps }
|
||||||
|
className={ styles.waiting }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -21,8 +21,7 @@ import IconCache from '~/ui/IconCache';
|
|||||||
|
|
||||||
const iconCache = IconCache.get();
|
const iconCache = IconCache.get();
|
||||||
|
|
||||||
export default function TokenImage ({ token }, context) {
|
export default function TokenImage ({ token }, { api }) {
|
||||||
const { api } = context;
|
|
||||||
const imageurl = token.image || iconCache.images[token.address];
|
const imageurl = token.image || iconCache.images[token.address];
|
||||||
let imagesrc = unknownImage;
|
let imagesrc = unknownImage;
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ export Icons from './Icons';
|
|||||||
export IdentityIcon from './IdentityIcon';
|
export IdentityIcon from './IdentityIcon';
|
||||||
export IdentityName from './IdentityName';
|
export IdentityName from './IdentityName';
|
||||||
export LanguageSelector from './LanguageSelector';
|
export LanguageSelector from './LanguageSelector';
|
||||||
|
export List from './List';
|
||||||
export Loading from './Loading';
|
export Loading from './Loading';
|
||||||
export MethodDecoding from './MethodDecoding';
|
export MethodDecoding from './MethodDecoding';
|
||||||
export { Busy as BusyStep, Completed as CompletedStep } from './Modal';
|
export { Busy as BusyStep, Completed as CompletedStep } from './Modal';
|
||||||
@ -57,6 +58,7 @@ export SelectionList from './SelectionList';
|
|||||||
export ShortenedHash from './ShortenedHash';
|
export ShortenedHash from './ShortenedHash';
|
||||||
export SignerIcon from './SignerIcon';
|
export SignerIcon from './SignerIcon';
|
||||||
export Snackbar from './Snackbar';
|
export Snackbar from './Snackbar';
|
||||||
|
export Tabs from './Tabs';
|
||||||
export Tags from './Tags';
|
export Tags from './Tags';
|
||||||
export Title from './Title';
|
export Title from './Title';
|
||||||
export TxHash from './TxHash';
|
export TxHash from './TxHash';
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { Menu, Segment } from 'semantic-ui-react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
@ -22,12 +21,12 @@ import { connect } from 'react-redux';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import { newError, openSnackbar } from '@parity/shared/redux/actions';
|
import { newError, openSnackbar } from '@parity/shared/redux/actions';
|
||||||
import { Button, IdentityName, IdentityIcon, Portal } from '@parity/ui';
|
import { Button, IdentityName, IdentityIcon, Portal, Tabs } from '@parity/ui';
|
||||||
import PasswordStrength from '@parity/ui/Form/PasswordStrength';
|
import PasswordStrength from '@parity/ui/Form/PasswordStrength';
|
||||||
import Form, { Input } from '@parity/ui/Form';
|
import Form, { Input } from '@parity/ui/Form';
|
||||||
import { CancelIcon, CheckIcon, SendIcon } from '@parity/ui/Icons';
|
import { CancelIcon, CheckIcon, SendIcon } from '@parity/ui/Icons';
|
||||||
|
|
||||||
import Store, { CHANGE_ACTION, TEST_ACTION } from './store';
|
import Store from './store';
|
||||||
import styles from './passwordManager.css';
|
import styles from './passwordManager.css';
|
||||||
|
|
||||||
const MSG_SUCCESS_STYLE = {
|
const MSG_SUCCESS_STYLE = {
|
||||||
@ -37,12 +36,8 @@ const MSG_FAILURE_STYLE = {
|
|||||||
backgroundColor: 'rgba(229, 115, 115, 0.75)'
|
backgroundColor: 'rgba(229, 115, 115, 0.75)'
|
||||||
};
|
};
|
||||||
|
|
||||||
let MENU_CONTENT = 'TEST';
|
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class PasswordManager extends Component {
|
class PasswordManager extends Component {
|
||||||
state = { activeItem: 'bio' };
|
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
api: PropTypes.object.isRequired
|
api: PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
@ -132,40 +127,39 @@ class PasswordManager extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderPage () {
|
renderPage () {
|
||||||
const { activeItem } = this.state;
|
const { activeTab } = this.store;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Menu attached='top' tabular>
|
<Tabs
|
||||||
<Menu.Item name='Test Password' active={ activeItem === 'Test Password' } onClick={ this.itemTestPassword } />
|
activeTab={ activeTab }
|
||||||
<Menu.Item name='Change Password' active={ activeItem === 'Change Password' } onClick={ this.itemChangePassword } />
|
tabs={ [
|
||||||
</Menu>
|
<FormattedMessage
|
||||||
|
id='passwordChange.tabChange'
|
||||||
<Segment attached='bottom'>
|
defaultMessage='Change Password'
|
||||||
{ MENU_CONTENT === 'TEST' ? this.renderTabTest() : this.renderTabChange() }
|
/>,
|
||||||
</Segment>
|
<FormattedMessage
|
||||||
|
id='passwordChange.tabTest'
|
||||||
|
defaultMessage='TestPassword'
|
||||||
|
/>
|
||||||
|
] }
|
||||||
|
onChange={ this.onChangeTab }
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
activeTab === 1
|
||||||
|
? this.renderTabTest()
|
||||||
|
: this.renderTabChange()
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTestPassword = (e, name) => {
|
onChangeTab = (event, activeTab) => {
|
||||||
MENU_CONTENT = 'TEST';
|
this.store.setActiveTab(activeTab);
|
||||||
this.onActivateTestTab();
|
|
||||||
this.setState({ activeItem: name });
|
|
||||||
}
|
|
||||||
|
|
||||||
itemChangePassword = (e, name) => {
|
|
||||||
MENU_CONTENT = 'CHANGE';
|
|
||||||
this.onActivateChangeTab();
|
|
||||||
this.setState({ activeItem: name });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTabTest () {
|
renderTabTest () {
|
||||||
const { actionTab, busy } = this.store;
|
const { busy } = this.store;
|
||||||
|
|
||||||
if (actionTab !== TEST_ACTION) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={ styles.form }>
|
<Form className={ styles.form }>
|
||||||
@ -196,11 +190,7 @@ class PasswordManager extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTabChange () {
|
renderTabChange () {
|
||||||
const { actionTab, busy, isRepeatValid, newPassword, passwordHint } = this.store;
|
const { busy, isRepeatValid, newPassword, passwordHint } = this.store;
|
||||||
|
|
||||||
if (actionTab !== CHANGE_ACTION) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={ styles.form }>
|
<Form className={ styles.form }>
|
||||||
@ -300,7 +290,7 @@ class PasswordManager extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderDialogActions () {
|
renderDialogActions () {
|
||||||
const { actionTab, busy, isRepeatValid } = this.store;
|
const { activeTab, busy, isRepeatValid } = this.store;
|
||||||
|
|
||||||
const cancelBtn = (
|
const cancelBtn = (
|
||||||
<Button
|
<Button
|
||||||
@ -332,7 +322,7 @@ class PasswordManager extends Component {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionTab === TEST_ACTION) {
|
if (activeTab === 1) {
|
||||||
return [
|
return [
|
||||||
cancelBtn,
|
cancelBtn,
|
||||||
<Button
|
<Button
|
||||||
@ -366,14 +356,6 @@ class PasswordManager extends Component {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
onActivateChangeTab = () => {
|
|
||||||
this.store.setActionTab(CHANGE_ACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
onActivateTestTab = () => {
|
|
||||||
this.store.setActionTab(TEST_ACTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditCurrentPassword = (event, password) => {
|
onEditCurrentPassword = (event, password) => {
|
||||||
this.store.setPassword(password);
|
this.store.setPassword(password);
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@
|
|||||||
|
|
||||||
import { action, computed, observable, transaction } from 'mobx';
|
import { action, computed, observable, transaction } from 'mobx';
|
||||||
|
|
||||||
const CHANGE_ACTION = 'CHANGE_ACTION';
|
|
||||||
const TEST_ACTION = 'TEST_ACTION';
|
|
||||||
|
|
||||||
export default class Store {
|
export default class Store {
|
||||||
@observable actionTab = TEST_ACTION;
|
@observable activeTab = 0;
|
||||||
@observable address = null;
|
@observable address = null;
|
||||||
@observable busy = false;
|
@observable busy = false;
|
||||||
@observable infoMessage = null;
|
@observable infoMessage = null;
|
||||||
@ -44,9 +41,9 @@ export default class Store {
|
|||||||
return this.newPasswordRepeat === this.newPassword;
|
return this.newPasswordRepeat === this.newPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action setActionTab = (actionTab) => {
|
@action setActiveTab = (activeTab) => {
|
||||||
transaction(() => {
|
transaction(() => {
|
||||||
this.actionTab = actionTab;
|
this.activeTab = activeTab;
|
||||||
this.setInfoMessage();
|
this.setInfoMessage();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -154,8 +151,3 @@ export default class Store {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
|
||||||
CHANGE_ACTION,
|
|
||||||
TEST_ACTION
|
|
||||||
};
|
|
||||||
|
@ -129,9 +129,7 @@ export default class OptionsStep extends Component {
|
|||||||
this.props.store.setRefundAddress(refundAddress);
|
this.props.store.setRefundAddress(refundAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectCoin = (event, data) => {
|
onSelectCoin = (event, value) => {
|
||||||
const { value } = data;
|
|
||||||
|
|
||||||
this.props.store.setCoinSymbol(value);
|
this.props.store.setCoinSymbol(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ describe('views/Account/Shapeshift/OptionsStep', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sets the coinSymbol on the store', () => {
|
it('sets the coinSymbol on the store', () => {
|
||||||
instance.onSelectCoin(null, { value: 'XMR' });
|
instance.onSelectCoin(null, 'XMR');
|
||||||
expect(store.setCoinSymbol).to.have.been.calledWith('XMR');
|
expect(store.setCoinSymbol).to.have.been.calledWith('XMR');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -207,8 +207,8 @@ export default class Details extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeToken = (event, data) => {
|
onChangeToken = (event, token) => {
|
||||||
this.props.onChange('token', data.value);
|
this.props.onChange('token', token);
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditSender = (event, sender) => {
|
onEditSender = (event, sender) => {
|
||||||
|
@ -178,7 +178,7 @@ export default class DetailsStep extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (func.abi.inputs || []).map((input, index) => {
|
return (func.abi.inputs || []).map((input, index) => {
|
||||||
const onChange = (value) => onValueChange(null, index, value);
|
const onChange = (event, value) => onValueChange(null, index, value);
|
||||||
const label = `${input.name}: ${input.type}`;
|
const label = `${input.name}: ${input.type}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -200,7 +200,7 @@ export default class DetailsStep extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onFuncChange = (event, index, signature) => {
|
onFuncChange = (event, signature) => {
|
||||||
const { contract, onFuncChange } = this.props;
|
const { contract, onFuncChange } = this.props;
|
||||||
|
|
||||||
onFuncChange(event, contract.functions.find((fn) => fn.signature === signature));
|
onFuncChange(event, contract.functions.find((fn) => fn.signature === signature));
|
||||||
|
@ -58,23 +58,4 @@ describe('modals/ExecuteContract/DetailsStep', () => {
|
|||||||
it('renders', () => {
|
it('renders', () => {
|
||||||
expect(render({ accounts: {}, values: [ true ], valuesError: [ null ] })).to.be.ok;
|
expect(render({ accounts: {}, values: [ true ], valuesError: [ null ] })).to.be.ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parameter values', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
render({
|
|
||||||
accounts: {},
|
|
||||||
func: CONTRACT.functions[0],
|
|
||||||
values: [ false ],
|
|
||||||
valuesError: [ null ]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('bool parameters', () => {
|
|
||||||
it('toggles from false to true', () => {
|
|
||||||
component.find('TypedInput').last().shallow().simulate('change', { target: { value: 'true' } });
|
|
||||||
|
|
||||||
expect(onValueChange).to.have.been.calledWith(null, 0, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -43,7 +43,7 @@ function render (props) {
|
|||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('modals/ExecuteContract', () => {
|
describe('views/Contract/ExecuteContract', () => {
|
||||||
it('renders', () => {
|
it('renders', () => {
|
||||||
expect(render({ accounts: {} })).to.be.ok;
|
expect(render({ accounts: {} })).to.be.ok;
|
||||||
});
|
});
|
||||||
|
@ -14,27 +14,24 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { Subheader, IconButton, Tabs, Tab } from 'material-ui';
|
|
||||||
import { List, ListItem, makeSelectable } from 'material-ui/List';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Button, Portal } from '@parity/ui';
|
import { Button, List, Portal, Tabs } from '@parity/ui';
|
||||||
import Editor from '@parity/ui/Editor';
|
import Editor from '@parity/ui/Editor';
|
||||||
import { CancelIcon, CheckIcon, DeleteIcon } from '@parity/ui/Icons';
|
import { CancelIcon, CheckIcon, DeleteIcon } from '@parity/ui/Icons';
|
||||||
|
|
||||||
import styles from './loadContract.css';
|
import styles from './loadContract.css';
|
||||||
|
|
||||||
const SelectableList = makeSelectable(List);
|
|
||||||
|
|
||||||
const REMOVAL_STYLE = {
|
const REMOVAL_STYLE = {
|
||||||
backgroundColor: 'none',
|
backgroundColor: 'none',
|
||||||
cursor: 'default'
|
cursor: 'default'
|
||||||
};
|
};
|
||||||
const SELECTED_STYLE = {
|
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.1)'
|
// const SELECTED_STYLE = {
|
||||||
};
|
// backgroundColor: 'rgba(255, 255, 255, 0.1)'
|
||||||
|
// };
|
||||||
|
|
||||||
export default class LoadContract extends Component {
|
export default class LoadContract extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -46,6 +43,7 @@ export default class LoadContract extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
activeTab: -1,
|
||||||
selected: -1,
|
selected: -1,
|
||||||
deleteRequest: false,
|
deleteRequest: false,
|
||||||
deleteId: -1
|
deleteId: -1
|
||||||
@ -81,7 +79,9 @@ export default class LoadContract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBody () {
|
renderBody () {
|
||||||
if (this.state.deleteRequest) {
|
const { activeTab, deleteRequest } = this.state;
|
||||||
|
|
||||||
|
if (deleteRequest) {
|
||||||
return this.renderConfirmRemoval();
|
return this.renderConfirmRemoval();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,51 +89,57 @@ export default class LoadContract extends Component {
|
|||||||
const contractsTab = Object.keys(contracts).length === 0
|
const contractsTab = Object.keys(contracts).length === 0
|
||||||
? null
|
? null
|
||||||
: (
|
: (
|
||||||
<Tab
|
<FormattedMessage
|
||||||
label={
|
id='loadContract.tab.local'
|
||||||
<FormattedMessage
|
defaultMessage='Local'
|
||||||
id='loadContract.tab.local'
|
/>
|
||||||
defaultMessage='Local'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{ this.renderEditor() }
|
|
||||||
<SelectableList onChange={ this.onClickContract }>
|
|
||||||
<Subheader>
|
|
||||||
<FormattedMessage
|
|
||||||
id='loadContract.header.saved'
|
|
||||||
defaultMessage='Saved Contracts'
|
|
||||||
/>
|
|
||||||
</Subheader>
|
|
||||||
{ this.renderContracts(contracts) }
|
|
||||||
</SelectableList>
|
|
||||||
</Tab>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.loadContainer }>
|
<div className={ styles.loadContainer }>
|
||||||
<Tabs onChange={ this.handleChangeTab }>
|
<Tabs
|
||||||
{ contractsTab }
|
activeTab={ activeTab }
|
||||||
<Tab
|
onChange={ this.handleChangeTab }
|
||||||
label={
|
tabs={ [
|
||||||
<FormattedMessage
|
contractsTab,
|
||||||
id='loadContract.tab.snippets'
|
<FormattedMessage
|
||||||
defaultMessage='Snippets'
|
id='loadContract.tab.snippets'
|
||||||
|
defaultMessage='Snippets'
|
||||||
|
/>
|
||||||
|
] }
|
||||||
|
/>
|
||||||
|
{ this.renderEditor() }
|
||||||
|
{
|
||||||
|
this.state.activeTab === 0
|
||||||
|
? (
|
||||||
|
<List
|
||||||
|
label={
|
||||||
|
<h4>
|
||||||
|
<FormattedMessage
|
||||||
|
id='loadContract.header.saved'
|
||||||
|
defaultMessage='Saved Contracts'
|
||||||
|
/>
|
||||||
|
</h4>
|
||||||
|
}
|
||||||
|
onChange={ this.onClickContract }
|
||||||
|
items={ this.renderContracts(contracts) }
|
||||||
/>
|
/>
|
||||||
}
|
)
|
||||||
>
|
: (
|
||||||
{ this.renderEditor() }
|
<List
|
||||||
<SelectableList onChange={ this.onClickContract }>
|
label={
|
||||||
<Subheader>
|
<h4>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='loadContract.header.snippets'
|
id='loadContract.header.snippets'
|
||||||
defaultMessage='Contract Snippets'
|
defaultMessage='Contract Snippets'
|
||||||
/>
|
/>
|
||||||
</Subheader>
|
</h4>
|
||||||
{ this.renderContracts(snippets, false) }
|
}
|
||||||
</SelectableList>
|
onClick={ this.onClickContract }
|
||||||
</Tab>
|
items={ this.renderContracts(snippets, false) }
|
||||||
</Tabs>
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -150,9 +156,9 @@ export default class LoadContract extends Component {
|
|||||||
defaultMessage='Are you sure you want to remove the following contract from your saved contracts?'
|
defaultMessage='Are you sure you want to remove the following contract from your saved contracts?'
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<ListItem
|
<List.Item
|
||||||
primaryText={ name }
|
label={ name }
|
||||||
secondaryText={
|
description={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='loadContract.removal.savedAt'
|
id='loadContract.removal.savedAt'
|
||||||
defaultMessage='Saved {when}'
|
defaultMessage='Saved {when}'
|
||||||
@ -200,46 +206,31 @@ export default class LoadContract extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderContracts (contracts, removable = true) {
|
renderContracts (contracts, removable = true) {
|
||||||
const { selected } = this.state;
|
|
||||||
|
|
||||||
return Object
|
return Object
|
||||||
.values(contracts)
|
.values(contracts)
|
||||||
.map((contract) => {
|
.map((contract) => {
|
||||||
const { id, name, timestamp, description } = contract;
|
const { id, name, timestamp, description } = contract;
|
||||||
const onDelete = () => this.onDeleteRequest(id);
|
const onDelete = () => this.onDeleteRequest(id);
|
||||||
|
|
||||||
return (
|
return {
|
||||||
<ListItem
|
key: id,
|
||||||
key={ id }
|
label: name,
|
||||||
primaryText={ name }
|
buttons: removable && (
|
||||||
rightIconButton={
|
<Button
|
||||||
removable
|
icon={ <DeleteIcon /> }
|
||||||
? (
|
onClick={ onDelete }
|
||||||
<IconButton onTouchTap={ onDelete }>
|
/>
|
||||||
<DeleteIcon />
|
),
|
||||||
</IconButton>
|
description: description || (
|
||||||
)
|
<FormattedMessage
|
||||||
: null
|
id='loadContract.contract.savedAt'
|
||||||
}
|
defaultMessage='Saved {when}'
|
||||||
secondaryText={
|
values={ {
|
||||||
description || (
|
when: moment(timestamp).fromNow()
|
||||||
<FormattedMessage
|
} }
|
||||||
id='loadContract.contract.savedAt'
|
/>
|
||||||
defaultMessage='Saved {when}'
|
)
|
||||||
values={ {
|
};
|
||||||
when: moment(timestamp).fromNow()
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
style={
|
|
||||||
selected === id
|
|
||||||
? SELECTED_STYLE
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
value={ id }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,8 +291,8 @@ export default class LoadContract extends Component {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeTab = () => {
|
handleChangeTab = (event, activeTab) => {
|
||||||
this.setState({ selected: -1 });
|
this.setState({ activeTab, selected: -1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickContract = (event, selected) => {
|
onClickContract = (event, selected) => {
|
||||||
|
@ -179,7 +179,7 @@ export default class ContractDevelopStore {
|
|||||||
this.reloadContracts(-1, sourcecode);
|
this.reloadContracts(-1, sourcecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action handleSelectBuild = (_, index, value) => {
|
@action handleSelectBuild = (event, value) => {
|
||||||
this.selectedBuild = value;
|
this.selectedBuild = value;
|
||||||
return this
|
return this
|
||||||
.loadSolidityVersion(this.builds[value])
|
.loadSolidityVersion(this.builds[value])
|
||||||
@ -282,7 +282,7 @@ export default class ContractDevelopStore {
|
|||||||
this.showSaveModal = false;
|
this.showSaveModal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action handleSelectContract = (_, index, value) => {
|
@action handleSelectContract = (event, value) => {
|
||||||
this.contractIndex = value;
|
this.contractIndex = value;
|
||||||
this.contract = this.contracts[Object.keys(this.contracts)[value]];
|
this.contract = this.contracts[Object.keys(this.contracts)[value]];
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { Menu } from 'semantic-ui-react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
@ -67,7 +66,7 @@ export default class Node extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem (name, func, label) {
|
renderItem (name, label) {
|
||||||
return {
|
return {
|
||||||
key: name,
|
key: name,
|
||||||
text: name,
|
text: name,
|
||||||
@ -129,46 +128,43 @@ export default class Node extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ layout.option }>
|
<div className={ layout.option }>
|
||||||
<FormattedMessage
|
<Dropdown
|
||||||
id='settings.parity.modes.hint'
|
|
||||||
defaultMessage='Choose the syncing mode for the Parity node'
|
|
||||||
/>
|
|
||||||
<Menu
|
|
||||||
vertical
|
|
||||||
id='parityModeSelect'
|
id='parityModeSelect'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.modes.hint'
|
||||||
|
defaultMessage='Choose the syncing mode for the Parity node'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onChange={ this.onChangeMode }
|
||||||
value={ mode }
|
value={ mode }
|
||||||
>
|
options={ [
|
||||||
<Dropdown
|
this.renderItem('active', (
|
||||||
item
|
<FormattedMessage
|
||||||
text={ mode }
|
id='settings.parity.modes.mode_active'
|
||||||
options={ [
|
defaultMessage='Continuously sync'
|
||||||
this.renderItem('active', this.onChangeMode, (
|
/>
|
||||||
<FormattedMessage
|
)),
|
||||||
id='settings.parity.modes.mode_active'
|
this.renderItem('passive', (
|
||||||
defaultMessage='Continuously sync'
|
<FormattedMessage
|
||||||
/>
|
id='settings.parity.modes.mode_passive'
|
||||||
)),
|
defaultMessage='Sync on intervals'
|
||||||
this.renderItem('passive', this.onChangeMode, (
|
/>
|
||||||
<FormattedMessage
|
)),
|
||||||
id='settings.parity.modes.mode_passive'
|
this.renderItem('dark', (
|
||||||
defaultMessage='Sync on intervals'
|
<FormattedMessage
|
||||||
/>
|
id='settings.parity.modes.mode_dark'
|
||||||
)),
|
defaultMessage='Sync when RPC is active'
|
||||||
this.renderItem('dark', this.onChangeMode, (
|
/>
|
||||||
<FormattedMessage
|
)),
|
||||||
id='settings.parity.modes.mode_dark'
|
this.renderItem('offline', (
|
||||||
defaultMessage='Sync when RPC is active'
|
<FormattedMessage
|
||||||
/>
|
id='settings.parity.modes.mode_offline'
|
||||||
)),
|
defaultMessage='No Syncing'
|
||||||
this.renderItem('offline', this.onChangeMode, (
|
/>
|
||||||
<FormattedMessage
|
))
|
||||||
id='settings.parity.modes.mode_offline'
|
] }
|
||||||
defaultMessage='No Syncing'
|
/>
|
||||||
/>
|
|
||||||
))
|
|
||||||
] }
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -178,78 +174,76 @@ export default class Node extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ layout.option }>
|
<div className={ layout.option }>
|
||||||
<FormattedMessage
|
<Dropdown
|
||||||
id='settings.parity.chains.hint'
|
|
||||||
defaultMessage='Choose the chain for the Parity node to sync to'
|
|
||||||
/>
|
|
||||||
<Menu
|
|
||||||
vertical
|
|
||||||
id='parityChainSelect'
|
id='parityChainSelect'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.hint'
|
||||||
|
defaultMessage='Choose the chain for the Parity node to sync to'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onChange={ this.onChangeChain }
|
||||||
value={ chain }
|
value={ chain }
|
||||||
>
|
options={ [
|
||||||
<Dropdown
|
this.renderItem('foundation', (
|
||||||
text={ chain }
|
<FormattedMessage
|
||||||
options={ [
|
id='settings.parity.chains.chain_foundation'
|
||||||
this.renderItem('foundation', this.onChangeChain, (
|
defaultMessage='Ethereum Foundation'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_foundation'
|
)),
|
||||||
defaultMessage='Ethereum Foundation'
|
this.renderItem('kovan', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_kovan'
|
||||||
this.renderItem('kovan', this.onChangeChain, (
|
defaultMessage='Kovan test network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_kovan'
|
)),
|
||||||
defaultMessage='Kovan test network'
|
this.renderItem('olympic', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_olympic'
|
||||||
this.renderItem('olympic', this.onChangeChain, (
|
defaultMessage='Olympic test network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_olympic'
|
)),
|
||||||
defaultMessage='Olympic test network'
|
this.renderItem('morden', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.cmorden_kovan'
|
||||||
this.renderItem('morden', this.onChangeChain, (
|
defaultMessage='Morden (Classic) test network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.cmorden_kovan'
|
)),
|
||||||
defaultMessage='Morden (Classic) test network'
|
this.renderItem('ropsten', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_ropsten'
|
||||||
this.renderItem('ropsten', this.onChangeChain, (
|
defaultMessage='Ropsten test network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_ropsten'
|
)),
|
||||||
defaultMessage='Ropsten test network'
|
this.renderItem('classic', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_classic'
|
||||||
this.renderItem('classic', this.onChangeChain, (
|
defaultMessage='Ethereum Classic network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_classic'
|
)),
|
||||||
defaultMessage='Ethereum Classic network'
|
this.renderItem('expanse', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_expanse'
|
||||||
this.renderItem('expanse', this.onChangeChain, (
|
defaultMessage='Expanse network'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_expanse'
|
)),
|
||||||
defaultMessage='Expanse network'
|
this.renderItem('dev', (
|
||||||
/>
|
<FormattedMessage
|
||||||
)),
|
id='settings.parity.chains.chain_dev'
|
||||||
this.renderItem('dev', this.onChangeChain, (
|
defaultMessage='Local development chain'
|
||||||
<FormattedMessage
|
/>
|
||||||
id='settings.parity.chains.chain_dev'
|
))
|
||||||
defaultMessage='Local development chain'
|
] }
|
||||||
/>
|
/>
|
||||||
))
|
|
||||||
] }
|
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeMode = (e, mode) => {
|
onChangeMode = (event, mode) => {
|
||||||
this.store.changeMode(mode.name);
|
this.store.changeMode(mode.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeChain = (e, chain) => {
|
onChangeChain = (event, chain) => {
|
||||||
this.store.changeChain(chain.name);
|
this.store.changeChain(chain.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ describe('views/Settings/Node', () => {
|
|||||||
let select;
|
let select;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
select = component.find('Menu[id="parityModeSelect"]');
|
select = component.find('Dropdown[id="parityModeSelect"]');
|
||||||
sinon.spy(instance.store, 'changeMode');
|
sinon.spy(instance.store, 'changeMode');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ describe('views/Settings/Node', () => {
|
|||||||
let select;
|
let select;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
select = component.find('Menu[id="parityChainSelect"]');
|
select = component.find('Dropdown[id="parityChainSelect"]');
|
||||||
sinon.spy(instance.store, 'changeChain');
|
sinon.spy(instance.store, 'changeChain');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,15 +16,16 @@
|
|||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Menu } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
import { Page } from '@parity/ui';
|
import { Page, Tabs } from '@parity/ui';
|
||||||
import { BackgroundIcon, EthernetIcon, VisibleIcon } from '@parity/ui/Icons';
|
import { BackgroundIcon, EthernetIcon, VisibleIcon } from '@parity/ui/Icons';
|
||||||
|
|
||||||
import imagesEthcoreBlock from '~/../assets/images/parity-logo-white-no-text.svg';
|
import imagesEthcoreBlock from '~/../assets/images/parity-logo-white-no-text.svg';
|
||||||
|
|
||||||
import styles from './settings.css';
|
import styles from './settings.css';
|
||||||
|
|
||||||
|
const TABS = ['views', 'background', 'proxy', 'parity'];
|
||||||
|
|
||||||
export default class Settings extends Component {
|
export default class Settings extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object.isRequired
|
router: PropTypes.object.isRequired
|
||||||
@ -36,22 +37,36 @@ export default class Settings extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { children } = this.props;
|
const { children } = this.props;
|
||||||
const hash = (window.location.hash || '').split('?')[0].split('/')[2];
|
const hash = (window.location.hash || '').split('?')[0].split('/')[1];
|
||||||
const isProxied = window.location.hostname.indexOf('.parity') !== -1;
|
const isProxied = window.location.hostname.indexOf('.parity') !== -1;
|
||||||
let proxy = null;
|
|
||||||
|
|
||||||
if (!isProxied) {
|
|
||||||
proxy = this.renderTab(hash, 'proxy', <EthernetIcon />);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Menu className={ styles.tabs } name={ hash }>
|
<Tabs
|
||||||
{ this.renderTab(hash, 'views', <VisibleIcon />) }
|
activeTab={ TABS.indexOf(hash) }
|
||||||
{ this.renderTab(hash, 'background', <BackgroundIcon />) }
|
className={ styles.tabs }
|
||||||
{ proxy }
|
onChange={ this.onActivate }
|
||||||
{ this.renderTab(hash, 'parity', <img src={ imagesEthcoreBlock } className={ styles.imageIcon } />) }
|
tabs={ [
|
||||||
</Menu>
|
{
|
||||||
|
icon: <VisibleIcon />,
|
||||||
|
label: <FormattedMessage id='settings.views.label' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <BackgroundIcon />,
|
||||||
|
label: <FormattedMessage id='settings.background.label' />
|
||||||
|
},
|
||||||
|
isProxied
|
||||||
|
? null
|
||||||
|
: {
|
||||||
|
icon: <EthernetIcon />,
|
||||||
|
label: <FormattedMessage id='settings.proxy.label' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <img src={ imagesEthcoreBlock } className={ styles.imageIcon } />,
|
||||||
|
label: <FormattedMessage id='settings.parity.label' />
|
||||||
|
}
|
||||||
|
] }
|
||||||
|
/>
|
||||||
<Page>
|
<Page>
|
||||||
{ children }
|
{ children }
|
||||||
</Page>
|
</Page>
|
||||||
@ -59,32 +74,9 @@ export default class Settings extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTab (hash, name, icon) {
|
onActivate = (event, tabIndex) => {
|
||||||
return (
|
|
||||||
<Menu.Item
|
|
||||||
className={
|
|
||||||
hash === name
|
|
||||||
? styles.tabactive
|
|
||||||
: styles.tab
|
|
||||||
}
|
|
||||||
icon={ icon }
|
|
||||||
key={ name }
|
|
||||||
content={
|
|
||||||
<div className={ styles.menu }>
|
|
||||||
<FormattedMessage id={ `settings.${name}.label` } />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
onClick={ this.onActivate(name) }
|
|
||||||
name={ name }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onActivate = (name) => {
|
|
||||||
const { router } = this.context;
|
const { router } = this.context;
|
||||||
|
|
||||||
return (event) => {
|
router.push(`/${TABS[tabIndex]}`);
|
||||||
router.push(`/${name}`);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { MenuItem, IconMenu } from 'material-ui';
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
@ -23,7 +22,7 @@ import { bindActionCreators } from 'redux';
|
|||||||
|
|
||||||
import { bytesToHex } from '@parity/api/util/format';
|
import { bytesToHex } from '@parity/api/util/format';
|
||||||
import { confirmOperation, revokeOperation } from '@parity/shared/redux/providers/walletActions';
|
import { confirmOperation, revokeOperation } from '@parity/shared/redux/providers/walletActions';
|
||||||
import { Button, Container, InputAddress, IdentityIcon, Progress } from '@parity/ui';
|
import { Container, Dropdown, InputAddress, IdentityIcon, Progress } from '@parity/ui';
|
||||||
import TxRow from '@parity/ui/TxList/TxRow';
|
import TxRow from '@parity/ui/TxList/TxRow';
|
||||||
|
|
||||||
import styles from '../wallet.css';
|
import styles from '../wallet.css';
|
||||||
@ -89,14 +88,13 @@ class WalletConfirmations extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return realConfirmations
|
return realConfirmations.map((confirmation) => (
|
||||||
.map((confirmation) => (
|
<WalletConfirmation
|
||||||
<WalletConfirmation
|
key={ confirmation.operation }
|
||||||
key={ confirmation.operation }
|
confirmation={ confirmation }
|
||||||
confirmation={ confirmation }
|
{ ...others }
|
||||||
{ ...others }
|
/>
|
||||||
/>
|
));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,13 +128,9 @@ class WalletConfirmation extends Component {
|
|||||||
revokeOperation: PropTypes.func.isRequired
|
revokeOperation: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
|
||||||
openConfirm: false,
|
|
||||||
openRevoke: false
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { confirmation } = this.props;
|
const { confirmation } = this.props;
|
||||||
|
const { pending } = confirmation;
|
||||||
const confirmationsRows = [];
|
const confirmationsRows = [];
|
||||||
|
|
||||||
const className = styles.light;
|
const className = styles.light;
|
||||||
@ -158,65 +152,30 @@ class WalletConfirmation extends Component {
|
|||||||
{ confirmationsRows }
|
{ confirmationsRows }
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{ this.renderPending() }
|
{
|
||||||
|
pending && (
|
||||||
|
<div className={ styles.pendingOverlay } />
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPending () {
|
handleConfirm = (event, owner) => {
|
||||||
const { pending } = this.props.confirmation;
|
|
||||||
|
|
||||||
if (!pending) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={ styles.pendingOverlay } />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenConfirm = () => {
|
|
||||||
this.setState({
|
|
||||||
openConfirm: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCloseConfirm = () => {
|
|
||||||
this.setState({
|
|
||||||
openConfirm: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenRevoke = () => {
|
|
||||||
this.setState({
|
|
||||||
openRevoke: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCloseRevoke = () => {
|
|
||||||
this.setState({
|
|
||||||
openRevoke: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleConfirm = (e, item) => {
|
|
||||||
const { confirmOperation, confirmation, address } = this.props;
|
const { confirmOperation, confirmation, address } = this.props;
|
||||||
const owner = item.props.value;
|
|
||||||
|
|
||||||
confirmOperation(address, owner, confirmation.operation);
|
confirmOperation(address, owner, confirmation.operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRevoke = (e, item) => {
|
handleRevoke = (event, owner) => {
|
||||||
const { revokeOperation, confirmation, address } = this.props;
|
const { revokeOperation, confirmation, address } = this.props;
|
||||||
const owner = item.props.value;
|
|
||||||
|
|
||||||
revokeOperation(address, owner, confirmation.operation);
|
revokeOperation(address, owner, confirmation.operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderActions (confirmation, className) {
|
renderActions (confirmation, className) {
|
||||||
const { owners, accounts } = this.props;
|
const { owners, accounts } = this.props;
|
||||||
const { operation, confirmedBy, pending } = confirmation;
|
const { operation, confirmedBy } = confirmation;
|
||||||
const { openConfirm, openRevoke } = this.state;
|
|
||||||
|
|
||||||
const addresses = Object.keys(accounts);
|
const addresses = Object.keys(accounts);
|
||||||
|
|
||||||
@ -228,32 +187,6 @@ class WalletConfirmation extends Component {
|
|||||||
.filter((owner) => addresses.includes(owner))
|
.filter((owner) => addresses.includes(owner))
|
||||||
.filter((owner) => confirmedBy.includes(owner));
|
.filter((owner) => confirmedBy.includes(owner));
|
||||||
|
|
||||||
const confirmButton = (
|
|
||||||
<Button
|
|
||||||
onClick={ this.handleOpenConfirm }
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='wallet.confirmations.buttons.confirmAs'
|
|
||||||
defaultMessage='Confirm As...'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
disabled={ pending || possibleConfirm.length === 0 }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const revokeButton = (
|
|
||||||
<Button
|
|
||||||
onClick={ this.handleOpenRevoke }
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='wallet.confirmations.buttons.revokeAs'
|
|
||||||
defaultMessage='Revoke As...'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
disabled={ pending || possibleRevoke.length === 0 }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
className={ className }
|
className={ className }
|
||||||
@ -262,23 +195,30 @@ class WalletConfirmation extends Component {
|
|||||||
<td />
|
<td />
|
||||||
<td colSpan={ 3 }>
|
<td colSpan={ 3 }>
|
||||||
<div className={ styles.actions }>
|
<div className={ styles.actions }>
|
||||||
<IconMenu
|
<Dropdown
|
||||||
iconButtonElement={ confirmButton }
|
label={
|
||||||
open={ openConfirm }
|
<FormattedMessage
|
||||||
onRequestChange={ this.handleCloseConfirm }
|
id='wallet.confirmations.buttons.confirmAs'
|
||||||
onItemTouchTap={ this.handleConfirm }
|
defaultMessage='Confirm As...'
|
||||||
>
|
/>
|
||||||
{ possibleConfirm.map((address) => this.renderAccountItem(address)) }
|
}
|
||||||
</IconMenu>
|
onChange={ this.handleConfirm }
|
||||||
|
options={
|
||||||
<IconMenu
|
possibleConfirm.map((address) => this.renderAccountItem(address))
|
||||||
iconButtonElement={ revokeButton }
|
}
|
||||||
open={ openRevoke }
|
/>
|
||||||
onRequestChange={ this.handleCloseRevoke }
|
<Dropdown
|
||||||
onItemTouchTap={ this.handleRevoke }
|
label={
|
||||||
>
|
<FormattedMessage
|
||||||
{ possibleRevoke.map((address) => this.renderAccountItem(address)) }
|
id='wallet.confirmations.buttons.revokeAs'
|
||||||
</IconMenu>
|
defaultMessage='Revoke As...'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onChange={ this.handleRevoke }
|
||||||
|
oprions={
|
||||||
|
possibleRevoke.map((address) => this.renderAccountItem(address))
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
@ -288,22 +228,22 @@ class WalletConfirmation extends Component {
|
|||||||
|
|
||||||
renderAccountItem (address) {
|
renderAccountItem (address) {
|
||||||
const account = this.props.accounts[address];
|
const account = this.props.accounts[address];
|
||||||
|
const name = account.name.toUpperCase() || account.address;
|
||||||
|
|
||||||
return (
|
return {
|
||||||
<MenuItem
|
key: address,
|
||||||
key={ address }
|
label: (
|
||||||
value={ address }
|
|
||||||
>
|
|
||||||
<div className={ styles.accountItem }>
|
<div className={ styles.accountItem }>
|
||||||
<IdentityIcon
|
<IdentityIcon
|
||||||
address={ address }
|
address={ address }
|
||||||
center
|
center
|
||||||
inline
|
inline
|
||||||
/>
|
/>
|
||||||
<span>{ account.name.toUpperCase() || account.address }</span>
|
<span>{ name }</span>
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
),
|
||||||
);
|
value: name
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProgress (confirmation) {
|
renderProgress (confirmation) {
|
||||||
@ -398,18 +338,6 @@ class WalletConfirmation extends Component {
|
|||||||
renderConfirmedBy (confirmation, className) {
|
renderConfirmedBy (confirmation, className) {
|
||||||
const { operation, confirmedBy } = confirmation;
|
const { operation, confirmedBy } = confirmation;
|
||||||
|
|
||||||
const confirmed = confirmedBy.map((owner) => (
|
|
||||||
<InputAddress
|
|
||||||
key={ owner }
|
|
||||||
value={ owner }
|
|
||||||
allowCopy={ false }
|
|
||||||
hideUnderline
|
|
||||||
disabled
|
|
||||||
small
|
|
||||||
text
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={ `details_${operation}` } className={ className }>
|
<tr key={ `details_${operation}` } className={ className }>
|
||||||
<td colSpan={ 5 } style={ { padding: 0 } }>
|
<td colSpan={ 5 } style={ { padding: 0 } }>
|
||||||
@ -419,7 +347,19 @@ class WalletConfirmation extends Component {
|
|||||||
data-effect='solid'
|
data-effect='solid'
|
||||||
className={ styles.confirmed }
|
className={ styles.confirmed }
|
||||||
>
|
>
|
||||||
{ confirmed }
|
{
|
||||||
|
confirmedBy.map((owner) => (
|
||||||
|
<InputAddress
|
||||||
|
key={ owner }
|
||||||
|
value={ owner }
|
||||||
|
allowCopy={ false }
|
||||||
|
hideUnderline
|
||||||
|
disabled
|
||||||
|
small
|
||||||
|
text
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user