Add copy to clipboard functionality to addresses.
This commit is contained in:
parent
a2e320d923
commit
4030f709fc
54
src/app/_helpers/clipboard-copy.ts
Normal file
54
src/app/_helpers/clipboard-copy.ts
Normal 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
|
||||
};
|
@ -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';
|
||||
|
@ -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>
|
||||
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 { }
|
||||
|
@ -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>
|
||||
|
@ -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,15 +14,21 @@ 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 {
|
||||
this.senderBloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.transaction?.from + '/transactions';
|
||||
this.recipientBloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.transaction?.to + '/transactions';
|
||||
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> {
|
||||
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 { }
|
||||
|
1
src/assets/images/checklist.svg
Normal file
1
src/assets/images/checklist.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.8 KiB |
Loading…
Reference in New Issue
Block a user