Add copy to clipboard functionality to addresses.

This commit is contained in:
Spencer Ofwiti 2021-04-26 13:14:36 +03:00
parent a2e320d923
commit 4030f709fc
9 changed files with 129 additions and 16 deletions

View File

@ -0,0 +1,54 @@
function copyToClipboard(text: any): boolean {
// create our hidden div element
const hiddenCopy = document.createElement('div');
// set the innerHTML of the div
hiddenCopy.innerHTML = text;
// set the position to be absolute and off the screen
hiddenCopy.style.position = 'absolute';
hiddenCopy.style.left = '-9999px';
// check and see if the user had a text selection range
let currentRange;
if (document.getSelection().rangeCount > 0) {
// the user has a text selection range, store it
currentRange = document.getSelection().getRangeAt(0);
// remove the current selection
window.getSelection().removeRange(currentRange);
} else {
// they didn't have anything selected
currentRange = false;
}
// append the div to the body
document.body.appendChild(hiddenCopy);
// create a selection range
const copyRange = document.createRange();
// set the copy range to be the hidden div
copyRange.selectNode(hiddenCopy);
// add the copy range
window.getSelection().addRange(copyRange);
// since not all browsers support this, use a try block
try {
// copy the text
document.execCommand('copy');
} catch (err) {
window.alert('Your Browser Doesn\'t support this! Error : ' + err);
return false;
}
// remove the selection range (Chrome throws a warning if we don't.)
window.getSelection().removeRange(copyRange);
// remove the hidden div
document.body.removeChild(hiddenCopy);
// return the old selection range
if (currentRange) {
window.getSelection().addRange(currentRange);
}
return true;
}
export {
copyToClipboard
};

View File

@ -6,3 +6,4 @@ export * from '@app/_helpers/http-getter';
export * from '@app/_helpers/global-error-handler';
export * from '@app/_helpers/export-csv';
export * from '@app/_helpers/read-csv';
export * from '@app/_helpers/clipboard-copy';

View File

@ -35,7 +35,10 @@
</h3>
<span class="ml-auto"><strong>Balance:</strong> {{account?.balance | tokenRatio}} SRF</span>
<span class="ml-2"><strong>Created:</strong> {{account?.date_registered | date}}</span>
<span class="ml-2"><strong>Address:</strong><a href="{{bloxbergLink}}" target="_blank"> {{account?.identities.evm['bloxberg:8996']}} </a></span>
<span class="ml-2"><strong>Address:</strong>
<a href="{{bloxbergLink}}" target="_blank"> {{accountAddress}} </a>
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress()" alt="Copy">
</span>
</div>
</div>
<div *ngIf="account" class="card mt-3 mb-3">
@ -176,13 +179,13 @@
</div>
<div class="col-md-6 col-lg-4">
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-primary mb-3">
<button mat-raised-button color="primary" type="button" class="btn btn-outline-primary mb-3">
Add User KYC
</button>
</div>
<div class="col-md-6 col-lg-4">
<button mat-raised-button color="primary" type="button" class="btn btn btn-outline-success mb-3"
<button mat-raised-button color="primary" type="button" class="btn btn-outline-success mb-3"
(click)="resetPin()">
Reset Pin
</button>

View File

@ -6,7 +6,8 @@ import {BlockSyncService, LocationService, LoggingService, TokenService, Transac
import {ActivatedRoute, Params, Router} from '@angular/router';
import {first} from 'rxjs/operators';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher, exportCsv} from '@app/_helpers';
import {copyToClipboard, CustomErrorStateMatcher, exportCsv} from '@app/_helpers';
import {MatSnackBar} from '@angular/material/snack-bar';
@Component({
selector: 'app-account-details',
@ -54,6 +55,7 @@ export class AccountDetailsComponent implements OnInit {
private loggingService: LoggingService,
private blockSyncService: BlockSyncService,
private cdr: ChangeDetectorRef,
private snackBar: MatSnackBar,
) {
this.accountInfoForm = this.formBuilder.group({
name: ['', Validators.required],
@ -190,4 +192,10 @@ export class AccountDetailsComponent implements OnInit {
downloadCsv(data: any, filename: string): void {
exportCsv(data, filename);
}
copyAddress(): void {
if (copyToClipboard(this.accountAddress)) {
this.snackBar.open(this.accountAddress + ' copied successfully!', 'Close', { duration: 3000 });
}
}
}

View File

@ -25,6 +25,7 @@ import {MatRippleModule} from '@angular/material/core';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {ReactiveFormsModule} from '@angular/forms';
import { AccountSearchComponent } from './account-search/account-search.component';
import {MatSnackBarModule} from '@angular/material/snack-bar';
@NgModule({
@ -55,7 +56,8 @@ import { AccountSearchComponent } from './account-search/account-search.componen
MatTabsModule,
MatRippleModule,
MatProgressSpinnerModule,
ReactiveFormsModule
ReactiveFormsModule,
MatSnackBarModule,
]
})
export class AccountsModule { }

View File

@ -13,12 +13,20 @@
<ul class="list-group list-group-flush">
<li class="list-group-item">
<span>Sender: {{transaction.sender?.vcard.fn[0].value}}</span><br><br>
<span>Sender Address: <a href="{{senderBloxbergLink}}" target="_blank"> {{transaction.from}} </a></span><br><br>
<span>
Sender Address:
<a href="{{senderBloxbergLink}}" target="_blank"> {{transaction.from}} </a>
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.from)" alt="Copy">
</span><br><br>
<button mat-raised-button color="primary" class="btn btn-outline-info" (click)="viewSender()">View Sender</button>
</li>
<li class="list-group-item">
<span>Recipient: {{transaction.recipient?.vcard.fn[0].value}}</span><br><br>
<span>Recipient Address: <a href="{{recipientBloxbergLink}}" target="_blank"> {{transaction.to}} </a></span><br><br>
<span>
Recipient Address:
<a href="{{recipientBloxbergLink}}" target="_blank"> {{transaction.to}} </a>
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.to)" alt="Copy">
</span><br><br>
<button mat-raised-button color="primary" class="btn btn-outline-info" (click)="viewRecipient()">View Recipient</button>
</li>
<li class="list-group-item">
@ -28,7 +36,11 @@
<h4 class="mt-2">Token: </h4>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<span>Address: {{transaction.token._address}}</span>
<span>
Address:
{{transaction.token._address}}
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.token._address)" alt="Copy">
</span>
</li>
<li class="list-group-item">
<span>Name: Sarafu Token</span>
@ -73,17 +85,25 @@
<span><strong>Trader: {{transaction.sender?.vcard.fn[0].value}}</strong></span>
</li>
<li class="list-group-item">
<span>Trader Address: {{transaction.trader}}</span>
<span>
Trader Address:
<a href="{{traderBloxbergLink}}" target="_blank"> {{transaction.trader}} </a>
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.trader)" alt="Copy">
</span>
</li>
</ul>
<button mat-raised-button color="primary" class="btn btn-outline-info" routerLink="/accounts/1">View Trader</button>
<button mat-raised-button color="primary" class="btn btn-outline-info" (click)="viewTrader()">View Trader</button>
<br><br>
<div class="row">
<div class="col-md-6">
<h4>Source Token: </h4>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<span>Address: {{transaction.sourceToken.address}}</span>
<span>
Address:
{{transaction.sourceToken.address}}
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.sourceToken.address)" alt="Copy">
</span>
</li>
<li class="list-group-item">
<span>Name: {{transaction.sourceToken.name}}</span>
@ -100,7 +120,11 @@
<h4>Destination Token: </h4>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<span>Address: {{transaction.destinationToken.address}}</span>
<span>
Address:
{{transaction.destinationToken.address}}
<img src="assets/images/checklist.svg" class="ml-2" height="20rem" (click)="copyAddress(transaction.destinationToken.address)" alt="Copy">
</span>
</li>
<li class="list-group-item">
<span>Name: {{transaction.destinationToken.name}}</span>

View File

@ -1,6 +1,8 @@
import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {TransactionService} from '@app/_services';
import {copyToClipboard} from '../../../_helpers';
import {MatSnackBar} from '@angular/material/snack-bar';
@Component({
selector: 'app-transaction-details',
@ -12,16 +14,22 @@ export class TransactionDetailsComponent implements OnInit {
@Input() transaction;
senderBloxbergLink: string;
recipientBloxbergLink: string;
traderBloxbergLink: string;
constructor(
private router: Router,
private transactionService: TransactionService
private transactionService: TransactionService,
private snackBar: MatSnackBar,
) { }
ngOnInit(): void {
if (this.transaction.type === 'conversion') {
this.traderBloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.transaction?.trader + '/transactions';
} else {
this.senderBloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.transaction?.from + '/transactions';
this.recipientBloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.transaction?.to + '/transactions';
}
}
async viewSender(): Promise<void> {
await this.router.navigateByUrl(`/accounts/${this.transaction.from}`);
@ -31,6 +39,10 @@ export class TransactionDetailsComponent implements OnInit {
await this.router.navigateByUrl(`/accounts/${this.transaction.to}`);
}
async viewTrader(): Promise<void> {
await this.router.navigateByUrl(`/accounts/${this.transaction.trader}`);
}
async reverseTransaction(): Promise<void> {
await this.transactionService.transferRequest(
this.transaction.token.address,
@ -39,4 +51,10 @@ export class TransactionDetailsComponent implements OnInit {
this.transaction.value
);
}
copyAddress(address: string): void {
if (copyToClipboard(address)) {
this.snackBar.open(address + ' copied successfully!', 'Close', { duration: 3000 });
}
}
}

View File

@ -17,6 +17,7 @@ import {MatIconModule} from '@angular/material/icon';
import {MatSelectModule} from '@angular/material/select';
import {MatCardModule} from '@angular/material/card';
import {MatRippleModule} from '@angular/material/core';
import {MatSnackBarModule} from '@angular/material/snack-bar';
@NgModule({
@ -39,7 +40,8 @@ import {MatRippleModule} from '@angular/material/core';
MatIconModule,
MatSelectModule,
MatCardModule,
MatRippleModule
MatRippleModule,
MatSnackBarModule,
]
})
export class TransactionsModule { }

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB