From 35ff2c7225347670cc921ecc1d18958fa6a37f01 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 21 May 2024 00:56:24 +0000 Subject: [PATCH] Minor faucet UI refactor --- .../components/faucet/faucet.component.html | 17 ++-- .../components/faucet/faucet.component.scss | 2 +- .../app/components/faucet/faucet.component.ts | 97 ++++++++++++------- 3 files changed, 70 insertions(+), 46 deletions(-) diff --git a/frontend/src/app/components/faucet/faucet.component.html b/frontend/src/app/components/faucet/faucet.component.html index 2de642c2c..89e6bb8a8 100644 --- a/frontend/src/app/components/faucet/faucet.component.html +++ b/frontend/src/app/components/faucet/faucet.component.html @@ -13,16 +13,16 @@ {{ txid }} } - @else if (loading) { + @if (loading) {

Loading faucet...

} @else if (!user) {
- To limit abuse,  - authenticate  - or + To use the faucet, please  + login +  or
@@ -31,19 +31,18 @@
- To limit abuse + To use the faucet, please
} - @else if (error) { } @if (!loading) { -
+
@@ -68,7 +67,7 @@ Address
- +
Address is required
@@ -83,7 +82,7 @@ @if (status?.address) { -
If you no longer need your testnet4 coins, please consider sending them back to replenish the faucet.
+
If you no longer need your testnet4 coins, please consider sending them back to replenish the faucet.
}
diff --git a/frontend/src/app/components/faucet/faucet.component.scss b/frontend/src/app/components/faucet/faucet.component.scss index d611f5a23..c3d3a5b33 100644 --- a/frontend/src/app/components/faucet/faucet.component.scss +++ b/frontend/src/app/components/faucet/faucet.component.scss @@ -24,7 +24,7 @@ flex-grow: 1; } .submit-button:disabled { - pointer-events: none; + cursor: not-allowed; } #satoshis::after { diff --git a/frontend/src/app/components/faucet/faucet.component.ts b/frontend/src/app/components/faucet/faucet.component.ts index bfb485d0e..0d0d29600 100644 --- a/frontend/src/app/components/faucet/faucet.component.ts +++ b/frontend/src/app/components/faucet/faucet.component.ts @@ -41,10 +41,7 @@ export class FaucetComponent implements OnInit, OnDestroy { private websocketService: WebsocketService, private audioService: AudioService ) { - this.faucetForm = this.formBuilder.group({ - 'address': ['', [Validators.required, Validators.pattern(getRegex('address', 'testnet4'))]], - 'satoshis': [0, [Validators.required, Validators.min(0), Validators.max(0)]] - }); + this.initForm(1000, 500_000, null); } ngOnDestroy() { @@ -66,38 +63,7 @@ export class FaucetComponent implements OnInit, OnDestroy { } // Setup form - this.faucetStatusSubscription = this.servicesApiService.getFaucetStatus$().subscribe({ - next: (status) => { - if (!status) { - this.error = 'internal_server_error'; - return; - } - this.status = status; - - const notFaucetAddressValidator = (faucetAddress: string): ValidatorFn => { - return (control: AbstractControl): ValidationErrors | null => { - const forbidden = control.value === faucetAddress; - return forbidden ? { forbiddenAddress: { value: control.value } } : null; - }; - } - this.faucetForm = this.formBuilder.group({ - 'address': ['', [Validators.required, Validators.pattern(getRegex('address', 'testnet4')), notFaucetAddressValidator(this.status.address)]], - 'satoshis': [this.status.min, [Validators.required, Validators.min(this.status.min), Validators.max(this.status.max)]] - }); - - if (this.status.code !== 'ok') { - this.error = this.status.code; - } - - this.loading = false; - this.cd.markForCheck(); - }, - error: (response) => { - this.loading = false; - this.error = response.error; - this.cd.markForCheck(); - } - }); + this.updateFaucetStatus(); // Track transaction this.websocketService.want(['blocks', 'mempool-blocks']); @@ -117,7 +83,34 @@ export class FaucetComponent implements OnInit, OnDestroy { }); } + updateFaucetStatus(): void { + this.servicesApiService.getFaucetStatus$().subscribe({ + next: (status) => { + if (!status) { + this.error = 'internal_server_error'; + return; + } + this.status = status; + if (this.status.code !== 'ok') { + this.error = this.status.code; + this.updateForm(this.status.min ?? 1000, this.status.max ?? 500_000, this.status.address); + return; + } + // update the form with the proper validation parameters + this.updateForm(this.status.min, this.status.max, this.status.address); + }, + error: (response) => { + this.loading = false; + this.error = response.error; + this.cd.markForCheck(); + } + }); + } + requestCoins(): void { + if (this.isDisabled()) { + return; + } this.error = null; this.txid = ''; this.stateService.markBlock$.next({}); @@ -127,6 +120,7 @@ export class FaucetComponent implements OnInit, OnDestroy { this.txid = response.txid; this.websocketService.startTrackTransaction(this.txid); this.audioService.playSound('cha-ching'); + this.updateFaucetStatus(); this.cd.markForCheck(); }), error: (response: HttpErrorResponse) => { @@ -135,9 +129,40 @@ export class FaucetComponent implements OnInit, OnDestroy { }); } + isDisabled(): boolean { + return !(this.user && this.status?.code === 'ok' && !this.error); + } + + getNotFaucetAddressValidator(faucetAddress: string): ValidatorFn { + return faucetAddress ? (control: AbstractControl): ValidationErrors | null => { + const forbidden = control.value === faucetAddress; + return forbidden ? { forbiddenAddress: { value: control.value } } : null; + }: () => null; + } + + initForm(min: number, max: number, faucetAddress: string): void { + this.faucetForm = this.formBuilder.group({ + 'address': ['', [Validators.required, Validators.pattern(getRegex('address', 'testnet4')), this.getNotFaucetAddressValidator(faucetAddress)]], + 'satoshis': [min, [Validators.required, Validators.min(min), Validators.max(max)]] + }); + + this.loading = false; + this.cd.markForCheck(); + } + + updateForm(min, max, faucetAddress: string): void { + if (!this.faucetForm) { + this.initForm(min, max, faucetAddress); + } else { + this.faucetForm.get('address').setValidators([Validators.required, Validators.pattern(getRegex('address', 'testnet4')), this.getNotFaucetAddressValidator(faucetAddress)]); + this.faucetForm.get('satoshis').setValidators([Validators.required, Validators.min(min), Validators.max(max)]); + } + } + setAmount(value: number): void { if (this.faucetForm) { this.faucetForm.get('satoshis').setValue(value); + this.faucetForm.get('satoshis').markAsDirty(); } }