Basic UI structure in-place

This commit is contained in:
Jaco Greeff 2016-12-12 18:30:41 +01:00
parent 7a0fccf417
commit a2a89f7e59
8 changed files with 253 additions and 101 deletions

View File

@ -14,4 +14,4 @@
// 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 './upgrade';
export default from './updating';

View File

@ -17,17 +17,15 @@
import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
import styles from './.css';
@observer
export default class Upgrade extends Component {
export default class Updating extends Component {
static propTypes = {
store: PropTypes.object.isRequired
}
render () {
return (
<div className={ styles.body }>hello</div>
<div>hello</div>
);
}
}

View File

@ -0,0 +1,17 @@
// Copyright 2015, 2016 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 './upgradeParity';

View File

@ -0,0 +1,97 @@
// Copyright 2015, 2016 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 { action, computed, observable, transaction } from 'mobx';
import store from 'store';
const LS_UPDATE = '_parity::update';
const A_DAY = 24 * 60 * 60 * 1000;
const STEP_INFO = 1;
const STEP_UPDATING = 2;
const STEP_COMPLETED = 3;
const STEP_ERROR = 4;
export default class ModalStore {
@observable closed = false;
@observable error = null;
@observable step = 0;
@observable upgrade = null;
constructor (upgradeStore) {
this.upgrade = upgradeStore;
this.loadStorage();
}
@computed get showUpgrade () {
return !closed && Date.now() >= this.remindAt;
}
@action closeModal = () => {
transaction(() => {
this.closed = true;
this.setStep(STEP_INFO);
});
}
@action loadStorage = () => {
const values = store.get(LS_UPDATE) || {};
this.remindAt = values.remindAt ? values.remindAt : 0;
return values;
}
@action setStep = (step, error = null) => {
transaction(() => {
this.error = error;
this.setp = step;
});
}
@action snoozeTillTomorrow = () => {
this.remindAt = Date.now() + A_DAY;
store.set(LS_UPDATE, Object.assign(this.loadStorage(), { remindAt: this.remindAt }));
}
@action upgradeNow = () => {
this.setStep(STEP_UPDATING);
this.upgrade
.executeUpgrade()
.then((result) => {
if (!result) {
throw new Error('Unable to complete update');
}
this.setStep(STEP_COMPLETED);
})
.catch((error) => {
console.error('upgradeNow', error);
this.setStep(STEP_ERROR, error);
});
}
}
export {
STEP_COMPLETED,
STEP_ERROR,
STEP_INFO,
STEP_UPDATING
};

View File

@ -1,86 +0,0 @@
// Copyright 2015, 2016 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 { action, observable, transaction } from 'mobx';
import store from 'store';
const AN_HOUR = 60 * 60 * 1000;
const A_DAY = 24 * AN_HOUR;
const CHECK_INTERVAL = AN_HOUR;
const LS_UPDATE = '_parity::update';
export default class Store {
@observable availableUpgrade = null;
@observable remindAt = 0;
@observable showUpgrade = false;
constructor (api) {
this._api = api;
this.checkUpgrade();
setInterval(this.pollUpgrade, CHECK_INTERVAL);
}
@action loadStorage () {
const values = store.get(LS_UPDATE) || {};
this.remindAt = values.remindAt ? values.remindAt : 0;
return values;
}
@action setAvailableUpgrade (availableUpgrade, consensusCapability) {
transaction(() => {
this.setConsensusCapability(consensusCapability);
this.availableUpgrade = availableUpgrade;
if (availableUpgrade && Date.now() >= this.remindAt) {
this.showUpgrade = true;
}
});
}
@action setConsensusCapability (consensusCapability) {
this.consensusCapability = consensusCapability;
}
@action snoozeTillTomorrow () {
store.set(LS_UPDATE, Object.assign(this.loadStorage(), {
remindAt: Date.now() + A_DAY
}));
}
checkUpgrade = () => {
this.loadStorage();
return Promise
.all([
this._api.parity.upgradeReady(),
this._api.parity.consensusCapability()
])
.then(([availableUpgrade, consensusCapability]) => {
this.setAvailableUpgrade(availableUpgrade, consensusCapability);
})
.catch((error) => {
console.warn('checkUpgrade', error);
});
}
executeUpgrade = () => {
return this._api.parity
.executeUpgrade();
}
}

View File

@ -16,10 +16,16 @@
import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, Modal } from '~/ui';
import { CancelIcon, DoneIcon, NextIcon, SnoozeIcon } from '~/ui/Icons';
import Store from './store';
import Info from './Info';
import Updating from './Updating';
import ModalStore, { STEP_COMPLETED, STEP_ERROR, STEP_INFO, STEP_UPDATING } from './modalStore';
import UpgradeStore from './upgradeStore';
@observer
export default class UpgradeParity extends Component {
@ -27,21 +33,84 @@ export default class UpgradeParity extends Component {
api: PropTypes.object.isRequired
};
store = new Store(this.context.api);
store = new ModalStore(new UpgradeStore(this.context.api));
render () {
if (!this.store.showUpgrade) {
if (!this.store.upgrade.available || !this.store.showUpgrade) {
return null;
}
return (
<Modal
buttons={ [
<Button />
] }
actions={ this.renderActions() }
visible>
<div />
{ this.renderStep() }
</Modal>
);
}
renderActions () {
const closeButton =
<Button
icon={ <CancelIcon /> }
label={
<FormattedMessage
id='upgradeParity.button.close'
defaultMessage='close' />
}
onClick={ this.store.closeModal } />;
const doneButton =
<Button
icon={ <DoneIcon /> }
label={
<FormattedMessage
id='upgradeParity.button.done'
defaultMessage='done' />
}
onClick={ this.store.closeModal } />;
switch (this.store.step) {
case STEP_INFO:
return [
<Button
icon={ <SnoozeIcon /> }
label={
<FormattedMessage
id='upgradeParity.button.snooze'
defaultMessage='ask me tomorrow' />
}
onClick={ this.store.snoozeTillTomorrow } />,
<Button
icon={ <NextIcon /> }
label={
<FormattedMessage
id='upgradeParity.button.upgrade'
defaultMessage='upgrade now' />
}
onClick={ this.store.upgradeNow } />,
closeButton
];
case STEP_UPDATING:
return [
closeButton
];
case STEP_COMPLETED:
case STEP_ERROR:
return [
doneButton
];
}
}
renderStep () {
switch (this.store.step) {
case STEP_INFO:
return <Info store={ this.store } />;
case STEP_UPDATING:
return <Updating store={ this.store } />;
}
}
}

View File

@ -0,0 +1,57 @@
// Copyright 2015, 2016 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 { action, observable, transaction } from 'mobx';
const CHECK_INTERVAL = 1 * 60 * 1000;
export default class UpgradeStore {
@observable available = null;
@observable consensusCapability = null;
constructor (api) {
this._api = api;
this.checkUpgrade();
setInterval(this.checkUpgrade, CHECK_INTERVAL);
}
@action setAvailableUpgrade (available, consensusCapability) {
transaction(() => {
this.available = available;
this.consensusCapability = consensusCapability;
});
}
checkUpgrade = () => {
return Promise
.all([
this._api.parity.upgradeReady(),
this._api.parity.consensusCapability()
])
.then(([available, consensusCapability]) => {
console.log('[checkUpgrade]', 'available:', available, 'consensusCapability:', consensusCapability);
this.setAvailableUpgrade(available, consensusCapability);
})
.catch((error) => {
console.warn('checkUpgrade', error);
});
}
executeUpgrade = () => {
return this._api.parity.executeUpgrade();
}
}

View File

@ -42,11 +42,11 @@ class Modal extends Component {
className: PropTypes.string,
compact: PropTypes.bool,
current: PropTypes.number,
waiting: PropTypes.array,
settings: PropTypes.object.isRequired,
steps: PropTypes.array,
title: nodeOrStringProptype(),
visible: PropTypes.bool.isRequired,
settings: PropTypes.object.isRequired
waiting: PropTypes.array
}
render () {
@ -65,13 +65,13 @@ class Modal extends Component {
return (
<Dialog
className={ classes }
actions={ actions }
actionsContainerStyle={ ACTIONS_STYLE }
autoDetectWindowHeight={ false }
autoScrollBodyContent
actionsContainerClassName={ styles.actions }
bodyClassName={ styles.body }
className={ classes }
contentClassName={ styles.content }
contentStyle={ contentStyle }
modal