Merge pull request #1766 from mempool/nymkappa/feature/fee-redesign
Rewamp the fee widget
This commit is contained in:
		
						commit
						c9b98ed841
					
				| @ -133,7 +133,7 @@ | |||||||
|     text-align: center; |     text-align: center; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     justify-content: space-around; |     justify-content: space-around; | ||||||
|     padding: 22px 20px; |     padding: 24px 20px; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -148,3 +148,7 @@ | |||||||
|   margin-right: -2px; |   margin-right: -2px; | ||||||
|   font-size: 10px; |   font-size: 10px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .symbol { | ||||||
|  |   font-size: 13px; | ||||||
|  | } | ||||||
| @ -1,19 +1,33 @@ | |||||||
| <div class="fee-estimation-wrapper"> | <div class="fee-estimation-wrapper" *ngIf="(isLoadingWebSocket$ | async) === false && (recommendedFees$ | async) as recommendedFees; else loadingFees"> | ||||||
|   <div class="fee-estimation-container" *ngIf="(isLoadingWebSocket$ | async) === false && (recommendedFees$ | async) as recommendedFees; else loadingFees"> |   <div class="fee-progress-bar" [style.background]="gradient"> | ||||||
|  |     <span class="fee-label" i18n="fees-box.minimum">Minimum</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.economy">Economy</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.low">Low</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.medium">Medium</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.high">High</span> | ||||||
|  |   </div> | ||||||
|  |   <div class="fee-estimation-container"> | ||||||
|  |     <div class="item"> | ||||||
|  |       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> | ||||||
|  |         <div class="fee-text">{{ recommendedFees.minimumFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.minimumFee * 140" ></app-fiat></span> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |     <div class="item"> | ||||||
|  |       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> | ||||||
|  |         <div class="fee-text">{{ recommendedFees.economyFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.economyFee * 140" ></app-fiat></span> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.low-priority">Low priority</h5> |  | ||||||
|       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> |       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> | ||||||
|         <div class="fee-text">{{ recommendedFees.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.hourFee * 140" ></app-fiat></span> |         <div class="fee-text">{{ recommendedFees.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.hourFee * 140" ></app-fiat></span> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.medium-priority">Medium priority</h5> |  | ||||||
|       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> |       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> | ||||||
|         <div class="fee-text">{{ recommendedFees.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.halfHourFee * 140" ></app-fiat></span> |         <div class="fee-text">{{ recommendedFees.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.halfHourFee * 140" ></app-fiat></span> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.high-priority">High priority</h5> |  | ||||||
|       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> |       <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"> | ||||||
|         <div class="fee-text">{{ recommendedFees.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.fastestFee * 140" ></app-fiat></span> |         <div class="fee-text">{{ recommendedFees.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.fastestFee * 140" ></app-fiat></span> | ||||||
|       </div> |       </div> | ||||||
| @ -22,23 +36,39 @@ | |||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| <ng-template #loadingFees> | <ng-template #loadingFees> | ||||||
|  |   <div class="fee-progress-bar" [style.background]="gradient"> | ||||||
|  |     <span class="fee-label" i18n="fees-box.minimum">Minimum</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.economy">Economy</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.low">Low</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.medium">Medium</span> | ||||||
|  |     <span class="fee-label" i18n="fees-box.high">High</span> | ||||||
|  |   </div> | ||||||
|   <div class="fee-estimation-container loading-container"> |   <div class="fee-estimation-container loading-container"> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.low-priority">Low priority</h5> |  | ||||||
|       <div class="card-text"> |       <div class="card-text"> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.medium-priority">Medium priority</h5> |  | ||||||
|       <div class="card-text"> |       <div class="card-text"> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="item"> |     <div class="item"> | ||||||
|       <h5 class="card-title" i18n="fees-box.high-priority">High priority</h5> |       <div class="card-text"> | ||||||
|  |         <div class="skeleton-loader"></div> | ||||||
|  |         <div class="skeleton-loader"></div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |     <div class="item"> | ||||||
|  |       <div class="card-text"> | ||||||
|  |         <div class="skeleton-loader"></div> | ||||||
|  |         <div class="skeleton-loader"></div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |     <div class="item"> | ||||||
|       <div class="card-text"> |       <div class="card-text"> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|         <div class="skeleton-loader"></div> |         <div class="skeleton-loader"></div> | ||||||
|  | |||||||
| @ -21,28 +21,22 @@ | |||||||
| .fee-estimation-container { | .fee-estimation-container { | ||||||
|   display: flex; |   display: flex; | ||||||
|   justify-content: space-between; |   justify-content: space-between; | ||||||
|   @media (min-width: 376px) { |   flex-direction: row; | ||||||
|     flex-direction: row; |  | ||||||
|   }   |  | ||||||
|   .item { |   .item { | ||||||
|     max-width: 150px; |     width: 100px; | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     width: -webkit-fill-available; |     width: -webkit-fill-available; | ||||||
|     @media (min-width: 376px) { |     &:first-child { | ||||||
|       margin: 0 auto 0px; |       @media (767px < width < 992px), (width < 576px) { | ||||||
|     }     |         display: none | ||||||
|     &:first-child{ |  | ||||||
|       display: none; |  | ||||||
|       @media (min-width: 485px) { |  | ||||||
|         display: block; |  | ||||||
|       }     |  | ||||||
|       @media (min-width: 768px) { |  | ||||||
|         display: none; |  | ||||||
|       }     |  | ||||||
|       @media (min-width: 992px) { |  | ||||||
|         display: block; |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     &:nth-child(2) { | ||||||
|  |       @media (767px < width < 992px), (width < 576px) { | ||||||
|  |         display: none | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     margin: 0 auto 0px; | ||||||
|     &:last-child { |     &:last-child { | ||||||
|       margin-bottom: 0; |       margin-bottom: 0; | ||||||
|     } |     } | ||||||
| @ -55,18 +49,17 @@ | |||||||
|       border-bottom: 1px solid #ffffff1c; |       border-bottom: 1px solid #ffffff1c; | ||||||
|       width: fit-content; |       width: fit-content; | ||||||
|       margin: auto; |       margin: auto; | ||||||
|       line-height: 1.45; |       font-size: 20px; | ||||||
|       padding: 0px 2px; |  | ||||||
|     } |     } | ||||||
|     .fiat { |     .fiat { | ||||||
|       display: block; |       display: block; | ||||||
|       font-size: 14px !important; |       font-size: 13px !important; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .loading-container{ | .loading-container{ | ||||||
|   min-height: 76px; |   height: 50px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .card-text { | .card-text { | ||||||
| @ -74,8 +67,8 @@ | |||||||
|     width: 100%; |     width: 100%; | ||||||
|     display: block; |     display: block; | ||||||
|     &:first-child { |     &:first-child { | ||||||
|       max-width: 90px; |       max-width: 70px; | ||||||
|       margin: 15px auto 3px; |       margin: 10px auto 3px; | ||||||
|     } |     } | ||||||
|     &:last-child { |     &:last-child { | ||||||
|       margin: 10px auto 3px; |       margin: 10px auto 3px; | ||||||
| @ -83,3 +76,31 @@ | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .fee-progress-bar { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 22px; | ||||||
|  |   margin-bottom: 12px; | ||||||
|  |   border-radius: 0px 10px 10px 0px; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   transition: background-color 1s; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .fee-label { | ||||||
|  |   font-size: 14px; | ||||||
|  |   width: 20%; | ||||||
|  |   @media (767px < width < 992px), (width < 576px) { | ||||||
|  |     width: 33%; | ||||||
|  |   } | ||||||
|  |   &:first-child { | ||||||
|  |     @media (767px < width < 992px), (width < 576px) { | ||||||
|  |       display: none | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   &:nth-child(2) { | ||||||
|  |     @media (767px < width < 992px), (width < 576px) { | ||||||
|  |       display: none | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,14 +1,9 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from 'src/app/services/state.service'; | ||||||
| import { map, filter, tap } from 'rxjs/operators'; | import { Observable } from 'rxjs'; | ||||||
| import { merge, Observable } from 'rxjs'; | import { Recommendedfees } from 'src/app/interfaces/websocket.interface'; | ||||||
| import { MempoolBlock, Recommendedfees } from 'src/app/interfaces/websocket.interface'; | import { feeLevels, mempoolFeeColors } from 'src/app/app.constants'; | ||||||
| 
 | import { tap } from 'rxjs/operators'; | ||||||
| interface FeeEstimations { |  | ||||||
|   fastestFee: number; |  | ||||||
|   halfHourFee: number; |  | ||||||
|   hourFee: number; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-fees-box', |   selector: 'app-fees-box', | ||||||
| @ -19,16 +14,28 @@ interface FeeEstimations { | |||||||
| export class FeesBoxComponent implements OnInit { | export class FeesBoxComponent implements OnInit { | ||||||
|   isLoadingWebSocket$: Observable<boolean>; |   isLoadingWebSocket$: Observable<boolean>; | ||||||
|   recommendedFees$: Observable<Recommendedfees>; |   recommendedFees$: Observable<Recommendedfees>; | ||||||
|   defaultFee: number; |   gradient = 'linear-gradient(to right, #2e324e, #2e324e)'; | ||||||
| 
 | 
 | ||||||
|   constructor( |   constructor( | ||||||
|     private stateService: StateService, |     private stateService: StateService | ||||||
|   ) { } |   ) { } | ||||||
| 
 | 
 | ||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|     this.defaultFee = this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet' ? 0.1 : 1; |  | ||||||
| 
 |  | ||||||
|     this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$; |     this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$; | ||||||
|     this.recommendedFees$ = this.stateService.recommendedFees$; |     this.recommendedFees$ = this.stateService.recommendedFees$ | ||||||
|  |       .pipe( | ||||||
|  |         tap((fees) => { | ||||||
|  |           let feeLevelIndex = feeLevels.slice().reverse().findIndex((feeLvl) => fees.minimumFee >= feeLvl); | ||||||
|  |           feeLevelIndex = feeLevelIndex >= 0 ? feeLevels.length - feeLevelIndex : feeLevelIndex; | ||||||
|  |           const startColor = '#' + (mempoolFeeColors[feeLevelIndex - 1] || mempoolFeeColors[mempoolFeeColors.length - 1]); | ||||||
|  | 
 | ||||||
|  |           feeLevelIndex = feeLevels.slice().reverse().findIndex((feeLvl) => fees.fastestFee >= feeLvl); | ||||||
|  |           feeLevelIndex = feeLevelIndex >= 0 ? feeLevels.length - feeLevelIndex : feeLevelIndex; | ||||||
|  |           const endColor = '#' + (mempoolFeeColors[feeLevelIndex - 1] || mempoolFeeColors[mempoolFeeColors.length - 1]); | ||||||
|  | 
 | ||||||
|  |           this.gradient = `linear-gradient(to right, ${startColor}, ${endColor})`; | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -238,7 +238,6 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { | |||||||
|       gradientColors.push(mempoolFeeColors[feeLevelIndex - 1] || mempoolFeeColors[mempoolFeeColors.length - 1]); |       gradientColors.push(mempoolFeeColors[feeLevelIndex - 1] || mempoolFeeColors[mempoolFeeColors.length - 1]); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     gradientColors.forEach((color, i, gc) => { |     gradientColors.forEach((color, i, gc) => { | ||||||
|       backgroundGradients.push(` |       backgroundGradients.push(` | ||||||
|         #${i === 0 ? color : gc[i - 1]} ${ i === 0 ? emptyBackgroundSpacePercentage : ((i / gradientColors.length) * 100) * usedBlockSpace / 100 + emptyBackgroundSpacePercentage }%, |         #${i === 0 ? color : gc[i - 1]} ${ i === 0 ? emptyBackgroundSpacePercentage : ((i / gradientColors.length) * 100) * usedBlockSpace / 100 + emptyBackgroundSpacePercentage }%, | ||||||
|  | |||||||
| @ -64,7 +64,7 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .more-padding { | .more-padding { | ||||||
|   padding: 18px; |   padding: 24px 20px !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .card-wrapper { | .card-wrapper { | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
|       <div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'"> |       <div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'"> | ||||||
|         <div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div> |         <div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div> | ||||||
|         <div class="card"> |         <div class="card"> | ||||||
|           <div class="card-body"> |           <div class="card-body less-padding"> | ||||||
|             <app-fees-box class="d-block"></app-fees-box> |             <app-fees-box class="d-block"></app-fees-box> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
| @ -33,7 +33,7 @@ | |||||||
|         <div class="col card-wrapper"> |         <div class="col card-wrapper"> | ||||||
|           <div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div> |           <div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div> | ||||||
|           <div class="card"> |           <div class="card"> | ||||||
|             <div class="card-body"> |             <div class="card-body less-padding"> | ||||||
|               <app-fees-box class="d-block"></app-fees-box> |               <app-fees-box class="d-block"></app-fees-box> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  | |||||||
| @ -269,6 +269,9 @@ | |||||||
|     justify-content: space-around; |     justify-content: space-around; | ||||||
|     padding: 22px 20px; |     padding: 22px 20px; | ||||||
|   } |   } | ||||||
|  |   .less-padding { | ||||||
|  |     padding: 20px 20px; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .retarget-sign { | .retarget-sign { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user