Add x widget
This commit is contained in:
		
							parent
							
								
									cd8abe5c06
								
							
						
					
					
						commit
						f83404421a
					
				| @ -12,19 +12,26 @@ | ||||
|   "dashboard": { | ||||
|     "widgets": [ | ||||
|       { | ||||
|         "component": "fees" | ||||
|         "component": "fees", | ||||
|         "mobileOrder": 4 | ||||
|       }, | ||||
|       { | ||||
|         "component": "balance", | ||||
|         "mobileOrder": 1, | ||||
|         "props": { | ||||
|           "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo" | ||||
|         } | ||||
|       }, | ||||
|       { | ||||
|         "component": "goggles" | ||||
|         "component": "twitter", | ||||
|         "mobileOrder": 5, | ||||
|         "props": { | ||||
|           "handle": "bitcoinofficesv" | ||||
|         } | ||||
|       }, | ||||
|       { | ||||
|         "component": "address", | ||||
|         "mobileOrder": 2, | ||||
|         "props": { | ||||
|           "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo", | ||||
|           "period": "1m" | ||||
| @ -35,6 +42,7 @@ | ||||
|       }, | ||||
|       { | ||||
|         "component": "addressTransactions", | ||||
|         "mobileOrder": 3, | ||||
|         "props": { | ||||
|           "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo" | ||||
|         } | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
|     @for (widget of widgets; track widget.component) { | ||||
|       @switch (widget.component) { | ||||
|         @case ('fees') { | ||||
|           <div class="col card-wrapper"> | ||||
|           <div class="col card-wrapper" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div> | ||||
|             <div class="card"> | ||||
|               <div class="card-body less-padding"> | ||||
| @ -14,12 +14,12 @@ | ||||
|           </div> | ||||
|         } | ||||
|         @case ('difficulty') { | ||||
|           <div class="col"> | ||||
|           <div class="col" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <app-difficulty></app-difficulty> | ||||
|           </div> | ||||
|         } | ||||
|         @case ('goggles') { | ||||
|           <div class="col"> | ||||
|           <div class="col" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card graph-card"> | ||||
|               <div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2"> | ||||
|                 <a class="title-link mb-0" style="margin-top: -2px" href="" [routerLink]="['/mempool-block/0' | relativeUrl]"> | ||||
| @ -48,7 +48,7 @@ | ||||
|           </div> | ||||
|         } | ||||
|         @case ('incoming') { | ||||
|           <div class="col"> | ||||
|           <div class="col" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card graph-card"> | ||||
|               <div class="card-body"> | ||||
|                 <ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container> | ||||
| @ -93,7 +93,7 @@ | ||||
|           </ng-template> | ||||
|         } | ||||
|         @case ('replacements') { | ||||
|           <div class="col" style="max-height: 410px"> | ||||
|           <div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card"> | ||||
|               <div class="card-body"> | ||||
|                 <a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]"> | ||||
| @ -140,7 +140,7 @@ | ||||
|           </ng-template> | ||||
|         } | ||||
|         @case ('blocks') { | ||||
|           <div class="col" style="max-height: 410px"> | ||||
|           <div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card"> | ||||
|               <div class="card-body"> | ||||
|                 <a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]"> | ||||
| @ -184,7 +184,7 @@ | ||||
|           </ng-template> | ||||
|         } | ||||
|         @case ('transactions') { | ||||
|           <div class="col" style="max-height: 410px"> | ||||
|           <div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card"> | ||||
|               <div class="card-body"> | ||||
|                 <h5 class="card-title" i18n="dashboard.recent-transactions">Recent Transactions</h5> | ||||
| @ -224,13 +224,13 @@ | ||||
|           </ng-template> | ||||
|         } | ||||
|         @case ('balance') { | ||||
|           <div class="col card-wrapper"> | ||||
|           <div class="col card-wrapper" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="main-title" i18n="dashboard.treasury">Treasury</div> | ||||
|             <app-balance-widget [address]="widget.props.address" [addressSummary$]="addressSummary$" [addressInfo]="address"></app-balance-widget> | ||||
|           </div> | ||||
|         } | ||||
|         @case ('address') { | ||||
|           <div class="col" style="max-height: 410px"> | ||||
|           <div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card graph-card"> | ||||
|               <div class="card-body"> | ||||
|                 <a class="title-link" href="" [routerLink]="[('/address/' + widget.props.address) | relativeUrl]"> | ||||
| @ -244,7 +244,7 @@ | ||||
|           </div> | ||||
|         } | ||||
|         @case ('addressTransactions') { | ||||
|           <div class="col" style="max-height: 410px"> | ||||
|           <div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card"> | ||||
|               <div class="card-body"> | ||||
|                 <a class="title-link" href="" [routerLink]="[('/address/' + widget.props.address) | relativeUrl]"> | ||||
| @ -257,6 +257,22 @@ | ||||
|             </div> | ||||
|           </div> | ||||
|         } | ||||
|         @case ('twitter') { | ||||
|           <div class="col" style="min-height:410px" [style.order]="isMobile && widget.mobileOrder || 8"> | ||||
|             <div class="card graph-card"> | ||||
|               <div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2 d-flex flex-column"> | ||||
|                 <a class="title-link" [href]="'https://x.com/' + widget.props?.handle" target="_blank"> | ||||
|                   <h5 class="card-title d-inline" i18n="dashboard.x-timeline">X Timeline</h5> | ||||
|                   <span> </span> | ||||
|                   <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: var(--title-fg)"></fa-icon> | ||||
|                 </a> | ||||
|                 @defer { | ||||
|                   <app-twitter-widget [handle]="widget.props?.handle" style="flex-grow: 1"></app-twitter-widget> | ||||
|                 } | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   </div> | ||||
|  | ||||
| @ -57,6 +57,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni | ||||
|   incomingGraphHeight: number = 300; | ||||
|   graphHeight: number = 300; | ||||
|   webGlEnabled = true; | ||||
|   isMobile: boolean = window.innerWidth <= 767.98; | ||||
| 
 | ||||
|   widgets; | ||||
| 
 | ||||
| @ -368,5 +369,6 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni | ||||
|       this.goggleResolution = 86; | ||||
|       this.graphHeight = 310; | ||||
|     } | ||||
|     this.isMobile = window.innerWidth <= 767.98; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,16 @@ | ||||
| @if (loading) { | ||||
|   <div class="spinner-wrapper"> | ||||
|     <div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div> | ||||
|   </div> | ||||
| } @else if (error) { | ||||
|   <div class="error-wrapper"> | ||||
|     <span>failed to load X timeline</span> | ||||
|   </div> | ||||
| } | ||||
| <iframe id="twitter-widget-0" scrolling="no" frameborder="0" allowtransparency="true" allowfullscreen="true" | ||||
|   title="Twitter Timeline" | ||||
|   [src]="iframeSrc" | ||||
|   style="position: static; visibility: visible; width: 100%; height: 100%; display: block; flex-grow: 1;" | ||||
|   (load)="onReady()" | ||||
| ></iframe> | ||||
| 
 | ||||
| @ -0,0 +1,10 @@ | ||||
| .spinner-wrapper, .error-wrapper { | ||||
|   position: absolute; | ||||
|   left: 0; | ||||
|   right: 0; | ||||
|   top: 0; | ||||
|   bottom: 0; | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
|   align-items: center; | ||||
| } | ||||
| @ -0,0 +1,65 @@ | ||||
| import { Component, Input, ChangeDetectionStrategy, SecurityContext } from '@angular/core'; | ||||
| import { LanguageService } from '../../services/language.service'; | ||||
| import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-twitter-widget', | ||||
|   templateUrl: './twitter-widget.component.html', | ||||
|   styleUrls: ['./twitter-widget.component.scss'], | ||||
|   changeDetection: ChangeDetectionStrategy.OnPush, | ||||
| }) | ||||
| export class TwitterWidgetComponent { | ||||
|   @Input() handle: string; | ||||
|   @Input() width = 300; | ||||
|   @Input() height = 400; | ||||
| 
 | ||||
|   loading: boolean = true; | ||||
|   error: boolean = false; | ||||
|   lang: string = 'en'; | ||||
| 
 | ||||
|   iframeSrc: SafeResourceUrl; | ||||
| 
 | ||||
|   constructor( | ||||
|     private languageService: LanguageService, | ||||
|     public sanitizer: DomSanitizer, | ||||
|   ) { | ||||
|     this.lang = this.languageService.getLanguage(); | ||||
|     this.setIframeSrc(); | ||||
|   } | ||||
| 
 | ||||
|   setIframeSrc(): void { | ||||
|     this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.sanitizer.sanitize(SecurityContext.URL, | ||||
|       'https://syndication.twitter.com/srv/timeline-profile/screen-name/bitcoinofficesv?creatorScreenName=mempool' | ||||
|       + '&dnt=true' | ||||
|       + '&embedId=twitter-widget-0' | ||||
|       + '&features=eyJ0ZndfdGltZWxpbmVfbGlzdCI6eyJidWNrZXQiOltdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2ZvbGxvd2VyX2NvdW50X3N1bnNldCI6eyJidWNrZXQiOnRydWUsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9iYWNrZW5kIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19yZWZzcmNfc2Vzc2lvbiI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfZm9zbnJfc29mdF9pbnRlcnZlbnRpb25zX2VuYWJsZWQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X21peGVkX21lZGlhXzE1ODk3Ijp7ImJ1Y2tldCI6InRyZWF0bWVudCIsInZlcnNpb24iOm51bGx9LCJ0ZndfZXhwZXJpbWVudHNfY29va2llX2V4cGlyYXRpb24iOnsiYnVja2V0IjoxMjA5NjAwLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3Nob3dfYmlyZHdhdGNoX3Bpdm90c19lbmFibGVkIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdXNlX3Byb2ZpbGVfaW1hZ2Vfc2hhcGVfZW5hYmxlZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0ZndfbGVnYWN5X3RpbWVsaW5lX3N1bnNldCI6eyJidWNrZXQiOnRydWUsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D' | ||||
|       + '&frame=false' | ||||
|       + '&hideBorder=true' | ||||
|       + '&hideFooter=false' | ||||
|       + '&hideHeader=true' | ||||
|       + '&hideScrollBar=false' | ||||
|       + `&lang=${this.lang}` | ||||
|       + '&maxHeight=500px' | ||||
|       + '&origin=https%3A%2F%2Fmempool.space%2F' | ||||
|       // + '&sessionId=88f6d661d0dcca99c43c0a590f6a3e61c89226a9'
 | ||||
|       + '&showHeader=false' | ||||
|       + '&showReplies=false' | ||||
|       + '&siteScreenName=mempool' | ||||
|       + '&theme=dark' | ||||
|       + '&transparent=true' | ||||
|       + '&widgetsVersion=2615f7e52b7e0%3A1702314776716' | ||||
|     )); | ||||
|   } | ||||
| 
 | ||||
|   onReady(): void { | ||||
|     console.log('ready!'); | ||||
|     this.loading = false; | ||||
|     this.error = false; | ||||
|   } | ||||
| 
 | ||||
|   onFailed(): void { | ||||
|     console.log('failed!') | ||||
|     this.loading = false; | ||||
|     this.error = true; | ||||
|   } | ||||
| } | ||||
| @ -33,6 +33,7 @@ export interface Customization { | ||||
|   dashboard: { | ||||
|     widgets: { | ||||
|       component: string; | ||||
|       mobileOrder?: number; | ||||
|       props: { [key: string]: any }; | ||||
|     }[]; | ||||
|   }; | ||||
|  | ||||
| @ -112,6 +112,7 @@ import { ClockComponent } from '../components/clock/clock.component'; | ||||
| import { CalculatorComponent } from '../components/calculator/calculator.component'; | ||||
| import { BitcoinsatoshisPipe } from '../shared/pipes/bitcoinsatoshis.pipe'; | ||||
| import { HttpErrorComponent } from '../shared/components/http-error/http-error.component'; | ||||
| import { TwitterWidgetComponent } from '../components/twitter-widget/twitter-widget.component'; | ||||
| 
 | ||||
| import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-directives/weight-directives'; | ||||
| 
 | ||||
| @ -224,6 +225,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | ||||
|     AccelerateCheckout, | ||||
|     PendingStatsComponent, | ||||
|     HttpErrorComponent, | ||||
|     TwitterWidgetComponent, | ||||
|   ], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
| @ -351,6 +353,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | ||||
|     AccelerateCheckout, | ||||
|     PendingStatsComponent, | ||||
|     HttpErrorComponent, | ||||
|     TwitterWidgetComponent, | ||||
| 
 | ||||
|     MempoolBlockOverviewComponent, | ||||
|     ClockchainComponent, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user