gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: format amount so it is align


From: gnunet
Subject: [taler-wallet-core] branch master updated: format amount so it is align to fractional digitls
Date: Thu, 09 Jun 2022 18:46:02 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new ff49e347 format amount so it is align to fractional digitls
ff49e347 is described below

commit ff49e3477e155b94e752c516cf58fdea1ca19d54
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Jun 9 13:37:33 2022 -0300

    format amount so it is align to fractional digitls
---
 packages/taler-util/src/amounts.ts                 |  24 +++++
 .../src/components/Amount.stories.tsx              | 114 +++++++++++++++++++++
 .../src/components/Amount.tsx                      |  94 +++++++++++++++--
 .../src/components/BankDetailsByPaytoType.tsx      |   8 +-
 .../src/components/index.stories.tsx               |   5 +-
 .../src/wallet/DepositPage.stories.tsx             |   6 +-
 .../src/wallet/DepositPage.tsx                     |   3 +-
 .../src/wallet/Transaction.stories.tsx             |   2 +
 .../src/wallet/Transaction.tsx                     |  96 ++++++++++-------
 9 files changed, 301 insertions(+), 51 deletions(-)

diff --git a/packages/taler-util/src/amounts.ts 
b/packages/taler-util/src/amounts.ts
index 98cd4ad6..d65390a1 100644
--- a/packages/taler-util/src/amounts.ts
+++ b/packages/taler-util/src/amounts.ts
@@ -444,4 +444,28 @@ export class Amounts {
 
     return s;
   }
+
+  /**
+   * Number of fractional digits needed to fully represent the amount
+   * @param a amount
+   * @returns 
+   */
+  static maxFractionalDigits(a: AmountJson): number {
+    if (a.fraction === 0) return 0;
+    if (a.fraction < 0) {
+      console.error("amount fraction can not be negative", a);
+      return 0;
+    }
+    let i = 0;
+    let check = true;
+    let rest = a.fraction;
+    while (rest > 0 && check) {
+      check = rest % 10 === 0;
+      rest = rest / 10;
+      i++;
+    }
+    return amountFractionalLength - i + 1;
+  }
+
 }
+
diff --git 
a/packages/taler-wallet-webextension/src/components/Amount.stories.tsx 
b/packages/taler-wallet-webextension/src/components/Amount.stories.tsx
new file mode 100644
index 00000000..caf35d57
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/Amount.stories.tsx
@@ -0,0 +1,114 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler 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, or (at your option) any later version.
+
+ GNU Taler 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
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { styled } from "@linaria/react";
+import { Fragment, h, VNode } from "preact";
+import { Amount } from "./Amount.js";
+
+export default {
+  title: "components/amount",
+  component: Amount,
+};
+
+const Table = styled.table`
+  td {
+    padding: 4px;
+  }
+  td {
+    border-bottom: 1px solid black;
+  }
+`;
+
+function ProductTable(
+  prods: string[],
+  AmountRender: (p: { value: string; index: number }) => VNode = Amount,
+): VNode {
+  return (
+    <Table>
+      <tr>
+        <td>product</td>
+        <td>price</td>
+      </tr>
+      {prods.map((value, i) => {
+        return (
+          <tr key={i}>
+            <td>p{i}</td>
+            <td>
+              <AmountRender value={value} index={i} />
+              {/* <Amount value={value} fracSize={fracSize} /> */}
+            </td>
+          </tr>
+        );
+      })}
+    </Table>
+  );
+}
+
+export const WithoutFixedSizeDefault = (): VNode =>
+  ProductTable(["ARS:19", "ARS:0.1", "ARS:10.02"]);
+
+export const WithFixedSizeZero = (): VNode =>
+  ProductTable(["ARS:19", "ARS:0.1", "ARS:10.02"], ({ value }) => {
+    return <Amount value={value} maxFracSize={0} />;
+  });
+
+export const WithFixedSizeFour = (): VNode =>
+  ProductTable(
+    ["ARS:19", "ARS:0.1", "ARS:10.02", "ARS:10.0123", "ARS:10.0123123"],
+    ({ value }) => {
+      return <Amount value={value} maxFracSize={4} />;
+    },
+  );
+
+export const WithFixedSizeFourNegative = (): VNode =>
+  ProductTable(
+    ["ARS:19", "ARS:0.1", "ARS:10.02", "ARS:10.0123", "ARS:10.0123123"],
+    ({ value, index }) => {
+      return (
+        <Amount value={value} maxFracSize={4} negative={index % 2 === 0} />
+      );
+    },
+  );
+
+export const WithFixedSizeFourOverflow = (): VNode =>
+  ProductTable(
+    ["ARS:19", "ARS:0.1", "ARS:10123123.02", "ARS:10.0123", "ARS:10.0123123"],
+    ({ value, index }) => {
+      return (
+        <Amount value={value} maxFracSize={4} negative={index % 2 === 0} />
+      );
+    },
+  );
+
+export const WithFixedSizeFourAccounting = (): VNode =>
+  ProductTable(
+    ["ARS:19", "ARS:0.1", "ARS:10123123.02", "ARS:10.0123", "ARS:10.0123123"],
+    ({ value, index }) => {
+      return (
+        <Amount
+          value={value}
+          signType="accounting"
+          maxFracSize={4}
+          negative={index % 2 === 0}
+        />
+      );
+    },
+  );
diff --git a/packages/taler-wallet-webextension/src/components/Amount.tsx 
b/packages/taler-wallet-webextension/src/components/Amount.tsx
index 8b97896b..09f65473 100644
--- a/packages/taler-wallet-webextension/src/components/Amount.tsx
+++ b/packages/taler-wallet-webextension/src/components/Amount.tsx
@@ -13,15 +13,95 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { AmountJson, Amounts, AmountString } from "@gnu-taler/taler-util";
-import { h, VNode, Fragment } from "preact";
+import {
+  amountFractionalBase,
+  amountFractionalLength,
+  AmountJson,
+  Amounts,
+  AmountString,
+} from "@gnu-taler/taler-util";
+import { Fragment, h, VNode } from "preact";
 
-export function Amount({ value }: { value: AmountJson | AmountString }): VNode 
{
+export function Amount({
+  value,
+  maxFracSize,
+  negative,
+  hideCurrency,
+  signType = "standard",
+  signDisplay = "auto",
+}: {
+  negative?: boolean;
+  value: AmountJson | AmountString;
+  maxFracSize?: number;
+  hideCurrency?: boolean;
+  signType?: "accounting" | "standard";
+  signDisplay?: "auto" | "always" | "never" | "exceptZero";
+}): VNode {
   const aj = Amounts.jsonifyAmount(value);
-  const amount = Amounts.stringifyValue(aj, 2);
+  const minFractional =
+    maxFracSize !== undefined && maxFracSize < 2 ? maxFracSize : 2;
+  const af = aj.fraction % amountFractionalBase;
+  let s = "";
+  if ((af && maxFracSize) || minFractional > 0) {
+    s += ".";
+    let n = af;
+    for (
+      let i = 0;
+      (maxFracSize === undefined || i < maxFracSize) &&
+      i < amountFractionalLength;
+      i++
+    ) {
+      if (!n && i >= minFractional) {
+        break;
+      }
+      s = s + Math.floor((n / amountFractionalBase) * 10).toString();
+      n = (n * 10) % amountFractionalBase;
+    }
+  }
+  const fontSize = 18;
+  const letterSpacing = 0;
+  const mult = 0.7;
   return (
-    <Fragment>
-      {amount}&nbsp;{aj.currency}
-    </Fragment>
+    <span style={{ textAlign: "right", whiteSpace: "nowrap" }}>
+      <span
+        style={{
+          display: "inline-block",
+          fontFamily: "monospace",
+          fontSize,
+        }}
+      >
+        {negative ? (signType === "accounting" ? "(" : "-") : ""}
+        <span
+          style={{
+            display: "inline-block",
+            textAlign: "right",
+            fontFamily: "monospace",
+            fontSize,
+            letterSpacing,
+          }}
+        >
+          {aj.value}
+        </span>
+        <span
+          style={{
+            display: "inline-block",
+            width: !maxFracSize ? undefined : `${(maxFracSize + 1) * mult}em`,
+            textAlign: "left",
+            fontFamily: "monospace",
+            fontSize,
+            letterSpacing,
+          }}
+        >
+          {s}
+          {negative && signType === "accounting" ? ")" : ""}
+        </span>
+      </span>
+      {hideCurrency ? undefined : (
+        <Fragment>
+          &nbsp;
+          <span>{aj.currency}</span>
+        </Fragment>
+      )}
+    </span>
   );
 }
diff --git 
a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx 
b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
index ef2a9f24..ec5d1e7a 100644
--- 
a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
+++ 
b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
@@ -77,12 +77,16 @@ export function BankDetailsByPaytoType({
         <table>
           <tr>
             <td>{payto.targetPath}</td>
-            <td>{Amounts.stringifyValue(amount)} BTC</td>
+            <td>
+              <Amount value={amount} hideCurrency /> BTC
+            </td>
           </tr>
           {payto.segwitAddrs.map((addr, i) => (
             <tr key={i}>
               <td>{addr}</td>
-              <td>{Amounts.stringifyValue(min)} BTC</td>
+              <td>
+                <Amount value={min} hideCurrency /> BTC
+              </td>
             </tr>
           ))}
         </table>
diff --git 
a/packages/taler-wallet-webextension/src/components/index.stories.tsx 
b/packages/taler-wallet-webextension/src/components/index.stories.tsx
index b98606f6..053b27f7 100644
--- a/packages/taler-wallet-webextension/src/components/index.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/index.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import * as a1 from "./Banner.stories.js";
+ import * as a1 from "./Banner.stories.js";
 import * as a2 from "./PendingTransactions.stories.js";
+import * as a3 from "./Amount.stories.js";
 
-export default [a1, a2];
+export default [a1, a2, a3];
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx
index 04f7515e..250df742 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.stories.tsx
@@ -78,7 +78,11 @@ export const WithSomeBankAccounts = 
createExample(TestedComponent, {
       value: "10:USD",
     },
     cancelHandler: {},
-    depositHandler: {},
+    depositHandler: {
+      onClick: async () => {
+        return;
+      },
+    },
     totalFee: Amounts.getZero("USD"),
     totalToDeposit: Amounts.parseOrThrow("USD:10"),
     // onCalculateFee: alwaysReturnFeeToOne,
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
index a0dbcb3c..290c5ca2 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
@@ -18,6 +18,7 @@ import { AmountJson, Amounts, PaytoUri } from 
"@gnu-taler/taler-util";
 import { DepositGroupFees } from 
"@gnu-taler/taler-wallet-core/src/operations/deposits";
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
+import { Amount } from "../components/Amount.js";
 import { Loading } from "../components/Loading.js";
 import { LoadingError } from "../components/LoadingError.js";
 import { SelectList } from "../components/SelectList.js";
@@ -361,7 +362,7 @@ export function View({ state }: ViewProps): VNode {
         ) : (
           <Button variant="contained" onClick={state.depositHandler.onClick}>
             <i18n.Translate>
-              Deposit {Amounts.stringifyValue(state.totalToDeposit)}{" "}
+              Deposit&nbsp;{Amounts.stringifyValue(state.totalToDeposit)}{" "}
               {state.currency}
             </i18n.Translate>
           </Button>
diff --git 
a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
index b49d6cfe..ae43a7b0 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
@@ -428,6 +428,8 @@ export const DepositTalerBank = 
createExample(TestedComponent, {
 export const DepositBitcoin = createExample(TestedComponent, {
   transaction: {
     ...exampleData.deposit,
+    amountRaw: "BITCOINBTC:0.0000011",
+    amountEffective: "BITCOINBTC:0.00000092",  
     targetPaytoUri:
       
"payto://bitcoin/bcrt1q6ps8qs6v8tkqrnru4xqqqa6rfwcx5ufpdfqht4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
   },
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index d1cb72a7..1f195a2b 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -16,6 +16,7 @@
 
 import {
   AbsoluteTime,
+  amountFractionalLength,
   AmountJson,
   Amounts,
   Location,
@@ -749,7 +750,7 @@ function PurchaseDetails({
         <tr>
           <td>Refunded</td>
           <td>
-            <Amount value={transaction.totalRefundRaw} />
+            <Amount value={transaction.totalRefundRaw} negative />
           </td>
         </tr>
       )}
@@ -828,17 +829,20 @@ function RefundDetails({
 }): VNode {
   const { i18n } = useTranslationContext();
 
-  const fee = Amounts.sub(
-    Amounts.parseOrThrow(transaction.amountRaw),
-    Amounts.parseOrThrow(transaction.amountEffective),
-  ).amount;
+  const r = Amounts.parseOrThrow(transaction.amountRaw);
+  const e = Amounts.parseOrThrow(transaction.amountEffective);
+  const fee = Amounts.sub(r, e).amount;
+
+  const maxFrac = [r, e, fee]
+    .map((a) => Amounts.maxFractionalDigits(a))
+    .reduce((c, p) => Math.max(c, p), 0);
 
   return (
     <PurchaseDetailsTable>
       <tr>
         <td>Amount</td>
         <td>
-          <Amount value={transaction.amountRaw} />
+          <Amount value={transaction.amountRaw} maxFracSize={maxFrac} />
         </td>
       </tr>
 
@@ -846,7 +850,7 @@ function RefundDetails({
         <tr>
           <td>Transaction fees</td>
           <td>
-            <Amount value={fee} />
+            <Amount value={fee} negative maxFracSize={maxFrac} />
           </td>
         </tr>
       )}
@@ -858,7 +862,7 @@ function RefundDetails({
       <tr>
         <td>Total</td>
         <td>
-          <Amount value={transaction.amountEffective} />
+          <Amount value={transaction.amountEffective} maxFracSize={maxFrac} />
         </td>
       </tr>
     </PurchaseDetailsTable>
@@ -871,18 +875,20 @@ function DepositDetails({
   transaction: TransactionDeposit;
 }): VNode {
   const { i18n } = useTranslationContext();
+  const r = Amounts.parseOrThrow(transaction.amountRaw);
+  const e = Amounts.parseOrThrow(transaction.amountEffective);
+  const fee = Amounts.sub(r, e).amount;
 
-  const fee = Amounts.sub(
-    Amounts.parseOrThrow(transaction.amountRaw),
-    Amounts.parseOrThrow(transaction.amountEffective),
-  ).amount;
+  const maxFrac = [r, e, fee]
+    .map((a) => Amounts.maxFractionalDigits(a))
+    .reduce((c, p) => Math.max(c, p), 0);
 
   return (
     <PurchaseDetailsTable>
       <tr>
         <td>Amount</td>
         <td>
-          <Amount value={transaction.amountRaw} />
+          <Amount value={transaction.amountRaw} maxFracSize={maxFrac} />
         </td>
       </tr>
 
@@ -890,7 +896,7 @@ function DepositDetails({
         <tr>
           <td>Transaction fees</td>
           <td>
-            <Amount value={fee} />
+            <Amount value={fee} negative maxFracSize={maxFrac} />
           </td>
         </tr>
       )}
@@ -902,7 +908,7 @@ function DepositDetails({
       <tr>
         <td>Total transfer</td>
         <td>
-          <Amount value={transaction.amountEffective} />
+          <Amount value={transaction.amountEffective} maxFracSize={maxFrac} />
         </td>
       </tr>
     </PurchaseDetailsTable>
@@ -915,17 +921,26 @@ function RefreshDetails({
 }): VNode {
   const { i18n } = useTranslationContext();
 
-  const fee = Amounts.sub(
-    Amounts.parseOrThrow(transaction.amountRaw),
-    Amounts.parseOrThrow(transaction.amountEffective),
-  ).amount;
+  const r = Amounts.parseOrThrow(transaction.amountRaw);
+  const e = Amounts.parseOrThrow(transaction.amountEffective);
+  const fee = Amounts.sub(r, e).amount;
+
+  const maxFrac = [r, e, fee]
+    .map((a) => Amounts.maxFractionalDigits(a))
+    .reduce((c, p) => Math.max(c, p), 0);
 
   return (
     <PurchaseDetailsTable>
       <tr>
         <td>Amount</td>
         <td>
-          <Amount value={transaction.amountRaw} />
+          <Amount value={transaction.amountRaw} maxFracSize={maxFrac} />
+        </td>
+      </tr>
+      <tr>
+        <td>Transaction fees</td>
+        <td>
+          <Amount value={fee} negative maxFracSize={maxFrac} />
         </td>
       </tr>
       <tr>
@@ -934,9 +949,9 @@ function RefreshDetails({
         </td>
       </tr>
       <tr>
-        <td>Transaction fees</td>
+        <td>Total</td>
         <td>
-          <Amount value={fee} />
+          <Amount value={transaction.amountEffective} maxFracSize={maxFrac} />
         </td>
       </tr>
     </PurchaseDetailsTable>
@@ -946,17 +961,20 @@ function RefreshDetails({
 function TipDetails({ transaction }: { transaction: TransactionTip }): VNode {
   const { i18n } = useTranslationContext();
 
-  const fee = Amounts.sub(
-    Amounts.parseOrThrow(transaction.amountRaw),
-    Amounts.parseOrThrow(transaction.amountEffective),
-  ).amount;
+  const r = Amounts.parseOrThrow(transaction.amountRaw);
+  const e = Amounts.parseOrThrow(transaction.amountEffective);
+  const fee = Amounts.sub(r, e).amount;
+
+  const maxFrac = [r, e, fee]
+    .map((a) => Amounts.maxFractionalDigits(a))
+    .reduce((c, p) => Math.max(c, p), 0);
 
   return (
     <PurchaseDetailsTable>
       <tr>
         <td>Amount</td>
         <td>
-          <Amount value={transaction.amountRaw} />
+          <Amount value={transaction.amountRaw} maxFracSize={maxFrac} />
         </td>
       </tr>
 
@@ -964,7 +982,7 @@ function TipDetails({ transaction }: { transaction: 
TransactionTip }): VNode {
         <tr>
           <td>Transaction fees</td>
           <td>
-            <Amount value={fee} />
+            <Amount value={fee} negative maxFracSize={maxFrac} />
           </td>
         </tr>
       )}
@@ -976,7 +994,7 @@ function TipDetails({ transaction }: { transaction: 
TransactionTip }): VNode {
       <tr>
         <td>Total</td>
         <td>
-          <Amount value={transaction.amountEffective} />
+          <Amount value={transaction.amountEffective} maxFracSize={maxFrac} />
         </td>
       </tr>
     </PurchaseDetailsTable>
@@ -990,17 +1008,20 @@ function WithdrawDetails({
 }): VNode {
   const { i18n } = useTranslationContext();
 
-  const fee = Amounts.sub(
-    Amounts.parseOrThrow(transaction.amountRaw),
-    Amounts.parseOrThrow(transaction.amountEffective),
-  ).amount;
+  const r = Amounts.parseOrThrow(transaction.amountRaw);
+  const e = Amounts.parseOrThrow(transaction.amountEffective);
+  const fee = Amounts.sub(r, e).amount;
+
+  const maxFrac = [r, e, fee]
+    .map((a) => Amounts.maxFractionalDigits(a))
+    .reduce((c, p) => Math.max(c, p), 0);
 
   return (
     <PurchaseDetailsTable>
       <tr>
         <td>Withdraw</td>
         <td>
-          <Amount value={transaction.amountRaw} />
+          <Amount value={transaction.amountRaw} maxFracSize={maxFrac} />
         </td>
       </tr>
 
@@ -1008,7 +1029,7 @@ function WithdrawDetails({
         <tr>
           <td>Transaction fees</td>
           <td>
-            <Amount value={fee} />
+            <Amount value={fee} negative maxFracSize={maxFrac} />
           </td>
         </tr>
       )}
@@ -1020,7 +1041,7 @@ function WithdrawDetails({
       <tr>
         <td>Total</td>
         <td>
-          <Amount value={transaction.amountEffective} />
+          <Amount value={transaction.amountEffective} maxFracSize={maxFrac} />
         </td>
       </tr>
     </PurchaseDetailsTable>
@@ -1059,9 +1080,8 @@ function Header({
         <SubTitle>
           <Part
             title={type}
-            text={<Amount value={total} />}
+            text={<Amount value={total} negative={kind === "negative"} />}
             kind={kind}
-            showSign
           />
         </SubTitle>
       </div>

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]