add toggle to enable/disable block audits
This commit is contained in:
		
							parent
							
								
									94add379d0
								
							
						
					
					
						commit
						2ed49cf944
					
				| @ -23,13 +23,20 @@ | |||||||
| 
 | 
 | ||||||
|     <div class="grow"></div> |     <div class="grow"></div> | ||||||
| 
 | 
 | ||||||
|  |     <div class="audit-toggle" *ngIf="webGlEnabled && auditAvailable"> | ||||||
|  |       <app-toggle | ||||||
|  |         textLeft="audit" | ||||||
|  |         i18n-textLeft="block.audit-mode" | ||||||
|  |         [checked]="auditModeEnabled" | ||||||
|  |         (toggleStatusChanged)="toggleAuditMode($event)" | ||||||
|  |       ></app-toggle> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|     <button [routerLink]="['/' | relativeUrl]" class="btn btn-sm">✕</button> |     <button [routerLink]="['/' | relativeUrl]" class="btn btn-sm">✕</button> | ||||||
|   </div> |   </div> | ||||||
| 
 | 
 | ||||||
|   <div class="clearfix"></div> |   <div class="clearfix"></div> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   <div class="box" *ngIf="!error"> |   <div class="box" *ngIf="!error"> | ||||||
|     <div class="row"> |     <div class="row"> | ||||||
|       <div class="col-sm"> |       <div class="col-sm"> | ||||||
| @ -54,7 +61,7 @@ | |||||||
|                 <td i18n="block.weight">Weight</td> |                 <td i18n="block.weight">Weight</td> | ||||||
|                 <td [innerHTML]="'‎' + (block.weight | wuBytes: 2)"></td> |                 <td [innerHTML]="'‎' + (block.weight | wuBytes: 2)"></td> | ||||||
|               </tr> |               </tr> | ||||||
|               <tr *ngIf="!auditDataMissing && indexingAvailable"> |               <tr *ngIf="auditAvailable"> | ||||||
|                 <td i18n="block.health">Block health</td> |                 <td i18n="block.health">Block health</td> | ||||||
|                 <td> |                 <td> | ||||||
|                   <span |                   <span | ||||||
| @ -88,21 +95,21 @@ | |||||||
|               <tr> |               <tr> | ||||||
|                 <td colspan="2"><span class="skeleton-loader"></span></td> |                 <td colspan="2"><span class="skeleton-loader"></span></td> | ||||||
|               </tr> |               </tr> | ||||||
|               <tr *ngIf="!auditDataMissing && indexingAvailable"> |               <tr *ngIf="showAudit"> | ||||||
|                 <td colspan="2"><span class="skeleton-loader"></span></td> |                 <td colspan="2"><span class="skeleton-loader"></span></td> | ||||||
|               </tr> |               </tr> | ||||||
|             </ng-template> |             </ng-template> | ||||||
|             <ng-container *ngIf="isMobile || (webGlEnabled && (auditDataMissing || !indexingAvailable)); then restOfTable;"></ng-container> |             <ng-container *ngIf="isMobile || (webGlEnabled && !showAudit); then restOfTable;"></ng-container> | ||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
|       </div> |       </div> | ||||||
|       <div class="col-sm"> |       <div class="col-sm"> | ||||||
|         <table class="table table-borderless table-striped" *ngIf="!isMobile && !(webGlEnabled && (auditDataMissing || !indexingAvailable))"> |         <table class="table table-borderless table-striped" *ngIf="!isMobile && !(webGlEnabled && !showAudit)"> | ||||||
|           <tbody> |           <tbody> | ||||||
|             <ng-container *ngTemplateOutlet="restOfTable"></ng-container> |             <ng-container *ngTemplateOutlet="restOfTable"></ng-container> | ||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
|         <div class="col-sm chart-container" *ngIf="webGlEnabled && (!indexingAvailable || auditDataMissing)"> |         <div class="col-sm chart-container" *ngIf="webGlEnabled && !showAudit"> | ||||||
|           <app-block-overview-graph |           <app-block-overview-graph | ||||||
|             #blockGraphActual |             #blockGraphActual | ||||||
|             [isLoading]="isLoadingOverview" |             [isLoading]="isLoadingOverview" | ||||||
| @ -204,8 +211,8 @@ | |||||||
|   <br> |   <br> | ||||||
| 
 | 
 | ||||||
|   <!-- VISUALIZATIONS --> |   <!-- VISUALIZATIONS --> | ||||||
|   <div class="box" *ngIf="!error && webGlEnabled && indexingAvailable && !auditDataMissing"> |   <div class="box" *ngIf="!error && webGlEnabled && showAudit"> | ||||||
|     <div class="nav nav-tabs" *ngIf="isMobile && auditEnabled"> |     <div class="nav nav-tabs" *ngIf="isMobile && showAudit"> | ||||||
|       <a class="nav-link" [class.active]="mode === 'projected'" i18n="block.projected" |       <a class="nav-link" [class.active]="mode === 'projected'" i18n="block.projected" | ||||||
|         fragment="projected" (click)="changeMode('projected')">Projected</a> |         fragment="projected" (click)="changeMode('projected')">Projected</a> | ||||||
|       <a class="nav-link" [class.active]="mode === 'actual'" i18n="block.actual" |       <a class="nav-link" [class.active]="mode === 'actual'" i18n="block.actual" | ||||||
| @ -217,7 +224,7 @@ | |||||||
|         <div class="block-graph-wrapper"> |         <div class="block-graph-wrapper"> | ||||||
|           <app-block-overview-graph #blockGraphProjected [isLoading]="isLoadingOverview" [resolution]="75" |           <app-block-overview-graph #blockGraphProjected [isLoading]="isLoadingOverview" [resolution]="75" | ||||||
|             [blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" |             [blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" | ||||||
|             (txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="!isMobile && !auditEnabled"></app-block-overview-graph> |             (txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="!isMobile && !showAudit"></app-block-overview-graph> | ||||||
|           <ng-container *ngIf="!isMobile || mode !== 'actual'; else emptyBlockInfo"></ng-container> |           <ng-container *ngIf="!isMobile || mode !== 'actual'; else emptyBlockInfo"></ng-container> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @ -226,7 +233,7 @@ | |||||||
|         <div class="block-graph-wrapper"> |         <div class="block-graph-wrapper"> | ||||||
|           <app-block-overview-graph #blockGraphActual [isLoading]="isLoadingOverview" [resolution]="75" |           <app-block-overview-graph #blockGraphActual [isLoading]="isLoadingOverview" [resolution]="75" | ||||||
|             [blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" mode="mined" |             [blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" mode="mined" | ||||||
|             (txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="isMobile && !auditEnabled"></app-block-overview-graph> |             (txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="isMobile && !showAudit"></app-block-overview-graph> | ||||||
|           <ng-container *ngTemplateOutlet="emptyBlockInfo"></ng-container> |           <ng-container *ngTemplateOutlet="emptyBlockInfo"></ng-container> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|  | |||||||
| @ -223,3 +223,10 @@ h1 { | |||||||
|     margin-right: 1em; |     margin-right: 1em; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .audit-toggle { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-right: 1em; | ||||||
|  | } | ||||||
| @ -58,8 +58,9 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|   overviewError: any = null; |   overviewError: any = null; | ||||||
|   webGlEnabled = true; |   webGlEnabled = true; | ||||||
|   indexingAvailable = false; |   indexingAvailable = false; | ||||||
|   auditEnabled = true; |   auditModeEnabled: boolean = !this.stateService.hideAudit.value; | ||||||
|   auditDataMissing: boolean; |   auditAvailable = true; | ||||||
|  |   showAudit: boolean; | ||||||
|   isMobile = window.innerWidth <= 767.98; |   isMobile = window.innerWidth <= 767.98; | ||||||
|   hoverTx: string; |   hoverTx: string; | ||||||
|   numMissing: number = 0; |   numMissing: number = 0; | ||||||
| @ -79,6 +80,7 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|   timeLtrSubscription: Subscription; |   timeLtrSubscription: Subscription; | ||||||
|   timeLtr: boolean; |   timeLtr: boolean; | ||||||
|   childChangeSubscription: Subscription; |   childChangeSubscription: Subscription; | ||||||
|  |   auditPrefSubscription: Subscription; | ||||||
| 
 | 
 | ||||||
|   @ViewChildren('blockGraphProjected') blockGraphProjected: QueryList<BlockOverviewGraphComponent>; |   @ViewChildren('blockGraphProjected') blockGraphProjected: QueryList<BlockOverviewGraphComponent>; | ||||||
|   @ViewChildren('blockGraphActual') blockGraphActual: QueryList<BlockOverviewGraphComponent>; |   @ViewChildren('blockGraphActual') blockGraphActual: QueryList<BlockOverviewGraphComponent>; | ||||||
| @ -108,7 +110,12 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); |     this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); | ||||||
|     this.auditEnabled = this.indexingAvailable; |     this.setAuditAvailable(this.indexingAvailable); | ||||||
|  | 
 | ||||||
|  |     this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { | ||||||
|  |       this.auditModeEnabled = !hide; | ||||||
|  |       this.showAudit = this.auditAvailable && this.auditModeEnabled; | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     this.txsLoadingStatus$ = this.route.paramMap |     this.txsLoadingStatus$ = this.route.paramMap | ||||||
|       .pipe( |       .pipe( | ||||||
| @ -138,11 +145,11 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|         this.page = 1; |         this.page = 1; | ||||||
|         this.error = undefined; |         this.error = undefined; | ||||||
|         this.fees = undefined; |         this.fees = undefined; | ||||||
|         this.auditDataMissing = false; |         this.stateService.markBlock$.next({}); | ||||||
| 
 | 
 | ||||||
|         if (history.state.data && history.state.data.blockHeight) { |         if (history.state.data && history.state.data.blockHeight) { | ||||||
|           this.blockHeight = history.state.data.blockHeight; |           this.blockHeight = history.state.data.blockHeight; | ||||||
|           this.updateAuditDataMissingFromBlockHeight(this.blockHeight); |           this.updateAuditAvailableFromBlockHeight(this.blockHeight); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let isBlockHeight = false; |         let isBlockHeight = false; | ||||||
| @ -155,7 +162,7 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|         if (history.state.data && history.state.data.block) { |         if (history.state.data && history.state.data.block) { | ||||||
|           this.blockHeight = history.state.data.block.height; |           this.blockHeight = history.state.data.block.height; | ||||||
|           this.updateAuditDataMissingFromBlockHeight(this.blockHeight); |           this.updateAuditAvailableFromBlockHeight(this.blockHeight); | ||||||
|           return of(history.state.data.block); |           return of(history.state.data.block); | ||||||
|         } else { |         } else { | ||||||
|           this.isLoadingBlock = true; |           this.isLoadingBlock = true; | ||||||
| @ -217,7 +224,7 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|             this.apiService.getBlockAudit$(block.previousblockhash); |             this.apiService.getBlockAudit$(block.previousblockhash); | ||||||
|           }, 100); |           }, 100); | ||||||
|         } |         } | ||||||
|         this.updateAuditDataMissingFromBlockHeight(block.height); |         this.updateAuditAvailableFromBlockHeight(block.height); | ||||||
|         this.block = block; |         this.block = block; | ||||||
|         this.blockHeight = block.height; |         this.blockHeight = block.height; | ||||||
|         this.lastBlockHeight = this.blockHeight; |         this.lastBlockHeight = this.blockHeight; | ||||||
| @ -369,10 +376,9 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|             for (const tx of blockAudit.transactions) { |             for (const tx of blockAudit.transactions) { | ||||||
|               inBlock[tx.txid] = true; |               inBlock[tx.txid] = true; | ||||||
|             } |             } | ||||||
|             this.auditEnabled = true; |             this.setAuditAvailable(true); | ||||||
|           } else { |           } else { | ||||||
|             this.auditEnabled = false; |             this.setAuditAvailable(false); | ||||||
|             this.auditDataMissing = true; |  | ||||||
|           } |           } | ||||||
|           return blockAudit; |           return blockAudit; | ||||||
|         }), |         }), | ||||||
| @ -381,6 +387,7 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|           this.error = err; |           this.error = err; | ||||||
|           this.isLoadingOverview = false; |           this.isLoadingOverview = false; | ||||||
|           this.isLoadingAudit = false; |           this.isLoadingAudit = false; | ||||||
|  |           this.setAuditAvailable(false); | ||||||
|           return of(null); |           return of(null); | ||||||
|         }), |         }), | ||||||
|       ).subscribe((blockAudit) => { |       ).subscribe((blockAudit) => { | ||||||
| @ -440,6 +447,7 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|     this.networkChangedSubscription.unsubscribe(); |     this.networkChangedSubscription.unsubscribe(); | ||||||
|     this.queryParamsSubscription.unsubscribe(); |     this.queryParamsSubscription.unsubscribe(); | ||||||
|     this.timeLtrSubscription.unsubscribe(); |     this.timeLtrSubscription.unsubscribe(); | ||||||
|  |     this.auditSubscription.unsubscribe(); | ||||||
|     this.unsubscribeNextBlockSubscriptions(); |     this.unsubscribeNextBlockSubscriptions(); | ||||||
|     this.childChangeSubscription.unsubscribe(); |     this.childChangeSubscription.unsubscribe(); | ||||||
|   } |   } | ||||||
| @ -595,21 +603,30 @@ export class BlockComponent implements OnInit, OnDestroy { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   updateAuditDataMissingFromBlockHeight(blockHeight: number): void { |   setAuditAvailable(available: boolean): void { | ||||||
|  |     this.auditAvailable = available; | ||||||
|  |     this.showAudit = this.auditAvailable && this.auditModeEnabled; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   toggleAuditMode(event): void { | ||||||
|  |     this.stateService.hideAudit.next(!event); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   updateAuditAvailableFromBlockHeight(blockHeight: number): void { | ||||||
|     switch (this.stateService.network) { |     switch (this.stateService.network) { | ||||||
|       case 'testnet': |       case 'testnet': | ||||||
|         if (blockHeight < this.stateService.env.TESTNET_BLOCK_AUDIT_START_HEIGHT) { |         if (blockHeight < this.stateService.env.TESTNET_BLOCK_AUDIT_START_HEIGHT) { | ||||||
|           this.auditDataMissing = true; |           this.setAuditAvailable(true); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       case 'signet': |       case 'signet': | ||||||
|         if (blockHeight < this.stateService.env.SIGNET_BLOCK_AUDIT_START_HEIGHT) { |         if (blockHeight < this.stateService.env.SIGNET_BLOCK_AUDIT_START_HEIGHT) { | ||||||
|           this.auditDataMissing = true; |           this.setAuditAvailable(true); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
|         if (blockHeight < this.stateService.env.MAINNET_BLOCK_AUDIT_START_HEIGHT) { |         if (blockHeight < this.stateService.env.MAINNET_BLOCK_AUDIT_START_HEIGHT) { | ||||||
|           this.auditDataMissing = true; |           this.setAuditAvailable(true); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -118,6 +118,7 @@ export class StateService { | |||||||
|   blockScrolling$: Subject<boolean> = new Subject<boolean>(); |   blockScrolling$: Subject<boolean> = new Subject<boolean>(); | ||||||
|   timeLtr: BehaviorSubject<boolean>; |   timeLtr: BehaviorSubject<boolean>; | ||||||
|   hideFlow: BehaviorSubject<boolean>; |   hideFlow: BehaviorSubject<boolean>; | ||||||
|  |   hideAudit: BehaviorSubject<boolean>; | ||||||
| 
 | 
 | ||||||
|   constructor( |   constructor( | ||||||
|     @Inject(PLATFORM_ID) private platformId: any, |     @Inject(PLATFORM_ID) private platformId: any, | ||||||
| @ -177,6 +178,12 @@ export class StateService { | |||||||
|         this.storageService.removeItem('flow-preference'); |         this.storageService.removeItem('flow-preference'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     const savedAuditPreference = this.storageService.getValue('audit-preference'); | ||||||
|  |     this.hideAudit = new BehaviorSubject<boolean>(savedAuditPreference === 'hide'); | ||||||
|  |     this.hideAudit.subscribe((hide) => { | ||||||
|  |       this.storageService.setValue('audit-preference', hide ? 'hide' : 'show'); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setNetworkBasedonUrl(url: string) { |   setNetworkBasedonUrl(url: string) { | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| <div class="d-flex align-items-center"> | <div class="d-flex align-items-center"> | ||||||
|   <span style="margin-bottom: 0.5rem">{{ textLeft }}</span>  |   <span>{{ textLeft }}</span>  | ||||||
|   <label class="switch"> |   <label class="switch" style="margin-bottom: 0;"> | ||||||
|     <input type="checkbox" [checked]="checked" (change)="onToggleStatusChanged($event)"> |     <input type="checkbox" [checked]="checked" (change)="onToggleStatusChanged($event)"> | ||||||
|     <span class="slider round"></span> |     <span class="slider round" [class.animate]="animate"></span> | ||||||
|   </label> |   </label> | ||||||
|    <span style="margin-bottom: 0.5rem">{{ textRight }}</span> |    <span>{{ textRight }}</span> | ||||||
| </div> | </div> | ||||||
|  | |||||||
| @ -22,8 +22,6 @@ | |||||||
|   right: 0; |   right: 0; | ||||||
|   bottom: 0; |   bottom: 0; | ||||||
|   background-color: #ccc; |   background-color: #ccc; | ||||||
|   -webkit-transition: .4s; |  | ||||||
|   transition: .4s; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .slider:before { | .slider:before { | ||||||
| @ -34,6 +32,9 @@ | |||||||
|   left: 2px; |   left: 2px; | ||||||
|   bottom: 2px; |   bottom: 2px; | ||||||
|   background-color: white; |   background-color: white; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .slider.animate, .slider.animate:before { | ||||||
|   -webkit-transition: .4s; |   -webkit-transition: .4s; | ||||||
|   transition: .4s; |   transition: .4s; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { Component, Input, Output, ChangeDetectionStrategy, EventEmitter, AfterViewInit } from '@angular/core'; | import { Component, Input, Output, ChangeDetectionStrategy, EventEmitter, AfterViewInit, ChangeDetectorRef } from '@angular/core'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-toggle', |   selector: 'app-toggle', | ||||||
| @ -11,9 +11,15 @@ export class ToggleComponent implements AfterViewInit { | |||||||
|   @Input() textLeft: string; |   @Input() textLeft: string; | ||||||
|   @Input() textRight: string; |   @Input() textRight: string; | ||||||
|   @Input() checked: boolean = false; |   @Input() checked: boolean = false; | ||||||
|  |   animate: boolean = false; | ||||||
|  | 
 | ||||||
|  |   constructor( | ||||||
|  |     private cd: ChangeDetectorRef, | ||||||
|  |   ) { } | ||||||
| 
 | 
 | ||||||
|   ngAfterViewInit(): void { |   ngAfterViewInit(): void { | ||||||
|     this.toggleStatusChanged.emit(false); |     this.animate = true; | ||||||
|  |     setTimeout(() => { this.cd.markForCheck()}); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onToggleStatusChanged(e): void { |   onToggleStatusChanged(e): void { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user