Skip to content

Commit

Permalink
Added mosaic envelop icon and tooltips for transaction list. (#1549)
Browse files Browse the repository at this point in the history
* feat: add new icon image.

* feat: add icon and tooltip feature for mosaic and message.

* fix: adjust css for tooltips.

* fix: wrong format tooltips mosaics to relative amount.

* Update en-US.json

Co-authored-by: OlegMakarenko <33131259+OlegMakarenko@users.noreply.github.com>
  • Loading branch information
AnthonyLaw and OlegMakarenko committed Jun 24, 2021
1 parent fa8a9b5 commit 29d52f6
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 19 deletions.
44 changes: 37 additions & 7 deletions src/components/TransactionList/TransactionRow/TransactionRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,43 @@

<!-- THIRD COLUMN -->
<div class="amount-cell">
<MosaicAmountDisplay
v-if="getAmount() !== undefined"
:id="getAmountMosaicId()"
:absolute-amount="getAmount()"
:color="getAmountColor()"
:show-ticker="isAmountShowTicker()"
/>
<div v-if="hasNonNativeMosaic() || hasNetworkMosaic()">
<MosaicAmountDisplay
v-if="hasNetworkMosaic()"
:id="getAmountMosaicId()"
:absolute-amount="getAmount()"
:color="getAmountColor()"
:show-ticker="isAmountShowTicker()"
/>

<!-- Mosaic icon for non native mosaics. -->
<div v-if="hasNonNativeMosaic()" class="extend-icon-holder">
<Tooltip placement="right">
<img :src="getMosaicsIcon()" />
<div slot="content">
<!-- allow top 5 mosaics show in the tooltip -->
<div v-for="mosaic in nonNativeMosaicList().slice(0, numberOfShowMosicsTooltips)" :key="mosaic.id">
{{ mosaic.name }} - {{ mosaic.relativeAmount }}
</div>

<div v-if="nonNativeMosaicList().length - numberOfShowMosicsTooltips > 0">
{{ $t('tooltip_mosaic_view_more', { count: nonNativeMosaicList().length - numberOfShowMosicsTooltips }) }}
</div>
</div>
</Tooltip>
</div>

<!-- Message icon on transaction list -->
<div v-if="hasMessage()" class="extend-icon-holder">
<Tooltip placement="right">
<img :src="getEnvelopeIcon()" />
<div slot="content">
{{ messagePayload }}
</div>
</Tooltip>
</div>
</div>

<span v-else>N/A</span>
</div>

Expand Down
125 changes: 119 additions & 6 deletions src/components/TransactionList/TransactionRow/TransactionRowTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
// internal dependencies
import { Formatters } from '@/core/utils/Formatters';
import { TimeHelpers } from '@/core/utils/TimeHelpers';
import { MosaicModel } from '@/core/database/entities/MosaicModel';
// child components
// @ts-ignore
import MosaicAmountDisplay from '@/components/MosaicAmountDisplay/MosaicAmountDisplay.vue';
Expand All @@ -48,6 +49,11 @@ import { DateTimeFormatter } from '@js-joda/core';
import { AccountModel } from '@/core/database/entities/AccountModel';
import { TransactionStatus as TransactionStatusEnum } from '@/core/transactions/TransactionStatus';

export interface TooltipMosaics {
name: string;
relativeAmount: string;
}

@Component({
components: {
ActionDisplay,
Expand All @@ -60,6 +66,7 @@ import { TransactionStatus as TransactionStatusEnum } from '@/core/transactions/
currentProfile: 'profile/currentProfile',
currentAccount: 'account/currentAccount',
currentAccountMultisigInfo: 'account/currentAccountMultisigInfo',
balanceMosaics: 'mosaic/balanceMosaics',
}),
})
export class TransactionRowTs extends Vue {
Expand Down Expand Up @@ -117,6 +124,11 @@ export class TransactionRowTs extends Vue {
* @type {AggregateTransaction}
*/
private aggregateTransactionDetails: AggregateTransaction;
/**
* Get balance mosaics info.
* @type {AggregateTransaction}
*/
private balanceMosaics: MosaicModel[];
/**
* Checks wether transaction is signed
* @type {boolean}
Expand Down Expand Up @@ -181,20 +193,29 @@ export class TransactionRowTs extends Vue {
return this.view.isIncoming;
}

public getMosaicsIcon(): string {
return officialIcons.mosaics;
}

public getEnvelopeIcon(): string {
return officialIcons.envelope;
}

/**
* Returns the amount to be shown. The first mosaic or the paid fee.
* Returns the XYM amount to be shown.
*/
public getAmount(): number {
if (this.transaction.type === TransactionType.TRANSFER) {
// We may prefer XYM over other mosaic if XYM is 2nd+
const transferTransaction = this.transaction as TransferTransaction;
const amount = (transferTransaction.mosaics.length && transferTransaction.mosaics[0].amount.compact()) || 0;
const amount = transferTransaction.mosaics.find((mosaic) => mosaic.id.equals(this.networkMosaic)).amount.compact() || 0;

if (!this.isIncomingTransaction()) {
return -amount;
}
return amount;
}
return undefined;

return 0;
}

/**
Expand All @@ -213,9 +234,8 @@ export class TransactionRowTs extends Vue {
*/
public getAmountMosaicId(): MosaicId | NamespaceId | undefined {
if (this.transaction.type === TransactionType.TRANSFER) {
// We may prefer XYM over other mosaic if XYM is 2nd+
const transferTransaction = this.transaction as TransferTransaction;
return (transferTransaction.mosaics.length && transferTransaction.mosaics[0].id) || undefined;
return transferTransaction.mosaics.find((mosaic) => mosaic.id.equals(this.networkMosaic)).id || undefined;
}
return undefined;
}
Expand Down Expand Up @@ -281,6 +301,92 @@ export class TransactionRowTs extends Vue {
}
return;
}

/**
* Check the transaction included message.
* @returns boolean
*/
public hasMessage(): boolean {
if (this.transaction.type === TransactionType.TRANSFER) {
const transferTransaction = this.transaction as TransferTransaction;
const payload = transferTransaction.message.payload;
return typeof payload === 'string' && payload.length > 0;
}
return false;
}

/**
* Check the transaction included network mosaic (XYM).
* @returns boolean
*/
public hasNetworkMosaic(): boolean {
if (this.transaction.type === TransactionType.TRANSFER) {
const transferTransaction = this.transaction as TransferTransaction;

return transferTransaction.mosaics.filter((mosaic) => mosaic.id.equals(this.networkMosaic)).length > 0;
}
return false;
}

/**
* Check the transaction included Non network mosaic (XYM).
* @returns boolean
*/
public hasNonNativeMosaic(): boolean {
if (this.transaction.type === TransactionType.TRANSFER) {
const transferTransaction = this.transaction as TransferTransaction;

return transferTransaction.mosaics.filter((mosaic) => !mosaic.id.equals(this.networkMosaic)).length > 0;
}
return false;
}

/**
* Gets mosaics list excluded network mosaics.
* @returns
*/
public nonNativeMosaicList(): TooltipMosaics[] {
if (this.transaction.type === TransactionType.TRANSFER) {
const transferTransaction = this.transaction as TransferTransaction;

return transferTransaction.mosaics
.filter((mosaic) => !mosaic.id.equals(this.networkMosaic))
.map((mosaic) => {
const mosaicInfo = this.balanceMosaics.find((mosaicInfo) => mosaicInfo.mosaicIdHex === mosaic.id.toHex());

if (mosaicInfo) {
return {
name: mosaicInfo.name || mosaicInfo.mosaicIdHex,
relativeAmount: Formatters.formatNumber(mosaic.amount.compact() / Math.pow(10, mosaicInfo.divisibility)),
};
} else {
return {
name: mosaic.id.toHex(),
relativeAmount: Formatters.formatNumber(mosaic.amount.compact()),
};
}
});
}
return [];
}

/**
* Gets transaction message payload.
* @returns string
*/
public get messagePayload(): string {
if (this.transaction.type === TransactionType.TRANSFER) {
const transferTransaction = this.transaction as TransferTransaction;

if (transferTransaction.message.payload.length > 40) {
return `${transferTransaction.message.payload.slice(0, 40)}...`;
}
return transferTransaction.message.payload;
}

return '';
}

private get hasMissSignatures(): boolean {
//merkleComponentHash ==='000000000000...' present that the transaction is still lack of signature
return (
Expand All @@ -290,6 +396,13 @@ export class TransactionRowTs extends Vue {
);
}

/**
* Default set top 5 mosaics.
*/
private get numberOfShowMosicsTooltips(): number {
return 5;
}

@Watch('transaction', { immediate: true })
private async fetchTransaction() {
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

.transaction-rows-outer-container {
display: block;
position: relative;
width: 100%;
max-height: 100%;
}
Expand All @@ -51,7 +50,6 @@
display: grid;
grid-auto-rows: @rowHeight;
width: 100%;
position: relative;
}

.transaction-row-container:hover {
Expand Down Expand Up @@ -96,8 +94,19 @@
}

.amount-cell {
text-align: center;
text-align: right;
font-family: @symbolFont;

.extend-icon-holder {
display: inline-flex;
padding: 0.05rem;
vertical-align: sub;

img {
width: 0.2rem;
height: 0.2rem;
}
}
}

.confirmation-cell {
Expand Down
3 changes: 2 additions & 1 deletion src/language/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1121,5 +1121,6 @@
"optin_postlaunch_tx_nis_address": "Opted-in NEM NIS1 account",
"show_details": "Show details",
"hide_details": "Hide details",
"transaction_signed": "Signed Successfully"
"transaction_signed": "Signed Successfully",
"tooltip_mosaic_view_more": "And {count} more..."
}
3 changes: 2 additions & 1 deletion src/language/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -1121,5 +1121,6 @@
"optin_postlaunch_tx_nis_address": "オプトイン済みのNEM NIS1アカウント",
"show_details": "詳細を表示",
"hide_details": "隠す",
"transaction_signed": "正常に署名されました"
"transaction_signed": "正常に署名されました",
"tooltip_mosaic_view_more": "そしてさらに{count}..."
}
3 changes: 2 additions & 1 deletion src/language/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1121,5 +1121,6 @@
"optin_postlaunch_tx_nis_address": "选择加入NEM NIS1账户",
"show_details": "显示详细信息",
"hide_details": "隐藏详细信息",
"transaction_signed": "已签"
"transaction_signed": "已签",
"tooltip_mosaic_view_more": "还有{count}个..."
}
6 changes: 6 additions & 0 deletions src/views/resources/Images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ import encryptedMessage from '@/views/resources/img/icons/encrypted-message.png'
// @ts-ignore
import enterprise from '@/views/resources/img/icons/enterprise.png';
// @ts-ignore
import envelope from '@/views/resources/img/icons/envelope.png';
// @ts-ignore
import explorer from '@/views/resources/img/newicons/NavExplorer.svg';
// @ts-ignore
import fingerprint from '@/views/resources/img/icons/fingerprint.png';
Expand All @@ -153,6 +155,8 @@ import metadata from '@/views/resources/img/icons/metadata.png';
// @ts-ignore
import mosaic from '@/views/resources/img/icons/mosaic.svg';
// @ts-ignore
import mosaics from '@/views/resources/img/icons/mosaics.png';
// @ts-ignore
import mosaicTransaction from '@/views/resources/img/icons/mosaic.png';
// @ts-ignore
import mosaicRestriction from '@/views/resources/img/icons/mosaic-restriction.png';
Expand Down Expand Up @@ -314,6 +318,7 @@ export const officialIcons = {
delegatedHarvesting,
encryptedMessage,
enterprise,
envelope,
explorer,
fingerprint,
harvest,
Expand All @@ -323,6 +328,7 @@ export const officialIcons = {
message,
metadata,
mosaic,
mosaics,
mosaicRestriction,
mosaicTransaction,
multipleParties,
Expand Down
Binary file added src/views/resources/img/icons/envelope.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/views/resources/img/icons/mosaics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 29d52f6

Please sign in to comment.