From d6d56479469f0e7fc050976908c7abcacd61bc27 Mon Sep 17 00:00:00 2001 From: Marcos Gutierrez Date: Mon, 27 Jan 2020 10:11:39 -0300 Subject: add new history view and some global style changes --- src/webex/pages/popup.tsx | 432 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 342 insertions(+), 90 deletions(-) (limited to 'src/webex/pages/popup.tsx') diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx index b26e86e65..f873414a1 100644 --- a/src/webex/pages/popup.tsx +++ b/src/webex/pages/popup.tsx @@ -42,9 +42,12 @@ import { } from "../renderHtml"; import * as wxApi from "../wxApi"; -import * as React from "react"; +import React, { Fragment } from "react"; import { HistoryEvent } from "../../types/history"; +import moment from "moment"; +import { Timestamp } from "../../util/time"; + function onUpdateNotification(f: () => void): () => void { const port = chrome.runtime.connect({ name: "notifications" }); const listener = () => { @@ -185,7 +188,7 @@ function bigAmount(amount: AmountJson): JSX.Element { const v = amount.value + amount.fraction / Amounts.fractionalBase; return ( - {v}{" "} + {v}{" "} {amount.currency} ); @@ -193,12 +196,10 @@ function bigAmount(amount: AmountJson): JSX.Element { function EmptyBalanceView() { return ( -
- - You have no balance to show. Need some{" "} - help getting started? - -
+ + You have no balance to show. Need some{" "} + help getting started? + ); } @@ -299,7 +300,7 @@ class WalletBalanceView extends React.Component { const wallet = this.balance; if (this.gotError) { return ( -
+

{i18n.str`Error: could not retrieve balance information.`}

Click here for help and @@ -320,114 +321,354 @@ class WalletBalanceView extends React.Component {

); }); - return
{listing.length > 0 ? listing : }
; + return listing.length > 0 ?
{listing}
: ; } } +function Icon({ l }: { l: string }) { + return
{l}
; +} + +function formatAndCapitalize(text: string) { + text = text.replace("-", " "); + text = text.replace(/^./, text[0].toUpperCase()); + return text; +} + +type HistoryItemProps = { + title?: string | JSX.Element; + text?: string | JSX.Element; + small?: string | JSX.Element; + amount?: string | AmountJson; + fees?: string | AmountJson; + invalid?: string | AmountJson; + icon?: string; + timestamp: Timestamp; + negative?: boolean; +}; + +function HistoryItem({ + title, + text, + small, + amount, + fees, + invalid, + timestamp, + icon, + negative = false +}: HistoryItemProps) { + function formatDate(timestamp: number | "never") { + if (timestamp !== "never") { + const itemDate = moment(timestamp); + if (itemDate.isBetween(moment().subtract(2, "days"), moment())) { + return itemDate.fromNow(); + } + return itemDate.format("lll"); + } + return null; + } + + let invalidElement, amountElement, feesElement; + + if (amount) { + amountElement = renderAmount(amount); + } + + if (fees) { + fees = typeof fees === "string" ? Amounts.parse(fees) : fees; + if (fees && Amounts.isNonZero(fees)) { + feesElement = renderAmount(fees); + } + } + + if (invalid) { + invalid = typeof invalid === "string" ? Amounts.parse(invalid) : invalid; + if (invalid && Amounts.isNonZero(invalid)) { + invalidElement = renderAmount(invalid); + } + } + + return ( +
+ {icon ? : null} +
+ {title ?
{title}
: null} + {text ?
{text}
: null} + {small ?
{small}
: null} +
+
+
+ {amountElement ? ( +
+ {amountElement} +
+ ) : null} + {invalidElement ? ( +
+ {i18n.str`Invalid `}{" "} + {invalidElement} +
+ ) : null} + {feesElement ? ( +
+ {i18n.str`Fees `}{" "} + {feesElement} +
+ ) : null} +
+
{formatDate(timestamp.t_ms)}
+
+
+ ); +} + +function amountDiff( + total: string | Amounts.AmountJson, + partial: string | Amounts.AmountJson +): Amounts.AmountJson | string { + let a = typeof total === "string" ? Amounts.parse(total) : total; + let b = typeof partial === "string" ? Amounts.parse(partial) : partial; + if (a && b) { + return Amounts.sub(a, b).amount; + } else { + return total; + } +} + + +function parseSummary(summary: string) { + let parsed = summary.split(/: (.+)/); + return { + merchant: parsed[0], + item: parsed[1] + }; +} + function formatHistoryItem(historyItem: HistoryEvent) { - const d = historyItem; - console.log("hist item", historyItem); switch (historyItem.type) { - /* - case "create-reserve": + case "refreshed": { return ( - - Bank requested reserve ({abbrev(d.reservePub)}) for{" "} - {renderAmount(d.requestedAmount)}. - + + ); + } + + case "order-refused": { + const { merchant, item } = parseSummary( + historyItem.orderShortInfo.summary ); - case "confirm-reserve": { - const exchange = new URL(d.exchangeBaseUrl).host; - const pub = abbrev(d.reservePub); return ( - - Started to withdraw - {renderAmount(d.requestedAmount)} - from {exchange} ({pub}). - + ); } - case "offer-contract": { + + case "order-redirected": { + const { merchant, item } = parseSummary( + historyItem.newOrderShortInfo.summary + ); return ( - - Merchant {abbrev(d.merchantName, 15)} offered contract{" "} - {abbrev(d.contractTermsHash)}. - + ); } - case "depleted-reserve": { - const exchange = d.exchangeBaseUrl - ? new URL(d.exchangeBaseUrl).host - : "??"; - const amount = renderAmount(d.requestedAmount); - const pub = abbrev(d.reservePub); + + case "payment-aborted": { + const { merchant, item } = parseSummary( + historyItem.orderShortInfo.summary + ); return ( - - Withdrew {amount} from {exchange} ( - {pub}). - + ); } - case "pay": { - const url = d.fulfillmentUrl; - const merchantElem = {abbrev(d.merchantName, 15)}; + + case "payment-sent": { + const url = historyItem.orderShortInfo.merchantBaseUrl; + const { merchant, item } = parseSummary( + historyItem.orderShortInfo.summary + ); + const fees = amountDiff( + historyItem.amountPaidWithFees, + historyItem.orderShortInfo.amount + ); const fulfillmentLinkElem = ( - - view product - + + + {item ? abbrev(item, 30) : null} + + ); return ( - - Paid {renderAmount(d.amount)} to merchant{" "} - {merchantElem}. ( - {fulfillmentLinkElem}) - + + ); + } + case "order-accepted": { + const url = historyItem.orderShortInfo.merchantBaseUrl; + const { merchant, item } = parseSummary( + historyItem.orderShortInfo.summary + ); + const fulfillmentLinkElem = ( + + + {item ? abbrev(item, 40) : null} + + + ); + return ( + + ); + } + case "reserve-balance-updated": { + return ( + ); } case "refund": { - const merchantElem = {abbrev(d.merchantName, 15)}; + const merchantElem = ( + {abbrev(historyItem.orderShortInfo.summary, 25)} + ); return ( - - Merchant {merchantElem} gave a refund over{" "} - {renderAmount(d.refundAmount)}. - + ); } - case "tip": { - const tipPageUrl = new URL(chrome.extension.getURL("/src/webex/pages/tip.html")); - tipPageUrl.searchParams.set("tip_id", d.tipId); - tipPageUrl.searchParams.set("merchant_domain", d.merchantDomain); - const url = tipPageUrl.href; - const tipLink = {i18n.str`tip`}; - // i18n: Tip + case "withdrawn": { + const exchange = new URL(historyItem.exchangeBaseUrl).host; + const fees = amountDiff( + historyItem.amountWithdrawnRaw, + historyItem.amountWithdrawnEffective + ); + return ( + + ); + } + case "tip-accepted": { + return ( + Tip Accepted} + amount={historyItem.tipAmountRaw} + /> + ); + } + case "tip-declined": { return ( - <> - - Merchant {d.merchantDomain} gave a{" "} - {tipLink} of {renderAmount(d.amount)}. - - - {" "} - {d.accepted ? null : ( - You did not accept the tip yet. - )} - - + Tip Declined} + amount={historyItem.tipAmountRaw} + /> ); } - */ default: - return

{i18n.str`Unknown event (${historyItem.type})`}

; + return ( + + ); } } +const HistoryComponent = (props: any) => { + const record = props.record; + return formatHistoryItem(record); +}; + class WalletHistory extends React.Component { private myHistory: any[]; private gotError = false; private unmounted = false; - + private hidenTypes: string[] = [ + "order-accepted", + "order-redirected", + "refreshed", + "reserve-balance-updated", + "exchange-updated", + "exchange-added" + ]; + componentWillMount() { this.update(); + this.setState({ filter: true }); onUpdateNotification(() => this.update()); } @@ -468,21 +709,32 @@ class WalletHistory extends React.Component { } const listing: any[] = []; - for (const record of history.reverse()) { - const item = ( -
-
- {new Date(record.timestamp.t_ms).toString()} -
- {formatHistoryItem(record)} -
- ); - + const messages = history + .reverse() + .filter(hEvent => { + if (!this.state.filter) return true; + return this.hidenTypes.indexOf(hEvent.type) === -1; + }); + + for (const record of messages) { + const item = (); listing.push(item); } if (listing.length > 0) { - return
{listing}
; + return ( +
+
{listing}
+
+ Filtered list{" "} + this.setState({ filter: !this.state.filter })} + /> +
+
+ ); } return

{i18n.str`Your wallet has no events recorded.`}

; } -- cgit v1.2.3