integration: state with powergate and transforms

This commit is contained in:
jimmylee 2020-06-03 23:26:20 -07:00
parent 57876efbef
commit aa70f67d82
12 changed files with 599 additions and 399 deletions

View File

@ -1,5 +1,6 @@
# What is this? # What is this?
- A [live example](https://filecoin.onrender.com) of how to use the Filecoin Network.
- An open source desktop client for using [Textile's Powergate](https://github.com/textileio/powergate/). - An open source desktop client for using [Textile's Powergate](https://github.com/textileio/powergate/).
- An [open source design system](https://filecoin.onrender.com) for building your own applications that are compatible with [Textile's Powergate](https://github.com/textileio/powergate/). - An [open source design system](https://filecoin.onrender.com) for building your own applications that are compatible with [Textile's Powergate](https://github.com/textileio/powergate/).
- A kitchen sink example repository and multiple files to take example code snippets from for your own projects. - A kitchen sink example repository and multiple files to take example code snippets from for your own projects.

View File

@ -1,5 +1,6 @@
import 'isomorphic-fetch'; import 'isomorphic-fetch';
import * as State from '~/common/state';
import * as Strings from '~/common/strings'; import * as Strings from '~/common/strings';
const REQUEST_HEADERS = { const REQUEST_HEADERS = {
@ -9,6 +10,20 @@ const REQUEST_HEADERS = {
const SERVER_PATH = ''; const SERVER_PATH = '';
export const rehydrateViewer = async () => {
const options = {
method: 'POST',
headers: REQUEST_HEADERS,
credentials: 'include',
body: JSON.stringify({}),
};
const response = await fetch(`/_/viewer`, options);
const json = await response.json();
return State.getInitialState(json.data);
};
export const createWalletAddress = async (data) => { export const createWalletAddress = async (data) => {
if (Strings.isEmpty(data.name)) { if (Strings.isEmpty(data.name)) {
return null; return null;

View File

@ -9,10 +9,7 @@ const LOCAL_CONFIG = `
} }
`; `;
export const getInitialState = (props) => { export const getInitialState = () => {
const { status, messageList, peersList, addrsList, info } = props;
console.log(props);
return { return {
name: 'Andrew Hill', name: 'Andrew Hill',
photoURL: '/static/avatar-andrew-hill.jpg', photoURL: '/static/avatar-andrew-hill.jpg',

72
common/state.js Normal file
View File

@ -0,0 +1,72 @@
const STATIC_ADDRESS_TYPE_MAP = { bls: 'BLS' };
const transformAddresses = (addrsList, info) => {
const balanceMap = {};
info.balancesList.forEach((b) => {
balanceMap[b.addr.addr] = b.balance;
});
return addrsList.map((each, index) => {
return {
value: `${index + 1}`,
balance: balanceMap[each.addr],
name: each.name,
address: each.addr,
type: STATIC_ADDRESS_TYPE_MAP[each.type],
deals: 0,
transactions: [],
};
});
};
const transformPeers = (peersList) => {
return peersList.map((each) => {
return {
id: each.addrInfo.id,
'peer-avatar': null,
'chain-head': null,
height: null,
location: each.location.country,
upload: null,
download: null,
};
});
};
export const getInitialState = (props) => {
const { status, messageList, peersList, addrsList, info } = props;
console.log(props);
return {
id: info.id,
name: 'Andrew Hill',
photoURL: '/static/avatar-andrew-hill.jpg',
config: '',
upload_bandwidth: 0,
download_bandwidth: 0,
settings_deals_auto_approve: true,
settings_hot_enabled: info.defaultConfig.hot.enabled,
settings_hot_allow_unfreeze: info.defaultConfig.hot.allowUnfreeze,
settings_hot_ipfs_add_timeout: info.defaultConfig.hot.ipfs.addTimeout,
settings_cold_enabled: info.defaultConfig.cold.enabled,
settings_cold_default_address: info.defaultConfig.cold.filecoin.addr,
settings_cold_default_duration: info.defaultConfig.cold.filecoin.dealDuration,
settings_cold_default_replication_factor: info.defaultConfig.cold.filecoin.repFactor,
settings_cold_default_excluded_miners: info.defaultConfig.cold.filecoin.excludedMinersList,
settings_cold_default_trusted_miners: info.defaultConfig.cold.filecoin.trustedMinersList,
settings_cold_default_max_price: info.defaultConfig.cold.filecoin.maxPrice,
settings_cold_default_auto_renew: info.defaultConfig.cold.filecoin.renew.enabled,
settings_cold_default_auto_renew_max_price: info.defaultConfig.cold.filecoin.renew.threshold,
notifications: [],
payment_channels_active: [],
payment_channels_redeemed: [],
data_transfers: [],
peers: transformPeers(peersList),
deals: [],
addresses: transformAddresses(addrsList, info),
};
};

View File

@ -1,32 +1,31 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as SVG from "~/components/system/svg"; import * as SVG from '~/components/system/svg';
import * as System from "~/components/system"; import * as System from '~/components/system';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
const SELECT_MENU_OPTIONS = [ const SELECT_MENU_OPTIONS = [
{ value: "1", name: "SECP256K1" }, { value: '1', name: 'BLS' },
{ value: "2", name: "BLS" }, { value: '2', name: 'SECP256K1' },
{ value: "3", name: "MULTISIG" }, { value: '3', name: 'MULTISIG' },
]; ];
const SELECT_MENU_MAP = { const SELECT_MENU_MAP = {
"1": "SECP256K1", '1': 'BLS',
"2": "BLS", '2': 'SECP256K1',
"3": "MULTISIG", '3': 'MULTISIG',
}; };
export default class SidebarCreateWalletAddress extends React.Component { export default class SidebarCreateWalletAddress extends React.Component {
state = { state = {
name: "", name: '',
type: "1", type: '1',
}; };
_handleSubmit = () => { _handleSubmit = () => {
alert("TODO: Create a new wallet address"); this.props.onSubmit({ name: this.state.name, type: 'CREATE_WALLET_ADDRESS' });
this.props.onSubmit({});
}; };
_handleCancel = () => { _handleCancel = () => {
@ -40,9 +39,7 @@ export default class SidebarCreateWalletAddress extends React.Component {
render() { render() {
return ( return (
<div> <div>
<System.P style={{ fontFamily: "inter-semi-bold" }}> <System.P style={{ fontFamily: 'inter-semi-bold' }}>Create a new address</System.P>
Create a new address
</System.P>
<System.Input <System.Input
containerStyle={{ marginTop: 24 }} containerStyle={{ marginTop: 24 }}
@ -59,15 +56,11 @@ export default class SidebarCreateWalletAddress extends React.Component {
value={this.state.type} value={this.state.type}
category="type" category="type"
onChange={this._handleChange} onChange={this._handleChange}
options={SELECT_MENU_OPTIONS} options={SELECT_MENU_OPTIONS}>
>
{SELECT_MENU_MAP[this.state.type]} {SELECT_MENU_MAP[this.state.type]}
</System.SelectMenuFull> </System.SelectMenuFull>
<System.ButtonPrimaryFull <System.ButtonPrimaryFull style={{ marginTop: 48 }} onClick={this._handleSubmit}>
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Create {this.state.name} Create {this.state.name}
</System.ButtonPrimaryFull> </System.ButtonPrimaryFull>
</div> </div>

View File

@ -1,19 +1,19 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as SVG from "~/components/system/svg"; import * as SVG from '~/components/system/svg';
import * as System from "~/components/system"; import * as System from '~/components/system';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
const STYLES_FOCUS = css` const STYLES_FOCUS = css`
font-size: ${Constants.typescale.lvl1}; font-size: ${Constants.typescale.lvl1};
font-family: "inter-medium"; font-family: 'inter-medium';
overflow-wrap: break-word; overflow-wrap: break-word;
width: 100%; width: 100%;
strong { strong {
font-family: "inter-semi-bold"; font-family: 'inter-semi-bold';
font-weight: 400; font-weight: 400;
} }
`; `;
@ -29,13 +29,30 @@ const STYLES_ITEM = css`
export default class SidebarWalletSendFunds extends React.Component { export default class SidebarWalletSendFunds extends React.Component {
state = { state = {
address: "", address: '',
amount: "", amount: '',
}; };
_handleSubmit = () => { _handleSubmit = () => {
alert("TODO: Send Filecoin"); let addresses = {};
this.props.onSubmit({});
this.props.viewer.addresses.forEach((a) => {
addresses[a.value] = a;
});
const currentAddress = addresses[this.props.selected.address];
if (currentAddress.address === this.state.address) {
alert('TODO: Proper message for not allowing poeple to send funds to the same address.');
return;
}
this.props.onSubmit({
type: 'SEND_WALLET_ADDRESS_FILECOIN',
source: currentAddress.address,
target: this.state.address,
amount: this.state.amount,
});
}; };
_handleCancel = () => { _handleCancel = () => {
@ -57,9 +74,7 @@ export default class SidebarWalletSendFunds extends React.Component {
return ( return (
<React.Fragment> <React.Fragment>
<System.P style={{ fontFamily: "inter-semi-bold" }}> <System.P style={{ fontFamily: 'inter-semi-bold' }}>Send Filecoin</System.P>
Send Filecoin
</System.P>
<System.SelectMenuFull <System.SelectMenuFull
containerStyle={{ marginTop: 24 }} containerStyle={{ marginTop: 24 }}
@ -68,8 +83,7 @@ export default class SidebarWalletSendFunds extends React.Component {
value={this.props.selected.address} value={this.props.selected.address}
category="address" category="address"
onChange={this.props.onSelectedChange} onChange={this.props.onSelectedChange}
options={this.props.viewer.addresses} options={this.props.viewer.addresses}>
>
{currentAddress.name} {currentAddress.name}
</System.SelectMenuFull> </System.SelectMenuFull>
@ -99,10 +113,7 @@ export default class SidebarWalletSendFunds extends React.Component {
<div css={STYLES_SUBTEXT}>Total Filecoin</div> <div css={STYLES_SUBTEXT}>Total Filecoin</div>
</div> </div>
<System.ButtonPrimaryFull <System.ButtonPrimaryFull style={{ marginTop: 48 }} onClick={this._handleSubmit}>
style={{ marginTop: 48 }}
onClick={this._handleSubmit}
>
Send Send
</System.ButtonPrimaryFull> </System.ButtonPrimaryFull>
</React.Fragment> </React.Fragment>

View File

@ -1,6 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import * as Fixtures from '~/common/fixtures'; import * as Fixtures from '~/common/fixtures';
import * as Actions from '~/common/actions'; import * as Actions from '~/common/actions';
import * as State from '~/common/state';
import SceneDataTransfer from '~/scenes/SceneDataTransfer'; import SceneDataTransfer from '~/scenes/SceneDataTransfer';
import SceneDeals from '~/scenes/SceneDeals'; import SceneDeals from '~/scenes/SceneDeals';
@ -62,8 +63,6 @@ const getCurrentNavigationStateById = (navigation, targetId) => {
}; };
export const getServerSideProps = (context) => { export const getServerSideProps = (context) => {
// NOTE(jim)
// will be passed to the page component as props
return { return {
props: { ...context.query }, props: { ...context.query },
}; };
@ -77,20 +76,38 @@ export default class IndexPage extends React.Component {
selected: { selected: {
address: '1', address: '1',
}, },
viewer: Fixtures.getInitialState(this.props), viewer: this.props.production ? Fixtures.getInitialState() : State.getInitialState(this.props),
sidebar: null, sidebar: null,
}; };
async componentDidMount() { async componentDidMount() {
let response; // TODO(jim): You don't really need this.
response = await Actions.createWalletAddress({ name: 'new wallet' }); console.log(this.props);
console.log(response);
response = await Actions.sendWalletAddressFilecoin({ source: null, target: null, amount: 1000 });
console.log(response);
} }
_handleSubmit = (data) => { _handleSubmit = async (data) => {
if (this.props.production) {
alert('TODO');
return this._handleDismissSidebar();
}
if (data.type === 'CREATE_WALLET_ADDRESS') {
const response = await Actions.createWalletAddress({ name: data.name });
const viewer = await Actions.rehydrateViewer();
this.setState({ viewer });
}
if (data.type === 'SEND_WALLET_ADDRESS_FILECOIN') {
const response = await Actions.sendWalletAddressFilecoin({
source: data.source,
target: data.target,
amount: data.amount,
});
const viewer = await Actions.rehydrateViewer();
this.setState({ viewer });
}
this._handleDismissSidebar(); this._handleDismissSidebar();
}; };
@ -227,8 +244,6 @@ export default class IndexPage extends React.Component {
}; };
render() { render() {
console.log(this.props);
const next = this.state.history[this.state.currentIndex]; const next = this.state.history[this.state.currentIndex];
const current = getCurrentNavigationStateById(Fixtures.NavigationState, next.id); const current = getCurrentNavigationStateById(Fixtures.NavigationState, next.id);

View File

@ -1,16 +1,16 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as Fixtures from "~/common/fixtures"; import * as Fixtures from '~/common/fixtures';
import * as System from "~/components/system"; import * as System from '~/components/system';
import * as SchemaTable from "~/common/schema-table"; import * as SchemaTable from '~/common/schema-table';
import * as Data from "~/common/data"; import * as Data from '~/common/data';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
import GLRenderer from "~/components/three/GLRenderer"; import GLRenderer from '~/components/three/GLRenderer';
import Section from "~/components/core/Section"; import Section from '~/components/core/Section';
import ScenePage from "~/components/core/ScenePage"; import ScenePage from '~/components/core/ScenePage';
const STYLES_ROW = css` const STYLES_ROW = css`
display: flex; display: flex;
@ -60,15 +60,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 14], ['2017-05-01 00:00:00 UTC', 14],
["2017-20-01 00:00:00 UTC", 16], ['2017-20-01 00:00:00 UTC', 16],
["2017-24-01 00:00:00 UTC", 2], ['2017-24-01 00:00:00 UTC', 2],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="GB" denomination="GB">
>
Total data stored Total data stored
</System.StatCard> </System.StatCard>
</span> </span>
@ -76,15 +75,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 65], ['2017-01-01 00:00:00 UTC', 65],
["2017-05-01 00:00:00 UTC", 12], ['2017-05-01 00:00:00 UTC', 12],
["2017-20-01 00:00:00 UTC", 2], ['2017-20-01 00:00:00 UTC', 2],
["2017-24-01 00:00:00 UTC", 20], ['2017-24-01 00:00:00 UTC', 20],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="GB" denomination="GB">
>
Total data retrieved Total data retrieved
</System.StatCard> </System.StatCard>
</span> </span>
@ -92,15 +90,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 12], ['2017-05-01 00:00:00 UTC', 12],
["2017-20-01 00:00:00 UTC", 16], ['2017-20-01 00:00:00 UTC', 16],
["2017-24-01 00:00:00 UTC", 33], ['2017-24-01 00:00:00 UTC', 33],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="Deals" denomination="Deals">
>
Total deals Total deals
</System.StatCard> </System.StatCard>
</span> </span>
@ -108,15 +105,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 22], ['2017-05-01 00:00:00 UTC', 22],
["2017-20-01 00:00:00 UTC", 44], ['2017-20-01 00:00:00 UTC', 44],
["2017-24-01 00:00:00 UTC", 20], ['2017-24-01 00:00:00 UTC', 20],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="FIL" denomination="FIL">
>
Wallet Balance Wallet Balance
</System.StatCard> </System.StatCard>
</span> </span>
@ -126,15 +122,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 12], ['2017-05-01 00:00:00 UTC', 12],
["2017-20-01 00:00:00 UTC", 12], ['2017-20-01 00:00:00 UTC', 12],
["2017-24-01 00:00:00 UTC", 20], ['2017-24-01 00:00:00 UTC', 20],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="FIL/GB/Month" denomination="FIL/GB/Month">
>
Your average storage price Your average storage price
</System.StatCard> </System.StatCard>
</span> </span>
@ -142,15 +137,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 23], ['2017-05-01 00:00:00 UTC', 23],
["2017-20-01 00:00:00 UTC", 16], ['2017-20-01 00:00:00 UTC', 16],
["2017-24-01 00:00:00 UTC", 20], ['2017-24-01 00:00:00 UTC', 20],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="FIL/GB" denomination="FIL/GB">
>
Your average retrieval price Your average retrieval price
</System.StatCard> </System.StatCard>
</span> </span>
@ -158,15 +152,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 7], ['2017-01-01 00:00:00 UTC', 7],
["2017-05-01 00:00:00 UTC", 12], ['2017-05-01 00:00:00 UTC', 12],
["2017-20-01 00:00:00 UTC", 16], ['2017-20-01 00:00:00 UTC', 16],
["2017-24-01 00:00:00 UTC", 23], ['2017-24-01 00:00:00 UTC', 23],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="FIL/GB/Month" denomination="FIL/GB/Month">
>
Average storage market price Average storage market price
</System.StatCard> </System.StatCard>
</span> </span>
@ -174,15 +167,14 @@ export default class SceneHome extends React.Component {
<span css={STYLES_COLUMN}> <span css={STYLES_COLUMN}>
<System.StatCard <System.StatCard
data={[ data={[
["2017-01-01 00:00:00 UTC", 47], ['2017-01-01 00:00:00 UTC', 47],
["2017-05-01 00:00:00 UTC", 42], ['2017-05-01 00:00:00 UTC', 42],
["2017-20-01 00:00:00 UTC", 46], ['2017-20-01 00:00:00 UTC', 46],
["2017-24-01 00:00:00 UTC", 40], ['2017-24-01 00:00:00 UTC', 40],
[new Date(), 24], [new Date(), 24],
]} ]}
value={1000} value={1000}
denomination="FIL/GB" denomination="FIL/GB">
>
Average market retrieval price Average market retrieval price
</System.StatCard> </System.StatCard>
</span> </span>
@ -194,24 +186,22 @@ export default class SceneHome extends React.Component {
title="Recent data" title="Recent data"
buttons={[ buttons={[
{ {
name: "View files", name: 'View files',
type: "NAVIGATE", type: 'NAVIGATE',
value: "folder-root", value: 'folder-root',
}, },
]} ]}>
>
<System.Table <System.Table
data={{ data={{
columns: [ columns: [
{ key: "file", name: "File", type: "FILE_LINK" }, { key: 'file', name: 'File', type: 'FILE_LINK' },
{ {
key: "date", key: 'date',
name: "Date uploaded", name: 'Date uploaded',
width: "160px", width: '160px',
tooltip: tooltip: 'This date represents when the file was first uploaded to the network.',
"This date represents when the file was first uploaded to the network.",
}, },
{ key: "remaining", name: "Remaining time", width: "180px" }, { key: 'remaining', name: 'Remaining time', width: '180px' },
], ],
rows: Data.EXAMPLE_FILES.slice(0, 4), rows: Data.EXAMPLE_FILES.slice(0, 4),
}} }}
@ -223,30 +213,31 @@ export default class SceneHome extends React.Component {
/> />
</Section> </Section>
<Section {this.props.viewer.addresses[0] ? (
onAction={this.props.onAction} <Section
onNavigateTo={this.props.onNavigateTo}
title="Recent transactions"
buttons={[
{
name: "View wallet",
type: "NAVIGATE",
value: 2,
},
]}
>
<System.Table
data={{
columns: SchemaTable.Transactions,
rows: this.props.viewer.addresses[0].transactions,
}}
selectedRowId={this.state.transaction}
onChange={this._handleChange}
onAction={this.props.onAction} onAction={this.props.onAction}
onNavigateTo={this.props.onNavigateTo} onNavigateTo={this.props.onNavigateTo}
name="transaction" title="Recent transactions"
/> buttons={[
</Section> {
name: 'View wallet',
type: 'NAVIGATE',
value: 2,
},
]}>
<System.Table
data={{
columns: SchemaTable.Transactions,
rows: this.props.viewer.addresses[0].transactions,
}}
selectedRowId={this.state.transaction}
onChange={this._handleChange}
onAction={this.props.onAction}
onNavigateTo={this.props.onNavigateTo}
name="transaction"
/>
</Section>
) : null}
</ScenePage> </ScenePage>
); );
} }

View File

@ -1,24 +1,24 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as Fixtures from "~/common/fixtures"; import * as Fixtures from '~/common/fixtures';
import * as System from "~/components/system"; import * as System from '~/components/system';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
import Section from "~/components/core/Section"; import Section from '~/components/core/Section';
import ScenePage from "~/components/core/ScenePage"; import ScenePage from '~/components/core/ScenePage';
const SELECT_MENU_OPTIONS = [ const SELECT_MENU_OPTIONS = [
{ value: "1", name: "China" }, { value: '1', name: 'China' },
{ value: "2", name: "United States" }, { value: '2', name: 'United States' },
{ value: "3", name: "Russia" }, { value: '3', name: 'Russia' },
]; ];
const SELECT_MENU_MAP = { const SELECT_MENU_MAP = {
"1": "China", '1': 'China',
"2": "United States", '2': 'United States',
"3": "Russia", '3': 'Russia',
}; };
const STYLES_GROUP = css` const STYLES_GROUP = css`
@ -27,6 +27,10 @@ const STYLES_GROUP = css`
justify-content: space-between; justify-content: space-between;
`; `;
const STYLES_SUBGROUP = css`
padding-left: 24px;
`;
const STYLES_LEFT = css` const STYLES_LEFT = css`
flex-shrink: 0; flex-shrink: 0;
padding: 12px 0 0 0; padding: 12px 0 0 0;
@ -36,7 +40,7 @@ const STYLES_LEFT = css`
const STYLES_RIGHT = css` const STYLES_RIGHT = css`
min-width: 10%; min-width: 10%;
padding-left: 48px; padding-left: 48px;
padding-top: 16px; padding-top: 24px;
width: 100%; width: 100%;
`; `;
@ -46,6 +50,14 @@ export default class SceneSettings extends React.Component {
}; };
render() { render() {
let addresses = {};
this.props.viewer.addresses.forEach((a) => {
addresses[a.address] = a;
});
const currentAddress = addresses[this.props.viewer.settings_cold_default_address];
return ( return (
<ScenePage> <ScenePage>
<System.H1>Settings</System.H1> <System.H1>Settings</System.H1>
@ -69,6 +81,138 @@ export default class SceneSettings extends React.Component {
</div> </div>
</div> </div>
<div css={STYLES_GROUP} style={{ marginTop: 32 }}>
<div css={STYLES_LEFT}>
<System.DescriptionGroup
label="Enable cold storage"
tooltip="Placeholder"
description="By enabling cold storage, every time you make a deal your data will be stored on the Filecoin Network."
/>
</div>
<div css={STYLES_RIGHT}>
<System.Toggle
name="settings_cold_enabled"
onChange={this._handleChange}
active={this.props.viewer.settings_cold_enabled}
/>
</div>
</div>
{this.props.viewer.settings_cold_enabled ? (
<div css={STYLES_SUBGROUP}>
<System.SelectMenu
containerStyle={{ marginTop: 24 }}
label="Default Filecoin address"
description="Default Filecoin address settings description."
tooltip="Placeholder."
name="settings_cold_default_address"
value={this.props.viewer.settings_cold_default_address}
category="address"
onChange={this._handleChange}
options={this.props.viewer.addresses}>
{currentAddress.name}
</System.SelectMenu>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Default Filecoin deal duration"
description="Default Filecoin deal duration settings description."
tooltip="Placeholder."
name="settings_cold_default_duration"
value={this.props.viewer.settings_cold_default_duration}
placeholder="Type in months"
onChange={this._handleChange}
/>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Default Filecoin replication factor"
description="Default Filecoin replication factor settings description."
tooltip="Placeholder."
name="settings_cold_default_replication_factor"
value={this.props.viewer.settings_cold_default_replication_factor}
placeholder="Type in amount of miners"
onChange={this._handleChange}
/>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Max Filecoin price."
description="Set the maximum Filecoin price you're willing to pay."
tooltip="Placeholder."
name="settings_cold_default_max_price"
value={this.props.viewer.settings_cold_default_max_price}
placeholder="Type in amount of Filecoin"
onChange={this._handleChange}
/>
<System.CheckBox
style={{ marginTop: 48 }}
name="settings_cold_default_auto_renew"
value={this.props.viewer.settings_cold_default_auto_renew}
onChange={this._handleChange}>
Enable auto renew for Filecoin Network deals.
</System.CheckBox>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Max Filecoin deal auto renew price."
description="Set the maximum Filecoin price you're willing to pay for auto renew."
tooltip="Placeholder."
name="settings_cold_default_auto_renew_max_price"
value={this.props.viewer.settings_cold_default_auto_renew_max_price}
placeholder="Type in amount of Filecoin"
onChange={this._handleChange}
/>
</div>
) : null}
<div css={STYLES_GROUP} style={{ marginTop: 32 }}>
<div css={STYLES_LEFT}>
<System.DescriptionGroup
label="Enable hot storage"
tooltip="Placeholder"
description="By enabling hot storage, every time you make a deal your data will be stored on IPFS."
/>
</div>
<div css={STYLES_RIGHT}>
<System.Toggle
name="settings_hot_enabled"
onChange={this._handleChange}
active={this.props.viewer.settings_hot_enabled}
/>
</div>
</div>
{this.props.viewer.settings_hot_enabled ? (
<div css={STYLES_SUBGROUP}>
<System.CheckBox
style={{ marginTop: 48 }}
name="settings_hot_allow_unfreeze"
value={this.props.viewer.settings_hot_allow_unfreeze}
onChange={this._handleChange}>
IPFS allow unfreeze setting description.
</System.CheckBox>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Add timeout"
description="Add IPFS timeout setting description."
tooltip="Placeholder."
name="settings_hot_ipfs_add_timeout"
value={this.props.viewer.settings_hot_ipfs_add_timeout}
placeholder="Type in seconds"
onChange={this._handleChange}
/>
</div>
) : null}
</ScenePage>
);
}
}
/*
<System.Input <System.Input
containerStyle={{ marginTop: 24 }} containerStyle={{ marginTop: 24 }}
label="Default deal location" label="Default deal location"
@ -123,37 +267,7 @@ export default class SceneSettings extends React.Component {
name="settings_deal_country" name="settings_deal_country"
value={this.props.viewer.settings_deal_country} value={this.props.viewer.settings_deal_country}
onChange={this._handleChange} onChange={this._handleChange}
options={SELECT_MENU_OPTIONS} options={SELECT_MENU_OPTIONS}>
>
{SELECT_MENU_MAP[this.props.viewer.settings_deal_country]} {SELECT_MENU_MAP[this.props.viewer.settings_deal_country]}
</System.SelectMenu> </System.SelectMenu>
*/
<System.Input
containerStyle={{ marginTop: 32 }}
label="Transaction password"
description="Add a password before you perform any transaction."
type="password"
tooltip="We will still ask you for your password even if you skip storage deal confirmation."
name="settings_deal_password"
value={this.props.viewer.settings_deal_password}
placeholder="Type a password"
onChange={this._handleChange}
/>
<System.H2 style={{ marginTop: 72 }}>Miner</System.H2>
<System.P style={{ marginTop: 24 }}>
No miners have been detected, when you a run miners you can configure
their settings here
</System.P>
<System.H2 style={{ marginTop: 72 }}>Extensions</System.H2>
<System.P style={{ marginTop: 24 }}>
When third party services become available, you can enable them here
to automatically use them when you make storage or retrieval deals.
</System.P>
</ScenePage>
);
}
}

View File

@ -1,14 +1,14 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as Fixtures from "~/common/fixtures"; import * as Fixtures from '~/common/fixtures';
import * as System from "~/components/system"; import * as System from '~/components/system';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
import { LineChart } from "~/vendor/react-chartkick"; import { LineChart } from '~/vendor/react-chartkick';
import Section from "~/components/core/Section"; import Section from '~/components/core/Section';
import ScenePage from "~/components/core/ScenePage"; import ScenePage from '~/components/core/ScenePage';
const STYLES_ROW = css` const STYLES_ROW = css`
padding: 24px; padding: 24px;
@ -24,7 +24,7 @@ const STYLES_LEFT = css`
`; `;
const STYLES_RIGHT = css` const STYLES_RIGHT = css`
font-family: "inter-semi-bold"; font-family: 'inter-semi-bold';
font-size: ${Constants.typescale.lvl2}; font-size: ${Constants.typescale.lvl2};
color: ${Constants.system.brand}; color: ${Constants.system.brand};
min-width: 10%; min-width: 10%;
@ -71,7 +71,7 @@ const STYLES_GRAPH_ROW_RIGHT = css`
const STYLES_OPTION = css` const STYLES_OPTION = css`
color: ${Constants.system.white}; color: ${Constants.system.white};
margin-left: 24px; margin-left: 24px;
font-family: "inter-semi-bold"; font-family: 'inter-semi-bold';
font-size: 12px; font-size: 12px;
line-height: 0.2px; line-height: 0.2px;
text-transform: uppercase; text-transform: uppercase;
@ -108,12 +108,12 @@ const STYLES_ITEM = css`
const STYLES_FOCUS = css` const STYLES_FOCUS = css`
font-size: ${Constants.typescale.lvl1}; font-size: ${Constants.typescale.lvl1};
font-family: "inter-medium"; font-family: 'inter-medium';
overflow-wrap: break-word; overflow-wrap: break-word;
width: 100%; width: 100%;
strong { strong {
font-family: "inter-semi-bold"; font-family: 'inter-semi-bold';
font-weight: 400; font-weight: 400;
} }
`; `;
@ -141,44 +141,40 @@ export default class SceneStats extends React.Component {
title="Wallet" title="Wallet"
buttons={[ buttons={[
{ {
name: "Reset", name: 'Reset',
type: "ACTION", type: 'ACTION',
value: "ACTION_RESET_STATS_WALLET", value: 'ACTION_RESET_STATS_WALLET',
}, },
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_STATS_WALLET", value: 'CSV_STATS_WALLET',
}, },
]} ]}>
>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}>Total FIL Balance</div> <div css={STYLES_LEFT}>Total FIL Balance</div>
<div css={STYLES_RIGHT}>Value (FIL/ATTOLFIL)</div> <div css={STYLES_RIGHT}>Value (FIL/ATTOFIL)</div>
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}>Lifetime FIL Balance</div> <div css={STYLES_LEFT}>Lifetime FIL Balance</div>
<div css={STYLES_RIGHT}>Value (FIL/ATTOLFIL)</div> <div css={STYLES_RIGHT}>Value (FIL/ATTOFIL)</div>
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}>FIL spent today</div> <div css={STYLES_LEFT}>FIL spent today</div>
<div css={STYLES_RIGHT}>Value (FIL/ATTOLFIL)</div> <div css={STYLES_RIGHT}>Value (FIL/ATTOFIL)</div>
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}>Total FIL spent</div> <div css={STYLES_LEFT}>Total FIL spent</div>
<div css={STYLES_RIGHT}>Value (FIL/ATTOLFIL)</div> <div css={STYLES_RIGHT}>Value (FIL/ATTOFIL)</div>
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}>Total FIL received</div> <div css={STYLES_LEFT}>Total FIL received</div>
<div css={STYLES_RIGHT}>Value (FIL/ATTOLFIL)</div> <div css={STYLES_RIGHT}>Value (FIL/ATTOFIL)</div>
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}> <div css={STYLES_LEFT}>
Total wallet addresses{" "} Total wallet addresses{' '}
<strong <strong css={STYLES_TEXT_CTA} onClick={() => this.props.onNavigateTo({ id: 2 })}>
css={STYLES_TEXT_CTA}
onClick={() => this.props.onNavigateTo({ id: 2 })}
>
(view) (view)
</strong> </strong>
</div> </div>
@ -186,11 +182,8 @@ export default class SceneStats extends React.Component {
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}> <div css={STYLES_LEFT}>
Total payment channels{" "} Total payment channels{' '}
<strong <strong css={STYLES_TEXT_CTA} onClick={() => this.props.onNavigateTo({ id: 3 })}>
css={STYLES_TEXT_CTA}
onClick={() => this.props.onNavigateTo({ id: 3 })}
>
(view) (view)
</strong> </strong>
</div> </div>
@ -198,11 +191,8 @@ export default class SceneStats extends React.Component {
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}> <div css={STYLES_LEFT}>
Total FIL in payment channels{" "} Total FIL in payment channels{' '}
<strong <strong css={STYLES_TEXT_CTA} onClick={() => this.props.onNavigateTo({ id: 3 })}>
css={STYLES_TEXT_CTA}
onClick={() => this.props.onNavigateTo({ id: 3 })}
>
(view) (view)
</strong> </strong>
</div> </div>
@ -216,17 +206,16 @@ export default class SceneStats extends React.Component {
title="Node" title="Node"
buttons={[ buttons={[
{ {
name: "Reset", name: 'Reset',
type: "ACTION", type: 'ACTION',
value: "ACTION_RESET_STATS_NODE", value: 'ACTION_RESET_STATS_NODE',
}, },
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_STATS_NODE", value: 'CSV_STATS_NODE',
}, },
]} ]}>
>
<div css={STYLES_GRAPH_ROW}> <div css={STYLES_GRAPH_ROW}>
<div css={STYLES_GRAPH_ROW_LEFT}> <div css={STYLES_GRAPH_ROW_LEFT}>
<div css={STYLES_GRAPH_OBJECT}> <div css={STYLES_GRAPH_OBJECT}>
@ -239,10 +228,10 @@ export default class SceneStats extends React.Component {
</div> </div>
<LineChart <LineChart
data={[ data={[
["2017-01-01 00:00:00 UTC", 1], ['2017-01-01 00:00:00 UTC', 1],
["2018-01-01 00:00:00 UTC", 5], ['2018-01-01 00:00:00 UTC', 5],
["2019-01-01 00:00:00 UTC", 25], ['2019-01-01 00:00:00 UTC', 25],
["2020-01-01 00:00:00 UTC", 200], ['2020-01-01 00:00:00 UTC', 200],
[new Date(), 400], [new Date(), 400],
]} ]}
library={{ library={{
@ -293,10 +282,10 @@ export default class SceneStats extends React.Component {
</div> </div>
<LineChart <LineChart
data={[ data={[
["2017-01-01 00:00:00 UTC", 1], ['2017-01-01 00:00:00 UTC', 1],
["2018-01-01 00:00:00 UTC", 2], ['2018-01-01 00:00:00 UTC', 2],
["2019-01-01 00:00:00 UTC", 4], ['2019-01-01 00:00:00 UTC', 4],
["2020-01-01 00:00:00 UTC", 5], ['2020-01-01 00:00:00 UTC', 5],
[new Date(), 4], [new Date(), 4],
]} ]}
library={{ library={{
@ -343,11 +332,8 @@ export default class SceneStats extends React.Component {
</div> </div>
<div css={STYLES_ROW}> <div css={STYLES_ROW}>
<div css={STYLES_LEFT}> <div css={STYLES_LEFT}>
Favorite peers{" "} Favorite peers{' '}
<strong <strong css={STYLES_TEXT_CTA} onClick={() => this.props.onNavigateTo({ id: 8 })}>
css={STYLES_TEXT_CTA}
onClick={() => this.props.onNavigateTo({ id: 8 })}
>
(view) (view)
</strong> </strong>
</div> </div>
@ -365,17 +351,16 @@ export default class SceneStats extends React.Component {
title="Data" title="Data"
buttons={[ buttons={[
{ {
name: "Reset", name: 'Reset',
type: "ACTION", type: 'ACTION',
value: "ACTION_RESET_STATS_DATA", value: 'ACTION_RESET_STATS_DATA',
}, },
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_STATS_DATA", value: 'CSV_STATS_DATA',
}, },
]} ]}>
>
<div css={STYLES_GRAPH_ROW}> <div css={STYLES_GRAPH_ROW}>
<div css={STYLES_GRAPH_ROW_LEFT}> <div css={STYLES_GRAPH_ROW_LEFT}>
<div css={STYLES_GRAPH_OBJECT}> <div css={STYLES_GRAPH_OBJECT}>
@ -388,10 +373,10 @@ export default class SceneStats extends React.Component {
</div> </div>
<LineChart <LineChart
data={[ data={[
["2017-01-01 00:00:00 UTC", 1], ['2017-01-01 00:00:00 UTC', 1],
["2018-01-01 00:00:00 UTC", 5], ['2018-01-01 00:00:00 UTC', 5],
["2019-01-01 00:00:00 UTC", 25], ['2019-01-01 00:00:00 UTC', 25],
["2020-01-01 00:00:00 UTC", 200], ['2020-01-01 00:00:00 UTC', 200],
[new Date(), 400], [new Date(), 400],
]} ]}
library={{ library={{
@ -445,10 +430,10 @@ export default class SceneStats extends React.Component {
</div> </div>
<LineChart <LineChart
data={[ data={[
["2017-01-01 00:00:00 UTC", 1], ['2017-01-01 00:00:00 UTC', 1],
["2018-01-01 00:00:00 UTC", 5], ['2018-01-01 00:00:00 UTC', 5],
["2019-01-01 00:00:00 UTC", 25], ['2019-01-01 00:00:00 UTC', 25],
["2020-01-01 00:00:00 UTC", 200], ['2020-01-01 00:00:00 UTC', 200],
[new Date(), 400], [new Date(), 400],
]} ]}
library={{ library={{
@ -516,55 +501,54 @@ export default class SceneStats extends React.Component {
title="Most commonly retrieved CIDs" title="Most commonly retrieved CIDs"
buttons={[ buttons={[
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_MOST_COMMON_CIDS", value: 'CSV_MOST_COMMON_CIDS',
}, },
]} ]}>
>
<System.Table <System.Table
data={{ data={{
columns: [ columns: [
{ {
key: "deal-cid", key: 'deal-cid',
name: "Deal CID", name: 'Deal CID',
copyable: true, copyable: true,
tooltip: "Deal CID explainer", tooltip: 'Deal CID explainer',
width: "100%", width: '100%',
}, },
{ {
key: "data-cid", key: 'data-cid',
name: "Data CID", name: 'Data CID',
copyable: true, copyable: true,
tooltip: "Data CID explainer", tooltip: 'Data CID explainer',
width: "296px", width: '296px',
}, },
{ key: "miner", name: "Miner", width: "228px" }, { key: 'miner', name: 'Miner', width: '228px' },
], ],
rows: [ rows: [
{ {
id: 1, id: 1,
"data-cid": "44Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'data-cid': '44Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
"deal-cid": "55Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'deal-cid': '55Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
miner: "Example Miner A", miner: 'Example Miner A',
}, },
{ {
id: 2, id: 2,
"data-cid": "14Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'data-cid': '14Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
"deal-cid": "23Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'deal-cid': '23Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
miner: "Example Miner B", miner: 'Example Miner B',
}, },
{ {
id: 3, id: 3,
"data-cid": "88Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'data-cid': '88Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
"deal-cid": "89Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'deal-cid': '89Y7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
miner: "Example Miner C", miner: 'Example Miner C',
}, },
{ {
id: 4, id: 4,
"data-cid": "AAAAYh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'data-cid': 'AAAAYh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
"deal-cid": "BBBBYh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU", 'deal-cid': 'BBBBYh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU',
miner: "Example Miner D", miner: 'Example Miner D',
}, },
], ],
}} }}
@ -581,24 +565,22 @@ export default class SceneStats extends React.Component {
title="Top storage deals by GB" title="Top storage deals by GB"
buttons={[ buttons={[
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_TOP_STORAGE_DEALS_GB", value: 'CSV_TOP_STORAGE_DEALS_GB',
}, },
]} ]}>
>
<System.Table <System.Table
data={{ data={{
columns: [ columns: [
{ key: "file", name: "File", type: "FILE_LINK" }, { key: 'file', name: 'File', type: 'FILE_LINK' },
{ key: "miner", name: "Miner", width: "228px" }, { key: 'miner', name: 'Miner', width: '228px' },
{ key: "size", name: "Size" }, { key: 'size', name: 'Size' },
{ {
key: "date", key: 'date',
name: "Date uploaded", name: 'Date uploaded',
width: "168px", width: '168px',
tooltip: tooltip: 'This date represents when the file was first uploaded to the network.',
"This date represents when the file was first uploaded to the network.",
}, },
], ],
rows: [], rows: [],
@ -616,24 +598,22 @@ export default class SceneStats extends React.Component {
title="Top storage deals by FIL" title="Top storage deals by FIL"
buttons={[ buttons={[
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_TOP_STORAGE_DEALS_FIL", value: 'CSV_TOP_STORAGE_DEALS_FIL',
}, },
]} ]}>
>
<System.Table <System.Table
data={{ data={{
columns: [ columns: [
{ key: "file", name: "File", type: "FILE_LINK" }, { key: 'file', name: 'File', type: 'FILE_LINK' },
{ key: "miner", name: "Miner", width: "228px" }, { key: 'miner', name: 'Miner', width: '228px' },
{ key: "amount", name: "Amount" }, { key: 'amount', name: 'Amount' },
{ {
key: "date", key: 'date',
name: "Date uploaded", name: 'Date uploaded',
width: "168px", width: '168px',
tooltip: tooltip: 'This date represents when the file was first uploaded to the network.',
"This date represents when the file was first uploaded to the network.",
}, },
], ],
rows: [], rows: [],

View File

@ -1,15 +1,15 @@
import * as React from "react"; import * as React from 'react';
import * as Strings from "~/common/strings"; import * as Strings from '~/common/strings';
import * as Constants from "~/common/constants"; import * as Constants from '~/common/constants';
import * as SVG from "~/components/system/svg"; import * as SVG from '~/components/system/svg';
import * as Fixtures from "~/common/fixtures"; import * as Fixtures from '~/common/fixtures';
import * as System from "~/components/system"; import * as System from '~/components/system';
import * as SchemaTable from "~/common/schema-table"; import * as SchemaTable from '~/common/schema-table';
import { css } from "@emotion/react"; import { css } from '@emotion/react';
import Section from "~/components/core/Section"; import Section from '~/components/core/Section';
import ScenePage from "~/components/core/ScenePage"; import ScenePage from '~/components/core/ScenePage';
const STYLES_GROUP = css` const STYLES_GROUP = css`
padding: 24px; padding: 24px;
@ -60,12 +60,12 @@ const STYLES_TEXT = css`
const STYLES_FOCUS = css` const STYLES_FOCUS = css`
font-size: ${Constants.typescale.lvl1}; font-size: ${Constants.typescale.lvl1};
font-family: "inter-medium"; font-family: 'inter-medium';
overflow-wrap: break-word; overflow-wrap: break-word;
width: 100%; width: 100%;
strong { strong {
font-family: "inter-semi-bold"; font-family: 'inter-semi-bold';
font-weight: 400; font-weight: 400;
} }
`; `;
@ -137,6 +137,12 @@ export default class SceneWallet extends React.Component {
const currentAddress = addresses[this.props.selected.address]; const currentAddress = addresses[this.props.selected.address];
// TODO(jim):
// Capture this state.
if (!currentAddress) {
return null;
}
let transactions = []; let transactions = [];
if (currentAddress.transactions) { if (currentAddress.transactions) {
transactions = [...currentAddress.transactions]; transactions = [...currentAddress.transactions];
@ -152,17 +158,16 @@ export default class SceneWallet extends React.Component {
title="Addresses" title="Addresses"
buttons={[ buttons={[
{ {
name: "Create new", name: 'Create new',
type: "SIDEBAR", type: 'SIDEBAR',
value: "SIDEBAR_CREATE_WALLET_ADDRESS", value: 'SIDEBAR_CREATE_WALLET_ADDRESS',
}, },
{ {
name: "Delete", name: 'Delete',
type: "SIDEBAR", type: 'SIDEBAR',
value: "SIDEBAR_DELETE_WALLET_ADDRESS", value: 'SIDEBAR_DELETE_WALLET_ADDRESS',
}, },
]} ]}>
>
<div css={STYLES_GROUP}> <div css={STYLES_GROUP}>
<System.SelectMenu <System.SelectMenu
label="Select your address" label="Select your address"
@ -170,8 +175,7 @@ export default class SceneWallet extends React.Component {
value={this.props.selected.address} value={this.props.selected.address}
category="address" category="address"
onChange={this._handleWalletChange} onChange={this._handleWalletChange}
options={this.props.viewer.addresses} options={this.props.viewer.addresses}>
>
{currentAddress.name} {currentAddress.name}
</System.SelectMenu> </System.SelectMenu>
</div> </div>
@ -180,28 +184,21 @@ export default class SceneWallet extends React.Component {
<div css={STYLES_TEXT}> <div css={STYLES_TEXT}>
<div> <div>
<div css={STYLES_FOCUS}> <div css={STYLES_FOCUS}>
{this.state.visible ? ( {this.state.visible ? currentAddress.address : <span css={STYLES_FOCUS_EMPAHSIS}>Hidden</span>}
currentAddress.address
) : (
<span css={STYLES_FOCUS_EMPAHSIS}>Hidden</span>
)}
</div> </div>
<div css={STYLES_SUBTEXT}>Filecoin address</div> <div css={STYLES_SUBTEXT}>Filecoin address</div>
</div> </div>
<div style={{ marginTop: 24 }}> <div style={{ marginTop: 24 }}>
<div css={STYLES_FOCUS}> <div css={STYLES_FOCUS}>
{currentAddress.name}{" "} {currentAddress.name} <strong css={STYLES_FOCUS_EMPAHSIS}>(Primary)</strong>
<strong css={STYLES_FOCUS_EMPAHSIS}>(Primary)</strong>
</div> </div>
<div css={STYLES_SUBTEXT}>Filecoin address alias</div> <div css={STYLES_SUBTEXT}>Filecoin address alias</div>
</div> </div>
<div css={STYLES_ITEM_GROUP}> <div css={STYLES_ITEM_GROUP}>
<div css={STYLES_ITEM}> <div css={STYLES_ITEM}>
<div css={STYLES_FOCUS}> <div css={STYLES_FOCUS}>{Strings.formatNumber(currentAddress.balance)}</div>
{Strings.formatNumber(currentAddress.balance)}
</div>
<div css={STYLES_SUBTEXT}>Filecoin</div> <div css={STYLES_SUBTEXT}>Filecoin</div>
</div> </div>
@ -210,10 +207,7 @@ export default class SceneWallet extends React.Component {
<div css={STYLES_SUBTEXT}>Address type</div> <div css={STYLES_SUBTEXT}>Address type</div>
</div> </div>
<div <div css={STYLES_ITEM_CLICKABLE} onClick={() => this.props.onNavigateTo({ id: 5 })}>
css={STYLES_ITEM_CLICKABLE}
onClick={() => this.props.onNavigateTo({ id: 5 })}
>
<div css={STYLES_FOCUS}>{currentAddress.deals}</div> <div css={STYLES_FOCUS}>{currentAddress.deals}</div>
<div css={STYLES_SUBTEXT}>Active deals</div> <div css={STYLES_SUBTEXT}>Active deals</div>
</div> </div>
@ -223,12 +217,11 @@ export default class SceneWallet extends React.Component {
<System.ButtonPrimary <System.ButtonPrimary
onClick={() => onClick={() =>
this.props.onAction({ this.props.onAction({
name: "Send Filecoin", name: 'Send Filecoin',
type: "SIDEBAR", type: 'SIDEBAR',
value: "SIDEBAR_WALLET_SEND_FUNDS", value: 'SIDEBAR_WALLET_SEND_FUNDS',
}) })
} }>
>
Send Filecoin Send Filecoin
</System.ButtonPrimary> </System.ButtonPrimary>
</div> </div>
@ -239,11 +232,8 @@ export default class SceneWallet extends React.Component {
onClick={this._handleMakeAddressVisible} onClick={this._handleMakeAddressVisible}
style={{ style={{
marginRight: 16, marginRight: 16,
backgroundColor: this.state.visible backgroundColor: this.state.visible ? null : Constants.system.brand,
? null }}>
: Constants.system.brand,
}}
>
<SVG.Privacy height="16px" /> <SVG.Privacy height="16px" />
</span> </span>
<span css={STYLES_CIRCLE_BUTTON}> <span css={STYLES_CIRCLE_BUTTON}>
@ -252,10 +242,7 @@ export default class SceneWallet extends React.Component {
</div> </div>
<div css={STYLES_ACTIONS}> <div css={STYLES_ACTIONS}>
<div css={STYLES_QR_CODE}> <div css={STYLES_QR_CODE}>
<img <img src="/static/qr-code-example.jpg" css={STYLES_QR_CODE_IMAGE} />
src="/static/qr-code-example.jpg"
css={STYLES_QR_CODE_IMAGE}
/>
</div> </div>
</div> </div>
</div> </div>
@ -267,12 +254,11 @@ export default class SceneWallet extends React.Component {
title={`Transactions for ${currentAddress.name}`} title={`Transactions for ${currentAddress.name}`}
buttons={[ buttons={[
{ {
name: "Export", name: 'Export',
type: "DOWNLOAD", type: 'DOWNLOAD',
value: "CSV_WALLET_TRANSACTIONS", value: 'CSV_WALLET_TRANSACTIONS',
}, },
]} ]}>
>
<System.Table <System.Table
data={{ data={{
columns: SchemaTable.Wallet, columns: SchemaTable.Wallet,

View File

@ -24,14 +24,26 @@ let peersList;
let addrsList; let addrsList;
let info; let info;
const refresh = async () => {
const Health = await pow.health.check();
status = Health.status ? Health.status : null;
messageList = Health.messageList ? Health.messageList : null;
const Peers = await pow.net.peers();
peersList = Peers.peersList ? Peers.peersList : null;
};
const refreshWithToken = async () => {
const Addresses = await pow.ffs.addrs();
addrsList = Addresses.addrsList;
const NetworkInfo = await pow.ffs.info();
info = NetworkInfo.info;
};
app.prepare().then(async () => { app.prepare().then(async () => {
try { try {
const Health = await pow.health.check(); await refresh();
status = Health.status ? Health.status : null;
messageList = Health.messageList ? Health.messageList : null;
const Peers = await pow.net.peers();
peersList = Peers.peersList ? Peers.peersList : null;
// NOTE(jim): This is a configuration folder with all of the client tokens. // NOTE(jim): This is a configuration folder with all of the client tokens.
!FS.existsSync(`./.data`) && FS.mkdirSync(`./.data`, { recursive: true }); !FS.existsSync(`./.data`) && FS.mkdirSync(`./.data`, { recursive: true });
@ -49,11 +61,7 @@ app.prepare().then(async () => {
pow.setToken(token); pow.setToken(token);
const Addresses = await pow.ffs.addrs(); await refreshWithToken();
addrsList = Addresses.addrsList;
const NetworkInfo = await pow.ffs.info();
info = NetworkInfo.info;
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
@ -77,6 +85,22 @@ app.prepare().then(async () => {
res.send('ok'); res.send('ok');
}); });
server.post('/_/viewer', async (req, res) => {
await refresh();
await refreshWithToken();
const data = {
production: !dev,
status,
messageList,
peersList,
addrsList,
info,
};
return res.status(200).send({ success: true, data });
});
server.post('/_/wallet/create', async (req, res) => { server.post('/_/wallet/create', async (req, res) => {
let data; let data;
try { try {
@ -96,11 +120,12 @@ app.prepare().then(async () => {
return res.status(500).send({ error: e.message }); return res.status(500).send({ error: e.message });
} }
return res.status(200).send({ success: true, data }); return res.status(200).send({ success: true, data: { ...data, ...req.body } });
}); });
server.get('/', async (req, res) => { server.get('/', async (req, res) => {
return app.render(req, res, '/', { return app.render(req, res, '/', {
production: !dev,
status, status,
messageList, messageList,
peersList, peersList,