Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.0 #10

Merged
merged 10 commits into from
Mar 13, 2021
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,14 @@ Just run `npm start`
![Mobile Image](https://imgur.com/HxhUnR5.png)

# Todo
* Add a light theme
* Add full configuration for color picking so users can set their own colors/gradients
* Add setting for sorting cards (Market Cap, holdings, price, etc)
* Add multi-language support
* Get list of tokens dynamically, using a static list of tokens is limiting
* Add functionality for interest bearing assets
* Add functionality for exit strategy planning

v1.1.0 Planning:
* Add timestamp for last time data was updated
* Make it more clear that prices and value changes were updated (maybe similar to what CMC does?)
* Add link to CMC/CG page if someone clicks on the asset name/symbol
* Add configuration for hiding CryptoDash title
* Add Skeleton for cards while loading
* Add Skeleton for cards while loading
* Add different layout views (table, main portfolio change chart with small cards, etc.)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cryptodash",
"version": "1.0.3",
"version": "1.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "latest",
Expand Down
125 changes: 81 additions & 44 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,45 @@
import Card from './Components/Card.js';
import AssetCard from './Components/AssetCard.js';
import Header from './Components/Header.js';
import Hotkeys from 'react-hot-keys';
import React, { Component } from 'react';
import Settings from './Components/Settings.js';

import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';

import './styles/App.css';
import {IconButton, Snackbar} from "@material-ui/core";
import {colors, CssBaseline, IconButton, Snackbar} from "@material-ui/core";
import CloseIcon from '@material-ui/icons/Close';

const CORS_PROXY = 'https://cors.bridged.cc/'

const darkTheme = createMuiTheme({
palette: {
type: "dark",
background: {
default: "#1c2025",
paper: colors.grey[800]
},
primary: {
main: colors.grey[900]
}
}
});

const lightTheme = createMuiTheme({
palette: {
type: "light"
}
});

function CardRow(props) {
var cards = [];

if (!props.assets)
return <div></div>;

props.assets.forEach(asset => {
cards.push(<Card asset={asset} key={asset.symbol} removeCrypto={props.removeCrypto.bind(this)} settings={props.settings} updateHoldings={props.updateHoldings.bind(this)}/>)
cards.push(<AssetCard asset={asset} key={asset.symbol} removeCrypto={props.removeCrypto.bind(this)} settings={props.settings} updateHoldings={props.updateHoldings.bind(this)}/>)
});

return <div className="cardRow">{cards}</div>;
Expand All @@ -37,15 +59,18 @@ class App extends Component {
decimals3: 1,
decimals4: null,
fetchInterval: 300000,
limit: 200,
limit: 5000,
show1hChange: true,
show24hChange: true,
show7dChange: true,
showCardBalances: true,
showPortfolioBalance: true,
sliderMax: 10000
sliderMax: 10000,
theme: lightTheme
};

initialSettings.theme = createMuiTheme(initialSettings.theme);

this.state ={
cards: [],
cryptoassets: require("./cryptoassets.json").slice(0, initialSettings.limit),
Expand Down Expand Up @@ -100,17 +125,27 @@ class App extends Component {
cryptoassets: require("./cryptoassets.json").slice(0, value)
});
}
else if (settingName === "theme") {
if (value === "light") {
value = darkTheme;
}
else {
value = lightTheme;
}
}

var settings = this.state.settings;

settings[settingName] = value;

this.fetchAssetData((settingName === "currency") ? value : this.state.settings.currency);

this.setState({
settings: settings
});

if (settingName === "currency" || settingName === "datasource") {
this.fetchAssetData();
}

localStorage.setItem("settings", JSON.stringify(settings));
}

Expand Down Expand Up @@ -272,13 +307,11 @@ class App extends Component {
});
}

updateHoldings(event, asset){
let value = parseFloat(event.target.value);

updateHoldings(value, symbol){
var assets = this.state.data.assets;

if (value){
assets.find(asset => asset.symbol === asset.symbol.toUpperCase()).holdings = value;
if (value) {
assets.find(asset => asset.symbol === symbol).holdings = value;
}

this.storeData(assets);
Expand All @@ -303,38 +336,42 @@ class App extends Component {
render() {
return (
<div className="page">
<Header addCrypto={this.addCrypto.bind(this)} assets={this.state.data.assets} cryptoAssetData={this.state.cryptoassets} settings={this.state.settings} toggleShowSettings={this.toggleShowSettings.bind(this)}/>
<hr />
<div className="content">
<CardRow assets={this.state.data.assets} removeCrypto={this.removeCrypto.bind(this)} settings={this.state.settings} updateHoldings={this.updateHoldings.bind(this)} />
</div>
<Settings data={this.state.data} editSetting={this.editSetting.bind(this)} settings={this.state.settings} showSettings={this.state.showSettings} toggleShowSettings={this.toggleShowSettings.bind(this)} uploadData={this.uploadData.bind(this)} />
<Hotkeys
keyName="shift+/"
onKeyDown={this.toggleShowSettings.bind(this)}
/>
<Snackbar
action={
<React.Fragment>
<IconButton
aria-label="close"
color="inherit"
onClick={() => this.setState({dataUpdated: false})}
>
<CloseIcon />
</IconButton>
</React.Fragment>
}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
autoHideDuration={Number(this.state.settings.autoHideFetchNotification)}
key={this.state.timestamp}
message={`Prices updated: ${new Date(this.state.timestamp).toLocaleString()}`}
onClose={() => this.setState({dataUpdated: false})}
open={this.state.dataUpdated}
/>
<ThemeProvider theme={this.state.settings.theme || lightTheme}>
<CssBaseline />

<Header addCrypto={this.addCrypto.bind(this)} assets={this.state.data.assets} cryptoAssetData={this.state.cryptoassets} editSetting={this.editSetting.bind(this)} settings={this.state.settings} toggleShowSettings={this.toggleShowSettings.bind(this)}/>
<hr />
<div className="content">
<CardRow assets={this.state.data.assets} removeCrypto={this.removeCrypto.bind(this)} settings={this.state.settings} updateHoldings={this.updateHoldings.bind(this)} />
</div>
<Settings data={this.state.data} editSetting={this.editSetting.bind(this)} settings={this.state.settings} showSettings={this.state.showSettings} theme={this.state.settings.theme || lightTheme} toggleShowSettings={this.toggleShowSettings.bind(this)} uploadData={this.uploadData.bind(this)} />
<Hotkeys
keyName="shift+/"
onKeyDown={this.toggleShowSettings.bind(this)}
/>
<Snackbar
action={
<React.Fragment>
<IconButton
aria-label="close"
color="inherit"
onClick={() => this.setState({dataUpdated: false})}
>
<CloseIcon />
</IconButton>
</React.Fragment>
}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
autoHideDuration={Number(this.state.settings.autoHideFetchNotification)}
key={this.state.timestamp}
message={`Prices updated: ${new Date(this.state.timestamp).toLocaleString()}`}
onClose={() => this.setState({dataUpdated: false})}
open={this.state.dataUpdated}
/>
</ThemeProvider>
</div>
);
}
Expand Down
38 changes: 17 additions & 21 deletions src/Components/Card.js → src/Components/AssetCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'bootstrap/dist/css/bootstrap.min.css';
import FontAwesome from 'react-fontawesome';
import '../styles/Card.css';
import TextField from "@material-ui/core/TextField";
import {InputAdornment, Slider} from "@material-ui/core";
import {Card, InputAdornment, Slider} from "@material-ui/core";

function MyBalance(props) {
if (props.holdings > 0 && props.settings.showCardBalances) {
Expand All @@ -19,12 +19,11 @@ function MyBalance(props) {
)
}

class Card extends Component {
class AssetCard extends Component {
constructor(props){
super(props);
this.state ={
flip: false,
holdings: props.asset.holdings,
settings: props.settings,
simulatedPercentChange: 0,
simulatedPrice: props.asset.price,
Expand Down Expand Up @@ -114,7 +113,7 @@ class Card extends Component {
let back = this.state.flip ? '' : 'none';
return(
<div className="col-xs-12 col-sm-6 col-lg-4 card-container">
<div className="card">
<Card className="card">
<div className={(window.innerWidth <= 760) ? "row" : ""} style={{display: front}} onClick={() => this.toggleSettings()}>
<div className={(window.innerWidth <= 760) ? "ml-2 w-50" : ""}>
<FontAwesome
Expand All @@ -137,7 +136,7 @@ class Card extends Component {
{this.getPercentChange(this.props.asset.percent_change_1h, "1h")}
{this.getPercentChange(this.props.asset.percent_change_24h, "24h")}
{this.getPercentChange(this.props.asset.percent_change_7d, "7d")}
<MyBalance holdings={this.state.holdings} price={price} settings={this.state.settings} />
<MyBalance holdings={this.props.asset.holdings} price={price} settings={this.state.settings} />
</div>
</div>
</div>
Expand Down Expand Up @@ -166,18 +165,15 @@ class Card extends Component {
label="My Holdings"
onChange={
event => {
this.setState({
holdings: parseFloat(event.target.value)
});
this.props.updateHoldings(event, this.props.asset)
this.props.updateHoldings(parseFloat(event.target.value), this.props.asset.symbol)
}
}
size={"small"}
value={this.state.holdings || 0}
value={this.props.asset.holdings || 0}
variant="outlined"
/>

<MyBalance holdings={this.state.holdings} price={price} settings={this.state.settings} />
<MyBalance holdings={this.props.asset.holdings} price={price} settings={this.state.settings} />

<hr />

Expand All @@ -191,7 +187,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: event.target.value,
simulatedPrice: (((event.target.value * .01) * price) + price),
simulatedValue: ((((event.target.value * .01) * price) + price) * this.state.holdings),
simulatedValue: ((((event.target.value * .01) * price) + price) * this.props.asset.holdings),
simulatedCap: ((((event.target.value * .01) * price) + price) * this.props.asset.circulating_supply)
})
}
Expand All @@ -209,7 +205,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: value,
simulatedPrice: (((value * .01) * price) + price),
simulatedValue: ((((value * .01) * price) + price) * this.state.holdings),
simulatedValue: ((((value * .01) * price) + price) * this.props.asset.holdings),
simulatedCap: ((((value * .01) * price) + price) * this.props.asset.circulating_supply)
})
}
Expand All @@ -235,7 +231,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: (100 * ((event.target.value - price) / price)),
simulatedPrice: event.target.value,
simulatedValue: (event.target.value * this.state.holdings),
simulatedValue: (event.target.value * this.props.asset.holdings),
simulatedCap: (event.target.value * this.props.asset.circulating_supply)
})
}
Expand All @@ -252,14 +248,14 @@ class Card extends Component {
onChange={
event =>
this.setState({
simulatedPercentChange: (100 * (((event.target.value / this.state.holdings) - price) / price)),
simulatedPrice: (event.target.value / this.state.holdings),
simulatedPercentChange: (100 * (((event.target.value / this.props.asset.holdings) - price) / price)),
simulatedPrice: (event.target.value / this.props.asset.holdings),
simulatedValue: event.target.value,
simulatedCap: ((event.target.value / this.state.holdings) * this.props.asset.circulating_supply)
simulatedCap: ((event.target.value / this.props.asset.holdings) * this.props.asset.circulating_supply)
})
}
size={"small"}
value={this.getLocalizedPrice(this.state.simulatedValue) || this.getLocalizedPrice(this.state.holdings * price)}
value={this.getLocalizedPrice(this.state.simulatedValue) || this.getLocalizedPrice(this.props.asset.holdings * price)}
variant="outlined"
/>

Expand All @@ -273,7 +269,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: (100 * ((event.target.value - (this.props.asset.circulating_supply * price)) / (this.props.asset.circulating_supply * price))),
simulatedPrice: (event.target.value / this.props.asset.circulating_supply),
simulatedValue: ((event.target.value / this.props.asset.circulating_supply) * this.state.holdings),
simulatedValue: ((event.target.value / this.props.asset.circulating_supply) * this.props.asset.holdings),
simulatedCap: event.target.value
})
}
Expand All @@ -284,10 +280,10 @@ class Card extends Component {
</div>
</div>
</div>
</div>
</Card>
</div>
)
}
}

export default Card;
export default AssetCard;
Loading