diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 78e292c6a..a10c119a3 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -17,6 +17,7 @@ import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks. import { ApiDocsComponent } from './components/api-docs/api-docs.component'; import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component'; import { BisqMasterPageComponent } from './components/bisq-master-page/bisq-master-page.component'; +import { SponsorComponent } from './components/sponsor/sponsor.component'; let routes: Routes = [ { @@ -70,6 +71,10 @@ let routes: Routes = [ children: [], component: AddressComponent }, + { + path: 'sponsor', + component: SponsorComponent, + }, ], }, { diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index b97f5ba28..1410af51d 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -50,6 +50,7 @@ import { ApiDocsComponent } from './components/api-docs/api-docs.component'; import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component'; import { StorageService } from './services/storage.service'; import { HttpCacheInterceptor } from './services/http-cache.interceptor'; +import { SponsorComponent } from './components/sponsor/sponsor.component'; @NgModule({ declarations: [ @@ -85,6 +86,7 @@ import { HttpCacheInterceptor } from './services/http-cache.interceptor'; DashboardComponent, ApiDocsComponent, TermsOfServiceComponent, + SponsorComponent, ], imports: [ BrowserModule.withServerTransition({ appId: 'serverApp' }), diff --git a/frontend/src/app/components/about/about.component.html b/frontend/src/app/components/about/about.component.html index a136965e6..70f748d0f 100644 --- a/frontend/src/app/components/about/about.component.html +++ b/frontend/src/app/components/about/about.component.html @@ -72,137 +72,22 @@

Community Sponsors ❤️

-
-
-
-
- - - -
- -
-
-
+ + + +
+ +
+
+
+


- -

- Navigate to https://mempool.space/about to sponsor -

- -
-
-
-
- -
- -
-
-
- @ -
- -
-
Amount required
-
Minimum amount is 0.001 BTC
-
- -
-
-
- - -
- If you donate 0.01 BTC or more, your profile photo will be added to the list of sponsors above :) -
-
- -
- -
-
- - - -
-
- - -
- - - -
-
-
- -
- -
-
-

{{ donationObj.amount }} BTC

-
- - -
- - - -
-
- -
- -
- -
-
- -
- -
- -
-
- -

-

{{ donationObj.amount }} BTC

-
- - -
- - - -
-
-
- -
- -
-
-

{{ donationObj.amount }} BTC

-
- -

Waiting for transaction...

-
-
- -
-

Donation confirmed!
Thank you!

-
+ + Navigate to https://mempool.space/sponsor to sponsor

-

+

Community Integrations

@@ -334,19 +219,16 @@

Project Contributors

-
-
-
-
- - - -
- - {{ contributor.name }} -
-
-
+ + + +
+ + {{ contributor.name }} +
+
+
+




@@ -407,3 +289,8 @@ + + +
+
+
diff --git a/frontend/src/app/components/about/about.component.scss b/frontend/src/app/components/about/about.component.scss index f149e2a2f..e9ffe0304 100644 --- a/frontend/src/app/components/about/about.component.scss +++ b/frontend/src/app/components/about/about.component.scss @@ -1,10 +1,3 @@ -.qr-wrapper { - background-color: #FFF; - padding: 10px; - display: inline-block; - padding-bottom: 5px; -} - .profile_photo { width: 80px; height: 80px; @@ -39,11 +32,6 @@ font-size: 12px; } -.info-group { - max-width: 400px; -} - - .required { color: #FF0000; font-weight: bold; diff --git a/frontend/src/app/components/about/about.component.ts b/frontend/src/app/components/about/about.component.ts index 158a00d47..ccec8ab5f 100644 --- a/frontend/src/app/components/about/about.component.ts +++ b/frontend/src/app/components/about/about.component.ts @@ -1,42 +1,33 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { WebsocketService } from '../../services/websocket.service'; import { SeoService } from 'src/app/services/seo.service'; import { StateService } from 'src/app/services/state.service'; -import { Observable, Subscription } from 'rxjs'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Observable } from 'rxjs'; import { ApiService } from 'src/app/services/api.service'; -import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; -import { delay, retryWhen, switchMap, tap } from 'rxjs/operators'; import { IBackendInfo } from 'src/app/interfaces/websocket.interface'; +import { Router } from '@angular/router'; @Component({ selector: 'app-about', templateUrl: './about.component.html', styleUrls: ['./about.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class AboutComponent implements OnInit, OnDestroy { +export class AboutComponent implements OnInit { backendInfo$: Observable; - donationForm: FormGroup; - paymentForm: FormGroup; - donationStatus = 1; sponsors$: Observable; contributors$: Observable; - donationObj: any; - sponsorsEnabled = this.stateService.env.OFFICIAL_MEMPOOL_SPACE; frontendGitCommitHash = this.stateService.env.GIT_COMMIT_HASH.substr(0, 8); packetJsonVersion = this.stateService.env.PACKAGE_JSON_VERSION; officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE; - sponsors = null; - contributors = null; - requestSubscription: Subscription | undefined; + showNavigateToSponsor = false; constructor( private websocketService: WebsocketService, private seoService: SeoService, private stateService: StateService, - private formBuilder: FormBuilder, private apiService: ApiService, - private sanitizer: DomSanitizer, + private router: Router, ) { } ngOnInit() { @@ -44,59 +35,15 @@ export class AboutComponent implements OnInit, OnDestroy { this.seoService.setTitle($localize`:@@004b222ff9ef9dd4771b777950ca1d0e4cd4348a:About`); this.websocketService.want(['blocks']); - this.donationForm = this.formBuilder.group({ - amount: [0.01, [Validators.min(0.001), Validators.required]], - handle: [''], - }); - - this.paymentForm = this.formBuilder.group({ - 'method': 'chain' - }); - - this.apiService.getDonation$() - .subscribe((sponsors) => { - this.sponsors = sponsors; - }); - - this.apiService.getContributor$() - .subscribe((contributors) => { - this.contributors = contributors; - }); + this.sponsors$ = this.apiService.getDonation$(); + this.contributors$ = this.apiService.getContributor$(); } - ngOnDestroy() { - if (this.requestSubscription) { - this.requestSubscription.unsubscribe(); + sponsor() { + if (this.officialMempoolSpace) { + this.router.navigateByUrl('/sponsor'); + } else { + this.showNavigateToSponsor = true; } } - - submitDonation() { - if (this.donationForm.invalid) { - return; - } - this.requestSubscription = this.apiService.requestDonation$( - this.donationForm.get('amount').value, - this.donationForm.get('handle').value - ) - .pipe( - tap((response) => { - this.donationObj = response; - this.donationStatus = 3; - }), - switchMap(() => this.apiService.checkDonation$(this.donationObj.id) - .pipe( - retryWhen((errors) => errors.pipe(delay(2000))) - ) - ) - ).subscribe(() => { - this.donationStatus = 4; - if (this.donationForm.get('handle').value) { - this.sponsors.unshift({ handle: this.donationForm.get('handle').value }); - } - }); - } - - bypassSecurityTrustUrl(text: string): SafeUrl { - return this.sanitizer.bypassSecurityTrustUrl(text); - } } diff --git a/frontend/src/app/components/sponsor/sponsor.component.html b/frontend/src/app/components/sponsor/sponsor.component.html new file mode 100644 index 000000000..0b21f6313 --- /dev/null +++ b/frontend/src/app/components/sponsor/sponsor.component.html @@ -0,0 +1,151 @@ +
+
+ +

Sponsor

+ +
+ +

+ Navigate to https://mempool.space/sponsor to sponsor +

+ + + +
+ +
+ +
+
+
Pleb sponsor
+
+
100K sats
+

Thank you for supporting the mempool project

+
+
+ +
+
Community sponsor
+
+
1M sats
+

Your profile photo featured on our about page

+
+
+ +
+
Enterprise sponsor
+
+
1 BTC
+

Backlink to your organization's website

+
+
+
+ +
+
+ +
+
+
+ @ +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+ + + +
+
+ + +
+ + + +
+
+
+ +
+ +
+
+

{{ donationObj.amount }} BTC

+
+ + +
+ + + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +

+

{{ donationObj.amount }} BTC

+
+ + +
+ + + +
+
+
+ +
+ +
+
+

{{ donationObj.amount }} BTC

+
+ +

Waiting for transaction...

+
+
+ +
+

Donation confirmed!
Thank you!

+
+ + Order ID: +
+ {{ donationObj.id }} +
+ +
+
diff --git a/frontend/src/app/components/sponsor/sponsor.component.scss b/frontend/src/app/components/sponsor/sponsor.component.scss new file mode 100644 index 000000000..5f29e003e --- /dev/null +++ b/frontend/src/app/components/sponsor/sponsor.component.scss @@ -0,0 +1,40 @@ +.qr-wrapper { + background-color: #FFF; + padding: 10px; + display: inline-block; + padding-bottom: 5px; +} + +.info-group { + max-width: 400px; +} + +.card { + width: 220px; + height: 200px; + background-color: #1d1f31; + margin: 10px 20px 20px 20px; + border: 2px solid #1d1f31; + cursor: pointer; + + &.bigger { + height: 220px; + width: 240px; + margin-top: 0px; + } +} + +.card-header { + background-color: #171929; +} + +.flex-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; +} + +.shiny-border { + border: 2px solid #505892; +} diff --git a/frontend/src/app/components/sponsor/sponsor.component.ts b/frontend/src/app/components/sponsor/sponsor.component.ts new file mode 100644 index 000000000..619cb1159 --- /dev/null +++ b/frontend/src/app/components/sponsor/sponsor.component.ts @@ -0,0 +1,88 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; +import { Subscription } from 'rxjs'; +import { delay, retryWhen, switchMap, tap } from 'rxjs/operators'; +import { ApiService } from 'src/app/services/api.service'; +import { SeoService } from 'src/app/services/seo.service'; +import { StateService } from 'src/app/services/state.service'; +import { WebsocketService } from 'src/app/services/websocket.service'; + +@Component({ + selector: 'app-sponsor', + templateUrl: './sponsor.component.html', + styleUrls: ['./sponsor.component.scss'] +}) +export class SponsorComponent implements OnInit, OnDestroy { + sponsorsEnabled = this.stateService.env.OFFICIAL_MEMPOOL_SPACE; + donationForm: FormGroup; + paymentForm: FormGroup; + requestSubscription: Subscription | undefined; + donationObj: any; + donationStatus = 1; + + constructor( + private formBuilder: FormBuilder, + private apiService: ApiService, + private sanitizer: DomSanitizer, + private stateService: StateService, + private websocketService: WebsocketService, + private seoService: SeoService, + ) { } + + ngOnInit(): void { + this.seoService.setTitle($localize`:@@sponsor.title:Sponsor`); + this.websocketService.want(['blocks']); + + this.paymentForm = this.formBuilder.group({ + 'method': 'chain' + }); + + this.donationForm = this.formBuilder.group({ + selection: [0.01], + handle: [''], + }); + } + + submitDonation() { + if (this.donationForm.invalid) { + return; + } + this.requestSubscription = this.apiService.requestDonation$( + this.donationForm.get('selection').value, + this.donationForm.get('handle').value + ) + .pipe( + tap((response) => { + this.donationObj = response; + this.donationStatus = 2; + }), + switchMap(() => this.apiService.checkDonation$(this.donationObj.id) + .pipe( + retryWhen((errors) => errors.pipe(delay(2000))) + ) + ) + ).subscribe(() => { + this.donationStatus = 3; + /* + if (this.donationForm.get('handle').value) { + this.sponsors.unshift({ handle: this.donationForm.get('handle').value }); + } + */ + }); + } + + setSelection(amount: number): void { + this.donationForm.get('selection').setValue(amount); + } + + bypassSecurityTrustUrl(text: string): SafeUrl { + return this.sanitizer.bypassSecurityTrustUrl(text); + } + + ngOnDestroy() { + if (this.requestSubscription) { + this.requestSubscription.unsubscribe(); + } + } +}