From 0d89c2b558958478551eacbb762621a2791a8be2 Mon Sep 17 00:00:00 2001 From: readme-bot Date: Mon, 20 Nov 2023 04:22:57 +0800 Subject: [PATCH 1/6] improve percentage chart --- src/components/historical-data/index.tsx | 19 +-- src/components/latest-assets-percentage.tsx | 136 ++++++++++++++++++-- src/components/overview.tsx | 9 +- src/middlelayers/charts.ts | 30 ++--- src/middlelayers/types.d.ts | 2 + src/utils/app.ts | 9 +- 6 files changed, 154 insertions(+), 51 deletions(-) diff --git a/src/components/historical-data/index.tsx b/src/components/historical-data/index.tsx index 05406ea..51ac7a8 100644 --- a/src/components/historical-data/index.tsx +++ b/src/components/historical-data/index.tsx @@ -19,9 +19,9 @@ import { import Modal from "../common/modal"; import { downloadCoinLogos } from "@/middlelayers/data"; import { appCacheDir as getAppCacheDir } from "@tauri-apps/api/path"; -import { convertFileSrc } from "@tauri-apps/api/tauri"; import { useWindowSize } from "@/utils/hook"; import ImageStack from "../common/image-stack"; +import { getImageApiPath } from "@/utils/app"; type RankData = { id: number; @@ -92,7 +92,7 @@ const App = ({ .catch((e) => toast({ description: e.message, - variant: "destructive" + variant: "destructive", }) ) .finally(() => { @@ -120,7 +120,7 @@ const App = ({ .catch((e) => toast({ description: e.message, - variant: "destructive" + variant: "destructive", }) ); } @@ -208,7 +208,7 @@ const App = ({ .sortBy("value") .reverse() .take(7) - .map((a) => getImageApiPath(a.symbol)) + .map((a) => getImageApiPath(appCacheDir, a.symbol)) .value()} imageWidth={25} imageHeight={25} @@ -260,15 +260,10 @@ const App = ({ .value(); } - function getImageApiPath(symbol: string) { - const filePath = `${appCacheDir}assets/coins/${symbol.toLowerCase()}.png`; - return convertFileSrc(filePath); - } - function renderDetailPage(data: RankData[]) { return _(data) .map((d) => { - const apiPath = getImageApiPath(d.symbol); + const apiPath = getImageApiPath(appCacheDir, d.symbol); return ( @@ -403,9 +398,7 @@ const App = ({ -
+
(pageNum > 1 ? setPageNum(pageNum - 1) : null)} style={{ diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index 511feec..bdd2da5 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -1,18 +1,68 @@ import { Doughnut } from "react-chartjs-2"; import { useWindowSize } from "@/utils/hook"; -import { LatestAssetsPercentageData } from "@/middlelayers/types"; +import { + CurrencyRateDetail, + LatestAssetsPercentageData, +} from "@/middlelayers/types"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; +import _ from "lodash"; +import { useEffect, useState } from "react"; +import { appCacheDir as getAppCacheDir } from "@tauri-apps/api/path"; +import { Table, TableBody, TableCell, TableRow } from "./ui/table"; +import { getImageApiPath } from "@/utils/app"; +import { + currencyWrapper, + prettyNumberToLocaleString, + prettyPriceNumberToLocaleString, +} from "@/utils/currency"; +import { downloadCoinLogos } from "@/middlelayers/data"; -const App = ({ data }: { data: LatestAssetsPercentageData }) => { +const App = ({ + currency, + data, +}: { + currency: CurrencyRateDetail; + data: LatestAssetsPercentageData; +}) => { const size = useWindowSize(); + const [appCacheDir, setAppCacheDir] = useState(""); + + useEffect(() => { + getAppCacheDir().then((dir) => { + setAppCacheDir(dir); + }); + }, []); + + const [percentageData, setPercentageData] = useState< + { + coin: string; + percentage: number; + chartColor: string; + }[] + >(data); + + useEffect(() => { + setPercentageData(splitTopAndOtherData(data)); + + // download coin logos + downloadCoinLogos(_(data).map("coin").value()); + }, [data]); + const options = { maintainAspectRatio: false, responsive: false, plugins: { // text is set for resizing title: { display: false, text: "Percentage of Assets" }, - legend: { labels: { font: {} } }, + legend: { + display: true, + position: "right", + font: { + size: 14, + }, + labels: { font: {} }, + }, datalabels: { color: "white", font: { @@ -33,14 +83,38 @@ const App = ({ data }: { data: LatestAssetsPercentageData }) => { }, }; + function splitTopAndOtherData(d: LatestAssetsPercentageData) { + const count = 5; + if (d.length <= count) { + return d; + } + const top = _(d).sortBy("percentage").reverse().take(count).value(); + console.log(top); + const other = _(d).sortBy("percentage").reverse().drop(count).value(); + + return _([ + ...top, + other + ? { + coin: "Other", + percentage: _(other).map("percentage").sum(), + chartColor: other[0]?.chartColor ?? "#4B5563", + } + : null, + ]) + .compact() + .value(); + } + function lineData() { + const d = percentageData; return { - labels: data.map((coin) => coin.coin), + labels: d.map((coin) => coin.coin), datasets: [ { - data: data.map((coin) => coin.percentage), - borderColor: data.map((coin) => coin.chartColor), - backgroundColor: data.map((coin) => coin.chartColor), + data: d.map((coin) => coin.percentage), + borderColor: d.map((coin) => coin.chartColor), + backgroundColor: d.map((coin) => coin.chartColor), borderWidth: 1, }, ], @@ -52,16 +126,52 @@ const App = ({ data }: { data: LatestAssetsPercentageData }) => { + {size.width} Percentage of Assets -
- +
+
+ +
+
+ + + {/* todo: paginate */} + {data.map((d) => ( + + +
+ {d.coin} +
+ {prettyPriceNumberToLocaleString(d.amount)} +
+
{d.coin}
+
+
+ +
+ {currency.symbol + + prettyNumberToLocaleString( + currencyWrapper(currency)(d.value) + )} +
+
+
+ ))} +
+
+
diff --git a/src/components/overview.tsx b/src/components/overview.tsx index 6d4483b..f19b85d 100644 --- a/src/components/overview.tsx +++ b/src/components/overview.tsx @@ -27,7 +27,7 @@ const App = ({ topCoinsPercentageChangeData, }: { currency: CurrencyRateDetail; - pnlData: PNLData, + pnlData: PNLData; totalValueData: TotalValueData; latestAssetsPercentageData: LatestAssetsPercentageData; assetChangeData: AssetChangeData; @@ -43,12 +43,9 @@ const App = ({ assetChangeData={assetChangeData} totalValueData={totalValueData} > - +
- + { export async function queryLatestAssetsPercentage(): Promise { const size = 1 - const backgroundColors = generateRandomColors(11) // top 10 and others const assets = groupAssetModelsListBySymbol(await queryAssets(size) || []) if (assets.length === 0) { @@ -314,27 +313,22 @@ export async function queryLatestAssetsPercentage(): Promise { - res.push({ - coin: t.symbol, - percentage: t.value / total * 100, - }) - }) + const res: { + coin: string, + percentage: number, + amount: number, + value: number, + }[] = _(latest).map(t => ({ + coin: t.symbol, + amount: t.amount, + value: t.value, + percentage: t.value / total * 100, - if (others.length > 0) { - res.push({ - coin: 'Others', - percentage: _(others).sumBy('value') / total * 100, - }) - } + })).value() return _(res).sortBy('percentage').reverse().map((v, idx) => ({ ...v, diff --git a/src/middlelayers/types.d.ts b/src/middlelayers/types.d.ts index 4602da1..40bed98 100644 --- a/src/middlelayers/types.d.ts +++ b/src/middlelayers/types.d.ts @@ -99,6 +99,8 @@ export type AssetChangeData = { export type LatestAssetsPercentageData = { coin: string + amount: number + value: number percentage: number chartColor: string }[] diff --git a/src/utils/app.ts b/src/utils/app.ts index fcab9f8..976a05e 100644 --- a/src/utils/app.ts +++ b/src/utils/app.ts @@ -1,6 +1,8 @@ import * as api from '@tauri-apps/api' import { getClientIDConfiguration } from '../middlelayers/configuration' import { trackEvent } from '@aptabase/tauri' +import { appCacheDir } from "@tauri-apps/api/path" +import { convertFileSrc } from "@tauri-apps/api/tauri" export async function getVersion() { return api.app.getVersion() @@ -21,4 +23,9 @@ export async function trackEventWithClientID(event: string, props?: { [k: string } catch (e) { console.error("track event failed", e) } -} \ No newline at end of file +} + +export function getImageApiPath(cacheDir: string, symbol: string) { + const filePath = `${cacheDir}assets/coins/${symbol.toLowerCase()}.png` + return convertFileSrc(filePath) +} From ba3bca3593088699cb18f9aaa2ba24c417b6d698 Mon Sep 17 00:00:00 2001 From: readme-bot Date: Mon, 20 Nov 2023 04:28:17 +0800 Subject: [PATCH 2/6] tweak --- src/components/latest-assets-percentage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index bdd2da5..23ab678 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -126,7 +126,6 @@ const App = ({ - {size.width} Percentage of Assets @@ -144,7 +143,7 @@ const App = ({ {/* todo: paginate */} - {data.map((d) => ( + {data.slice(0, 8).map((d) => (
From 8d6e31e1c7c17c898e2182da7fcbcd1844c01ec5 Mon Sep 17 00:00:00 2001 From: readme-bot Date: Mon, 20 Nov 2023 04:58:34 +0800 Subject: [PATCH 3/6] fix layout --- src/components/latest-assets-percentage.tsx | 17 ++++++++------- src/components/overview.tsx | 23 ++++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index 23ab678..d5f9a47 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -130,21 +130,24 @@ const App = ({ -
+
-
+
+
+ Token Holding +
{/* todo: paginate */} - {data.slice(0, 8).map((d) => ( - + {data.slice(0, 5).map((d) => ( +
{d.coin} -
+
{prettyPriceNumberToLocaleString(d.amount)}
{d.coin}
diff --git a/src/components/overview.tsx b/src/components/overview.tsx index f19b85d..b922eee 100644 --- a/src/components/overview.tsx +++ b/src/components/overview.tsx @@ -37,15 +37,22 @@ const App = ({ }) => { return (
-
- - +
+
+ +
+
+ +
- + Date: Mon, 20 Nov 2023 05:01:24 +0800 Subject: [PATCH 4/6] hide card title --- src/components/latest-assets-percentage.tsx | 82 ++++++++++++--------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index d5f9a47..c369acf 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -121,12 +121,56 @@ const App = ({ }; } + function renderDoughnut() { + return ; + } + + function renderTokenHoldingList() { + return ( + <> +
+ Token holding +
+
+ + {/* todo: paginate */} + {data.slice(0, 5).map((d) => ( + + +
+ {d.coin} +
+ {prettyPriceNumberToLocaleString(d.amount)} +
+
{d.coin}
+
+
+ +
+ {currency.symbol + + prettyNumberToLocaleString( + currencyWrapper(currency)(d.value) + )} +
+
+
+ ))} +
+
+ + ); + } + return (
- Percentage of Assets + {/* Percentage of Assets */} @@ -137,42 +181,10 @@ const App = ({ height: 300, }} > - + {renderDoughnut()}
-
- Token Holding -
- - - {/* todo: paginate */} - {data.slice(0, 5).map((d) => ( - - -
- {d.coin} -
- {prettyPriceNumberToLocaleString(d.amount)} -
-
{d.coin}
-
-
- -
- {currency.symbol + - prettyNumberToLocaleString( - currencyWrapper(currency)(d.value) - )} -
-
-
- ))} -
-
+ {renderTokenHoldingList()}
From b3978b804e8837ada2a4df1a5ae7f5de9380ceef Mon Sep 17 00:00:00 2001 From: readme-bot Date: Tue, 21 Nov 2023 04:45:16 +0800 Subject: [PATCH 5/6] support page --- src/components/latest-assets-percentage.tsx | 96 ++++++++++++++------- 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index c369acf..7085dbb 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -1,5 +1,4 @@ import { Doughnut } from "react-chartjs-2"; -import { useWindowSize } from "@/utils/hook"; import { CurrencyRateDetail, LatestAssetsPercentageData, @@ -16,6 +15,13 @@ import { prettyPriceNumberToLocaleString, } from "@/utils/currency"; import { downloadCoinLogos } from "@/middlelayers/data"; +import { Button } from "./ui/button"; +import { Separator } from "./ui/separator"; +import { + ArrowLeftIcon, + ChevronLeftIcon, + ChevronRightIcon, +} from "@radix-ui/react-icons"; const App = ({ currency, @@ -24,9 +30,10 @@ const App = ({ currency: CurrencyRateDetail; data: LatestAssetsPercentageData; }) => { - const size = useWindowSize(); - const [appCacheDir, setAppCacheDir] = useState(""); + const [dataPage, setDataPage] = useState(0); + const [maxDataPage, setMaxDataPage] = useState(0); + const pageSize = 5; useEffect(() => { getAppCacheDir().then((dir) => { @@ -47,6 +54,9 @@ const App = ({ // download coin logos downloadCoinLogos(_(data).map("coin").value()); + + // set max data page + setMaxDataPage(Math.floor(data.length / pageSize)); }, [data]); const options = { @@ -128,37 +138,63 @@ const App = ({ function renderTokenHoldingList() { return ( <> -
- Token holding +
+
+ Token holding +
+
+ +
+ {dataPage + 1} {"/"} {maxDataPage + 1} +
+ +
+ {/* todo: paginate */} - {data.slice(0, 5).map((d) => ( - - -
- {d.coin} -
- {prettyPriceNumberToLocaleString(d.amount)} + {data + .slice(dataPage * pageSize, (dataPage + 1) * pageSize) + .map((d) => ( + + +
+ {d.coin} +
+ {prettyPriceNumberToLocaleString(d.amount)} +
+
{d.coin}
+
+
+ +
+ {currency.symbol + + prettyNumberToLocaleString( + currencyWrapper(currency)(d.value) + )}
-
{d.coin}
-
- - -
- {currency.symbol + - prettyNumberToLocaleString( - currencyWrapper(currency)(d.value) - )} -
-
- - ))} + + + ))}
@@ -183,7 +219,7 @@ const App = ({ > {renderDoughnut()}
-
+
{renderTokenHoldingList()}
From c1f830f4b58743553f27431731e609ad2dd482f8 Mon Sep 17 00:00:00 2001 From: readme-bot Date: Tue, 21 Nov 2023 04:46:13 +0800 Subject: [PATCH 6/6] rm commentor --- src/components/latest-assets-percentage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/latest-assets-percentage.tsx b/src/components/latest-assets-percentage.tsx index 7085dbb..1d396fc 100644 --- a/src/components/latest-assets-percentage.tsx +++ b/src/components/latest-assets-percentage.tsx @@ -167,7 +167,6 @@ const App = ({ - {/* todo: paginate */} {data .slice(dataPage * pageSize, (dataPage + 1) * pageSize) .map((d) => (