...
 
Commits (3)
......@@ -154,9 +154,9 @@ m-shadowboxHeader {
}
}
}
.m-shadowboxHeader__wrapper {
@include m-theme() {
box-shadow: none;
}
}
// .m-shadowboxHeader__wrapper {
// @include m-theme() {
// box-shadow: none;
// }
// }
}
......@@ -9,10 +9,18 @@
red: color === 'red'
}"
>
<div *ngIf="!saving" class="m-shadowboxSubmitButton__status--unsaved">
<div
*ngIf="!saving"
class="m-shadowboxSubmitButton__status--unsaved"
#buttonTextContainer
>
<ng-content></ng-content>
</div>
<div *ngIf="saving" class="m-shadowboxSubmitButton__status--saving">
<div
*ngIf="saving"
class="m-shadowboxSubmitButton__status--saving"
[style.width]="buttonTextWidth + 'px'"
>
<span></span>
<span></span>
<span></span>
......
......@@ -103,9 +103,7 @@
&[disabled] {
cursor: default;
&:not(.saving) {
@include m-theme() {
background-color: themed($m-grey-100);
}
opacity: 0.6;
}
}
}
......@@ -150,6 +148,10 @@ button {
}
}
}
.m-shadowboxSubmitButton__status--unsaved {
font-size: 15px;
line-height: 20px;
}
@media screen and (max-width: $max-mobile) {
m-shadowboxSubmitButton {
......
import { Component, Input } from '@angular/core';
import {
Component,
Input,
HostListener,
ViewChild,
ElementRef,
AfterViewInit,
} from '@angular/core';
@Component({
selector: 'm-shadowboxSubmitButton',
templateUrl: './shadowbox-submit-button.component.html',
})
export class ShadowboxSubmitButtonComponent {
export class ShadowboxSubmitButtonComponent implements AfterViewInit {
buttonTextWidth: number = 0;
@ViewChild('buttonTextContainer', { static: false })
buttonTextContainer: ElementRef;
@Input() saving: boolean = false;
@Input() disabled: boolean = false;
@Input() color: 'green' | 'grey' | 'red' = 'green';
constructor() {}
ngAfterViewInit() {
if (this.buttonTextContainer.nativeElement) {
this.setSavingWidth();
}
}
// Prevent button width from shrinking during saving animation
@HostListener('window:resize')
setSavingWidth() {
this.buttonTextWidth = this.buttonTextContainer.nativeElement.clientWidth;
}
}
<div *ngIf="!loaded" class="m-wallet__spinner">
<div *ngIf="!init" class="m-wallet__spinner">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
<div class="m-walletBalance--cash" *ngIf="loaded">
<div class="m-walletBalance--cash" *ngIf="init && cashWallet">
<div
class="m-walletBalance---cash__onboardingNotice"
*ngIf="viewId !== 'settings' && (!hasAccount || !account.bankAccount)"
*ngIf="viewId !== 'settings' && (!hasAccount || !hasBank)"
>
<p (click)="scrollToSettings()">
<a>Add your bank information</a>
......@@ -19,8 +19,9 @@
</p>
</div>
<div class="m-walletBalance--cash__colContainer">
<!-- ---PENDING BALANCE ------------------- -->
<!-- -------------------------------------------- -->
<!--- PENDING BALANCE ------------------------------>
<!-- -------------------------------------------- -->
<div class="m-walletBalance--cash__col">
<div class="m-walletBalance--cash__colTitle">
Pending Balance<m-tooltip icon="help"
......@@ -47,16 +48,21 @@
>.{{ pendingBalance.frac }}</span
>
</div>
<div class="m-walletBalance--cash__colSubtitle">
<!-- -------------------------------------------- -->
<!--- PAYOUT DATE----------------------------------->
<!-- -------------------------------------------- -->
<div *ngIf="hasBank" class="m-walletBalance--cash__colSubtitle">
<p>Estimated Payout</p>
<p>{{ nextPayoutDate }}</p>
</div>
</ng-container>
</div>
<!-- ---TOTAL PAID OUT ------------------- -->
<!-- -------------------------------------------- -->
<!--- TOTAL PAID OUT-------------------------------->
<!-- -------------------------------------------- -->
<div class="m-walletBalance--cash__col" *ngIf="hasAccount">
<div class="m-walletBalance--cash__col" *ngIf="hasBank">
<div class="m-walletBalance--cash__colTitle">
Total Paid Out<m-tooltip icon="help"
>The amount you've already received</m-tooltip
......@@ -75,9 +81,11 @@
</div>
</div>
<!-- ---PRO EARNINGS ------------------- -->
<!-- -------------------------------------------- -->
<!--- PRO EARNINGS --------------------------------->
<!-- -------------------------------------------- -->
<div class="m-walletBalance--cash__col" *ngIf="isPro">
<div class="m-walletBalance--cash__col" *ngIf="proEarnings">
<div class="m-walletBalance--cash__colTitle">
Pro Earnings<m-tooltip icon="help"
>At the end of each month, your Pro earnings will move into your
......
......@@ -10,7 +10,11 @@ import {
} from '@angular/core';
import { Client } from '../../../../services/api/client';
import { Session } from '../../../../services/session';
import { WalletDashboardService, WalletCurrency } from '../dashboard.service';
import {
WalletDashboardService,
WalletCurrency,
SplitBalance,
} from '../dashboard.service';
import { ActivatedRoute, ParamMap } from '@angular/router';
import * as moment from 'moment';
import { Subscription } from 'rxjs';
......@@ -20,133 +24,147 @@ import { ConfigsService } from '../../../../common/services/configs.service';
templateUrl: './balance-cash.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class WalletBalanceCashComponent implements OnInit, OnDestroy {
export class WalletBalanceCashComponent implements OnInit {
@Output() scrollToCashSettings: EventEmitter<any> = new EventEmitter();
@Input() viewId: string;
@Input() cashWallet: WalletCurrency; // TODOOJM USE ME & make me a setter
account;
hasAccount: boolean = true;
isPro: boolean = false;
pendingBalance;
totalPaidOut;
@Input() cashWallet: WalletCurrency;
// TODOOJM
// private _cashWallet: WalletCurrency;
// @Input() set cashWallet(value: WalletCurrency) {
// this._cashWallet = value;
// }
// get wallet(): WalletCurrency {
// return this._cashWallet;
// }
// account;
hasAccount: boolean = false;
hasBank: boolean = false;
pendingBalance: SplitBalance;
totalPaidOut: SplitBalance;
proEarnings: SplitBalance;
nextPayoutDate = '';
proEarnings;
onSettingsTab: boolean = false;
// onSettingsTab: boolean = false;
currency = 'usd';
paramsSubscription: Subscription;
loaded: boolean = false;
// paramsSubscription: Subscription;
init: boolean = false;
constructor(
protected client: Client,
protected cd: ChangeDetectorRef,
protected session: Session,
protected walletService: WalletDashboardService,
protected route: ActivatedRoute,
// protected route: ActivatedRoute,
private configs: ConfigsService
) {}
ngOnInit() {
this.paramsSubscription = this.route.paramMap.subscribe(
(params: ParamMap) => {
this.onSettingsTab = params.get('view') === 'settings';
this.detectChanges();
}
);
this.isPro = this.configs.get('pro');
this.load();
if (this.isPro) {
this.getProEarnings();
}
this.loaded = true;
this.detectChanges();
}
// this.paramsSubscription = this.route.paramMap.subscribe(
// (params: ParamMap) => {
// this.onSettingsTab = params.get('view') === 'settings';
// this.detectChanges();
// }
// );
ngOnDestroy() {
if (this.paramsSubscription) {
this.paramsSubscription.unsubscribe();
}
}
// this.load();
async load() {
// TODOOJM confirm that Mark has migrated all stripe accts to monthly intervals
// TODOOJM OR just get the payout date from the stripe account itself
this.nextPayoutDate = moment()
.endOf('month')
.format('ddd Do MMM');
// this.account = await this.walletService.getStripeAccount();
// if (!this.account || !this.account.accountNumber) {
if (this.cashWallet.address !== 'stripe') {
this.hasAccount = false;
this.pendingBalance = this.formatBalance(0);
this.totalPaidOut = this.formatBalance(0);
} else {
this.hasAccount = true;
this.pendingBalance = this.formatBalance(this.cashWallet.balance);
this.currency = this.cashWallet.label.toUpperCase();
this.account = await this.walletService.getStripeAccount();
// this.pendingBalance = this.formatBalance(
// this.account.pendingBalance.amount / 100
// );
// if (this.account.bankAccount) {
// this.currency = this.account.bankAccount.currency.toUpperCase();
// }
let totalPaidOutRaw =
(this.account.totalBalance.amount -
this.account.pendingBalance.amount) /
100;
console.log('888totalpaidoutraw', totalPaidOutRaw);
if (totalPaidOutRaw < 0) {
totalPaidOutRaw = 0;
}
this.totalPaidOut = this.formatBalance(totalPaidOutRaw);
}
this.hasAccount = this.cashWallet.stripeDetails.hasAccount;
this.hasBank = this.cashWallet.stripeDetails.hasBank;
this.pendingBalance = this.cashWallet.stripeDetails.pendingBalanceSplit;
this.totalPaidOut = this.cashWallet.stripeDetails.totalPaidOutSplit;
this.currency = this.hasBank ? this.cashWallet.label : 'USD';
if (this.configs.get('pro')) {
this.getProEarnings();
}
this.init = true;
this.detectChanges();
}
// ngOnDestroy() {
// if (this.paramsSubscription) {
// this.paramsSubscription.unsubscribe();
// }
// }
// async load() {
// // TODOOJM confirm that Mark has migrated all stripe accts to monthly intervals
// // TODOOJM OR just get the payout date from the stripe account itself
// this.nextPayoutDate = moment()
// .endOf('month')
// .format('ddd Do MMM');
// this.account = await this.walletService.getStripeAccount();
// if (!this.account || !this.account.accountNumber) {
// if (this.cashWallet.address !== 'stripe') {
// // this.hasAccount = false;
// this.pendingBalance = this.walletService.splitBalance(0);
// this.totalPaidOut = this.walletService.splitBalance(0);
// } else {
// this.hasAccount = true;
// this.pendingBalance = this.walletService.splitBalance(
// this.cashWallet.balance
// );
// this.currency = this.cashWallet.label.toUpperCase();
// this.account = await this.walletService.getStripeAccount();
// this.pendingBalance = this.walletService.splitBalance(
// this.account.pendingBalance.amount / 100
// );
// if (this.account.bankAccount) {
// this.currency = this.account.bankAccount.currency.toUpperCase();
// }
// let totalPaidOutRaw =
// (this.account.totalBalance.amount -
// this.account.pendingBalance.amount) /
// 100;
// this.totalPaidOut = this.walletService.splitBalance(totalPaidOutRaw);
// }
// this.detectChanges();
// }
async getProEarnings() {
try {
const response: number = await this.walletService.getProEarnings();
this.proEarnings = this.formatBalance(response);
this.proEarnings = this.walletService.splitBalance(response);
} catch (e) {
console.error(e.message);
this.proEarnings = this.formatBalance(0);
this.proEarnings = this.walletService.splitBalance(0);
}
this.detectChanges();
}
formatBalance(balance) {
console.log(balance);
const formattedBalance = {
total: balance,
int: 0,
frac: null,
};
if (balance <= 0) {
return formattedBalance;
}
const splitBalance = balance.toString().split('.');
console.log('888 splitBal...', splitBalance);
formattedBalance.int = splitBalance[0];
console.log('888 int...', formattedBalance);
if (splitBalance[1]) {
const frac = splitBalance[1].toString();
formattedBalance.frac = frac.length < 2 ? frac.concat('0') : frac;
console.log('888 frac...', formattedBalance);
}
return formattedBalance;
}
// formatBalance(balance) {
// console.log(balance);
// const formattedBalance = {
// total: balance,
// int: 0,
// frac: null,
// };
// if (balance <= 0) {
// return formattedBalance;
// }
// const splitBalance = balance.toString().split('.');
// console.log('888 splitBal...', splitBalance);
// formattedBalance.int = splitBalance[0];
// console.log('888 int...', formattedBalance);
// if (splitBalance[1]) {
// const frac = splitBalance[1].toString();
// formattedBalance.frac = frac.length < 2 ? frac.concat('0') : frac;
// console.log('888 frac...', formattedBalance);
// }
// return formattedBalance;
// }
scrollToSettings() {
this.scrollToCashSettings.emit();
......
......@@ -60,7 +60,9 @@
>
tokens
</div>
<a
<!-- TODOOJM TOGGLE -->
<a (click)="showModal = true">Transfer to On-Chain</a>
<!-- <a
*ngIf="
session.getLoggedInUser().rewards &&
wallet.offchain.balance > 0 &&
......@@ -68,7 +70,7 @@
"
(click)="showModal = true"
>Transfer to On-Chain</a
>
> -->
</div>
</div>
<div class="m-walletBalance--tokens__learnMore">
......
......@@ -49,9 +49,15 @@ export class WalletBalanceTokensV2Component implements OnInit, OnDestroy {
) {}
ngOnInit() {
this.tokenBalance = this.formatBalance(this.wallet.tokens.balance);
this.offchainBalance = this.formatBalance(this.wallet.offchain.balance);
this.onchainBalance = this.formatBalance(this.wallet.onchain.balance);
this.tokenBalance = this.walletService.splitBalance(
this.wallet.tokens.balance
);
this.offchainBalance = this.walletService.splitBalance(
this.wallet.offchain.balance
);
this.onchainBalance = this.walletService.splitBalance(
this.wallet.onchain.balance
);
this.getPayout();
this.inProgress = false;
......@@ -93,22 +99,22 @@ export class WalletBalanceTokensV2Component implements OnInit, OnDestroy {
}
}
formatBalance(balance) {
const formattedBalance = {
total: balance,
int: 0,
frac: null,
};
if (balance <= 0) {
return formattedBalance;
}
const splitBalance = balance.toString().split('.');
// formatBalance(balance) {
// const formattedBalance = {
// total: balance,
// int: 0,
// frac: null,
// };
// if (balance <= 0) {
// return formattedBalance;
// }
// const splitBalance = balance.toString().split('.');
formattedBalance.int = splitBalance[0];
formattedBalance.frac = splitBalance[1];
// formattedBalance.int = splitBalance[0];
// formattedBalance.frac = splitBalance[1];
return formattedBalance;
}
// return formattedBalance;
// }
transferComplete() {
this.formToastService.success('On-chain transfer complete');
......
......@@ -22,7 +22,7 @@
></m-shadowboxHeader__tabs>
<div class="m-shadowboxLayout__body">
<div
class="m-walletDashboardBalances__wrapper"
class="m-walletDashboardBalance__wrapper"
*ngIf="
activeCurrencyId === 'tokens' || activeCurrencyId === 'cash'
"
......@@ -66,7 +66,7 @@
</div>
<div class="m-walletDashboardViews__viewsContainer">
<m-walletChart
class="m-walletDashboardViews__view m-walletDashboardViews__view--overview"
class="m-walletDashboardViews__view"
*ngIf="
activeCurrencyId === 'tokens' && activeViewId === 'overview'
"
......@@ -85,6 +85,7 @@
<div class="m-walletDashboardSettings__wrapper">
<m-walletSettings--tokens
class="m-walletDashboardViews__view"
[wallet]="wallet"
*ngIf="activeCurrencyId === 'tokens'"
(onchainAddressChanged)="onchainAddressChanged()"
></m-walletSettings--tokens>
......
......@@ -31,7 +31,7 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
menu: Menu = sidebarMenu;
paramsSubscription: Subscription;
wallet: Wallet;
inProgress: boolean = true;
inProgress: boolean;
activeCurrencyId: string;
activeViewId: string;
......@@ -69,6 +69,8 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
this.router.navigate(['/login']);
return;
}
this.inProgress = true;
this.detectChanges();
this.phoneVerified = this.session.getLoggedInUser().rewards;
this.hasOnchainAddress = this.session.getLoggedInUser().eth_wallet;
......@@ -134,7 +136,6 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
};
// Handle currency formatting for cash
// TODOOJM this isn't going to work
if (currency === 'cash') {
if (this.wallet.cash.unit === 'cash') {
headerTab.unit = 'usd';
......
......@@ -12,9 +12,11 @@ export interface SplitBalance {
}
export interface StripeDetails {
pendingBalance: SplitBalance;
totalPaidOut: SplitBalance;
isLocalCurrency: boolean;
pendingBalanceSplit: SplitBalance;
totalPaidOutSplit: SplitBalance;
hasAccount: boolean;
hasBank: boolean;
verified: boolean;
}
export interface WalletCurrency {
......@@ -37,6 +39,8 @@ export interface Wallet {
@Injectable()
export class WalletDashboardService {
totalTokens = 0;
stripeDetails: StripeDetails;
stripeAccount;
wallet: Wallet = {
tokens: {
label: 'Tokens',
......@@ -185,36 +189,49 @@ export class WalletDashboardService {
async getStripeAccount() {
const merchant = this.session.getLoggedInUser().merchant;
const zeroSplit = this.splitBalance(0);
this.stripeDetails = {
hasAccount: false,
hasBank: false,
pendingBalanceSplit: zeroSplit,
totalPaidOutSplit: zeroSplit,
verified: false,
};
if (merchant && merchant.service === 'stripe') {
try {
const { account } = <any>(
let { account } = <any>(
await this.client.get('api/v2/payments/stripe/connect')
);
const friendlyAccount = { ...account };
this.stripeDetails.hasAccount = true;
this.stripeDetails.verified = account.verified;
console.log('svc getAcc', account);
this.wallet.cash.address = 'stripe';
this.wallet.cash.balance =
(account.totalBalance.amount - account.pendingBalance.amount) / 100;
if (!account.bankAccount) {
// Has stripe account but not setup bank account
this.wallet.cash.label = 'USD';
this.wallet.cash.unit = 'usd';
friendlyAccount.isLocalCurrency = false;
} else {
if (account.bankAccount) {
// this.wallet.cash.label = 'USD';
// this.wallet.cash.unit = 'usd';
// this.stripeDetails.hasBank = false;
// } else {
const bankCurrency: string = account.bankAccount.currency;
this.wallet.cash.label = bankCurrency.toUpperCase();
this.wallet.cash.unit = bankCurrency;
friendlyAccount.isLocalCurrency = true;
this.stripeDetails.hasBank = true;
}
// TODOOJM
//pendingBalanceFriendly
// totalPaidOutFriendly = (account.totalBalance.amount - account.pendingBalance.amount) / 100;
// formatBalance(int, frac, total)
this.stripeDetails.pendingBalanceSplit = this.splitBalance(
account.pendingBalance.amount / 100
);
this.stripeDetails.totalPaidOutSplit = this.splitBalance(
(account.totalBalance.amount - account.pendingBalance.amount) / 100
);
//return friendlyAccount
this.wallet.cash.stripeDetails = this.stripeDetails;
account = { ...account, ...this.stripeDetails };
console.log('svc has account(merge)', account);
return account;
} catch (e) {
......@@ -222,7 +239,10 @@ export class WalletDashboardService {
return;
}
} else {
return;
this.wallet.cash.stripeDetails = this.stripeDetails;
console.log('svc has NO account', this.stripeDetails);
return this.stripeDetails;
}
}
......
......@@ -51,26 +51,25 @@ m-walletModal {
display: inline-block;
font-weight: 300;
}
}
.m-walletModal__title {
font-weight: 500;
font-size: 24px;
line-height: 32px;
margin-bottom: 18px;
@include m-theme() {
color: themed($m-grey-800);
@media screen and (max-width: $min-tablet) {
padding: 46px 50px;
max-width: 80vw;
width: 80vw;
max-height: 90vh;
}
@media screen and (max-width: $max-mobile) {
// padding: 26px 32px;
min-width: 90vw;
min-height: 90vh;
max-height: 95vh;
}
}
.m-walletModal__desc {
.m-walletTertiaryText--desc {
margin-bottom: 30px;
p {
font-size: 16px;
line-height: 21px;
}
}
[class*='m-walletModal__footnote--'] {
[class*='m-walletModal__footnote'] {
margin: 10px 0 11px 0;
font-size: 15px;
line-height: 20px;
......@@ -115,20 +114,18 @@ m-walletModal {
opacity: 0.6;
}
}
}
@media screen and (max-width: $min-tablet) {
.m-walletModal {
padding: 46px 50px;
max-width: 80vw;
width: 80vw;
max-height: 90vh;
}
}
@media screen and (max-width: $max-mobile) {
.m-walletModal {
padding: 26px 35px;
width: 90vw;
max-height: 95vh;
@media screen and (max-width: $max-mobile) {
top: 14px;
right: 20px;
@include m-theme() {
background-color: rgba(0, 0, 0, 0);
box-shadow: none;
}
&:hover {
@include m-theme() {
box-shadow: none;
}
}
}
}
}
<div class="m-walletModal__title">
<h2>
On-Chain Transfer
</div>
<div class="m-walletModal__desc">
<p>
</h2>
<div class="m-walletTertiaryText--desc">
<p class="m-walletTertiaryText--16">
You can request to transfer up to
<span class="m-walletOnchainTransfer__offchainBalance"
<span class="m-walletTertiaryText--16 m-walletTertiaryText--emphasis"
>{balance, plural, =1 {{{balance | number}} token} other
{{{balance | number}} tokens}}</span
>
from your rewards to your on-chain wallet below. You may only transfer once
per day.
</p>
<p class="m-walletOnchainTransfer__gasNotice">
<p class="m-walletTertiaryText--15">
Note: a small amount of ETH will be charged to cover the transaction fee.
Transfers go through an approval process and may take up to 72 hours to
complete.
</p>
</div>
<form *ngIf="form" [formGroup]="form">
<div class="m-walletForm__wrapper">
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label">
<label for="amount" i18n>Amount</label>
<m-tooltip icon="help">
<ng-container i18n>Placeholder</ng-container>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid: !isFormValid() || submitError
}"
>
<input
type="number"
id="amount"
name="amount"
formControlName="amount"
class="form-control"
required
/>
</div>
<div class="m-walletForm__row--validation">
<ng-container *ngIf="!submitError && canTransfer">
<p *ngIf="amount.errors?.required">
Transfer amount required
</p>
<p *ngIf="amount.errors?.moreThanZero && !amount.errors?.required">
Transfer amount must be greater than zero
</p>
<p *ngIf="amount.errors?.max">
You don't have enough tokens to make this transfer
</p>
</ng-container>
<p *ngIf="!canTransfer">
You may only transfer once per day
<div *ngIf="!form" class="m-wallet__spinner m-wallet__spinner--tokenSettings">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
<form
*ngIf="form"
[formGroup]="form"
class="m-walletButtonLayout--buttonInline"
>
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label">
<label for="amount" i18n>Amount</label>
<!-- <m-tooltip icon="help">
<ng-container i18n>Placeholder</ng-container>
</m-tooltip> -->
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid: !isFormValid() || submitError
}"
>
<input
type="number"
id="amount"
name="amount"
formControlName="amount"
class="form-control"
required
/>
</div>
<div class="m-walletForm__row--validation">
<ng-container *ngIf="!submitError && canTransfer">
<p *ngIf="amount.errors?.required">
Transfer amount required
</p>
<p *ngIf="submitError">{{ submitError }}</p>
</div>
<p *ngIf="amount.errors?.moreThanZero && !amount.errors?.required">
Transfer amount must be greater than zero
</p>
<p *ngIf="amount.errors?.max">
You don't have enough tokens to make this transfer
</p>
</ng-container>
<p *ngIf="!canTransfer">
You may only transfer once per day
</p>
<p *ngIf="submitError">{{ submitError }}</p>
</div>
</div>
<m-shadowboxSubmitButton
[disabled]="!isFormValid() || loading"
[saving]="transferring"
(click)="submitError ? load() : onSubmit()"
>
{{ submitError ? 'Reset' : 'Transfer' }}
</m-shadowboxSubmitButton>
</div>
<m-shadowboxSubmitButton
[disabled]="!isFormValid() || loading"
[saving]="transferring"
(click)="submitError ? load() : onSubmit()"
>
{{ submitError ? 'Reset' : 'Transfer' }}
</m-shadowboxSubmitButton>
</form>
m-walletOnchainTransfer {
.m-walletOnchainTransfer__offchainBalance {
@include m-theme() {
color: themed($m-grey-800);
}
}
p.m-walletOnchainTransfer__gasNotice {
font-size: 15px;
line-height: 20px;
}
.m-wallet__spinner {
min-height: 150px;
}
<div class="m-walletModal__title">
<h2>
Phone Verification
</div>
</h2>
<div class="m-walletModal__desc">
<p>
<p class="m-walletTertiaryText">
You can earn tokens for your contributions to the Minds network. The more
interactions on your content, the greater your share of the daily token
reward pool to your off-chain address.
</p>
<p>
<p class="m-walletTertiaryText">
To start earning rewards, you will need to enter a unique phone number.
</p>
</div>
<!-- TODOOJM: check on the enter key behavior -->
<form [formGroup]="form" (keyup.enter)="onSubmit()">
<div class="m-walletForm__wrapper">
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField" *ngIf="!confirming">
<div class="m-walletForm__row--label">
<label for="number" i18n>Mobile Phone Number</label>
<m-tooltip icon="help">
<ng-container i18n
>Minds will not store the number you provide. It will be hashed
using SHA-256 and combined with a salt key for privacy and unique
identification purposes. VOIP numbers are not
allowed.</ng-container
>
</m-tooltip>
</div>
<m-phoneInput
formControlName="number"
class="m-walletForm__row--input"
[ngClass]="{ invalid: invalidNumber }"
name="number"
id="number"
ngDefaultControl
></m-phoneInput>
<div class="m-walletForm__row--validation">
<p *ngIf="invalidNumber">
Invalid phone number
</p>
</div>
<form
[formGroup]="form"
(keyup.enter)="onSubmit()"
class="m-walletButtonLayout--buttonInline"
>
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField" *ngIf="!confirming">
<div class="m-walletForm__row--label">
<label for="number" i18n>Mobile Phone Number</label>
<m-tooltip icon="help">
<ng-container i18n
>Minds will not store the number you provide. It will be hashed
using SHA-256 and combined with a salt key for privacy and unique
identification purposes. VOIP numbers are not allowed.</ng-container
>
</m-tooltip>
</div>
<m-phoneInput
formControlName="number"
class="m-walletForm__row--input"
[ngClass]="{ invalid: invalidNumber }"
name="number"
id="number"
ngDefaultControl
></m-phoneInput>
<div class="m-walletForm__row--validation">
<p *ngIf="invalidNumber">
Invalid phone number
</p>
</div>
</div>
<div class="m-walletForm__field--text stretchedField" *ngIf="confirming">
<div class="m-walletForm__row--label">
<label for="code" i18n>Verification Code</label>
<m-tooltip icon="help">
<ng-container i18n
>Please enter the code we just sent to +{{
form.value.number
}}.</ng-container
>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{ invalid: invalidCode }"
>
<input
type="text"
id="code"
name="code"
formControlName="code"
class="form-control"
autofocus
/>
</div>
<div class="m-walletForm__field--text stretchedField" *ngIf="confirming">
<div class="m-walletForm__row--label">
<label for="code" i18n>Verification Code</label>
<m-tooltip icon="help">
<ng-container i18n
>Please enter the code we just sent to +{{
form.value.number
}}.</ng-container
>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{ invalid: invalidCode }"
>
<input
type="text"
id="code"
name="code"
formControlName="code"
class="form-control"
autofocus
/>
</div>
<div class="m-walletForm__row--validation">
<p *ngIf="invalidCode">
Invalid verification code
</p>
</div>
<div class="m-walletForm__row--validation">
<p *ngIf="invalidCode">
Invalid verification code
</p>
</div>
</div>
<!-- TODOOJM button disabling -->
<!-- (from onboarding: !number || number.length < 13) -->
<!-- [disabled]="inProgress || invalidNumber || invalidCode" -->
<m-shadowboxSubmitButton
[disabled]="inProgress"
[saving]="inProgress"
(click)="onSubmit()"
>
{{ !confirming ? 'Send Verification' : 'Verify Code' }}
</m-shadowboxSubmitButton>
</div>
<!-- TODOOJM button disabling -->
<!-- (from onboarding: !number || number.length < 13) -->
<!-- [disabled]="inProgress || invalidNumber || invalidCode" -->
<m-shadowboxSubmitButton
[disabled]="inProgress"
[saving]="inProgress"
(click)="onSubmit()"
>
{{ !confirming ? 'Send Verification' : 'Verify Code' }}
</m-shadowboxSubmitButton>
</form>
<div class="m-walletModal__footnote--formStatus" *ngIf="confirming">
<div class="m-walletPhoneVerification__formStatusCodeSent">
Verification code sent to +{{ form.value.number }}
</div>
<div class="m-walletPhoneVerification__formStatusActions">
<div class="m-walletModal__footnote" *ngIf="confirming">
<div>Verification code sent to +{{ form.value.number }}</div>
<div>
Didn't receive it? <a (click)="validateNumber()">Send it again</a> or
<a (click)="changePhone()">change phone number</a>
</div>
......
m-walletPhoneVerification {
.m-walletModal__footnote {
.m-walletPhoneVerification__formStatusCodeSent {
margin-bottom: 6px;
div {
@include m-theme() {
color: themed($m-grey-800);
}
&:first-child {
margin-bottom: 8px;
}
}
}
......@@ -12,18 +14,23 @@ m-walletPhoneVerification {
.m-phoneInput__countryList {
max-height: 124px;
}
}
m-shadowboxSubmitButton {
width: 147px;
button {
width: 100%;
.m-phoneInput__wrapper {
@media screen and (max-width: $max-mobile) {
min-width: 200px;
}
}
}
// m-shadowboxSubmitButton {
// width: 147px;
// button {
// width: 100%;
// }
// }
@media screen and (max-width: 771px) {
m-shadowboxSubmitButton {
margin: 0 0 21px 0;
}
// m-shadowboxSubmitButton {
// margin: 0 0 21px 0;
// }
.stretchedField {
.m-walletForm__row--label m-tooltip {
.m-tooltip--bubble {
......@@ -31,6 +38,7 @@ m-walletPhoneVerification {
width: 174px;
}
}
// TODOOJM look into this
[class*='m-walletForm__row'] {
&:not(.m-phoneInput__wrapper) {
flex-flow: row wrap;
......
......@@ -4,7 +4,8 @@ m-walletRewardsPopup {
top: 0;
left: 0;
font-weight: 300;
@include m-walletText--13;
font-size: 13px;
line-height: 18px;
@include m-theme() {
background-color: themed($m-white);
color: themed($m-textColor--secondary);
......@@ -27,7 +28,8 @@ m-walletRewardsPopup {
margin: 10px 20px 20px 20px;
span {
@include m-walletText--14;
font-size: 14px;
line-height: 19px;
@include m-theme() {
color: themed($m-textColor--primary);
}
......
......@@ -2,15 +2,15 @@
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
<div class="m-walletSettings" *ngIf="loaded">
<!---PROVIDE ADDRESS---------------------------->
<div
class="m-walletSettingsView--addressProvide"
*ngIf="!currentAddress && !showForm"
>
<!-- -------------------------------------------- -->
<!--- ADDRESS - SETUP - ---------------------------->
<!-- -------------------------------------------- -->
<div *ngIf="!currentAddress && !showForm">
<h2>
Setup your Bitcoin Address
</h2>
<p>
<p class="m-walletTertiaryText--desc">
You can receive Bitcoin payments by linking your Bitcoin receiver address
below.
</p>
......@@ -18,59 +18,66 @@
Add Bitcoin address
</m-shadowboxSubmitButton>
</div>
<div class="m-walletSettingsView--addressProvide" *ngIf="showForm">
<!-- -------------------------------------------- -->
<!--- ADDRESS - PROVIDE ---------------------------->
<!-- -------------------------------------------- -->
<div *ngIf="showForm">
<h2>
Update Bitcoin Address
</h2>
<p>
<p class="m-walletTertiaryText--desc">
Note: You may want to rotate this address frequently to avoid third party
tracking.
</p>
<form *ngIf="form" [formGroup]="form">
<div class="m-walletForm__wrapper">
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label">
<label for="addressInput" i18n>Bitcoin Address</label>
<m-tooltip icon="help">
<ng-container i18n
>Enter the public address from your own Bitcoin wallet which
will be used to receive Bitcoin payments on Minds. Minds does
not store your Bitcoin.</ng-container
>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid:
(form.dirty || form.touched) &&
addressInput.hasError('format')
}"
>
<input
type="text"
id="addressInput"
name="addressInput"
formControlName="addressInput"
class="form-control"
[readonly]="inProgress"
autofocus
/>
</div>
<div class="m-walletForm__row--validation">
<p
*ngIf="
(form.dirty || form.touched) &&
addressInput.hasError('format')
"
<form
*ngIf="form"
[formGroup]="form"
class="m-walletButtonLayout--buttonOffsetRight"
>
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label m-walletTertiaryText--label">
<label for="addressInput" i18n>Bitcoin Address</label>
<m-tooltip icon="help">
<ng-container i18n
>Enter the public address from your own Bitcoin wallet which
will be used to receive Bitcoin payments on Minds. Minds does
not store your Bitcoin.</ng-container
>
Invalid address format
</p>
</div>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid:
(form.dirty || form.touched) && addressInput.hasError('format')
}"
>
<input
type="text"
id="addressInput"
name="addressInput"
formControlName="addressInput"
class="form-control"
[readonly]="inProgress"
autofocus
/>
</div>
<div class="m-walletForm__row--validation">
<p
*ngIf="
(form.dirty || form.touched) && addressInput.hasError('format')
"
>
Invalid address format
</p>
</div>
</div>
</div>
<div class="m-walletForm__buttonsContainer">
<m-shadowboxSubmitButton
[disabled]="
inProgress ||
......@@ -84,31 +91,29 @@
</div>
</form>
<a
class="m-walletSettings__backButton"
class="m-walletTertiaryText--backButton"
*ngIf="currentAddress"
(click)="showForm = false"
><i class="material-icons"></i><span>Back to current address</span></a
>
</div>
<!---CURRENT ADDRESS ----------------------------------------------->
<div
class="m-walletSettingsView--addressCurrent"
*ngIf="currentAddress && !showForm"
>
<!-- -------------------------------------------- -->
<!--- ADDRESS - CURRENT ---------------------------->
<!-- -------------------------------------------- -->
<div *ngIf="currentAddress && !showForm">
<h2>
Bitcoin Address
</h2>
<ng-container *ngTemplateOutlet="onchainDesc"></ng-container>
<p class="m-walletSettingsView--addressCurrent__title">
Current receiver address
<p class="m-walletTertiaryText--label">
Current bitcoin address
</p>
<div class="m-walletSettingsView--addressCurrent__addressContainer">
<div>{{ currentAddress }}</div>
<div>
<a (click)="addressInput.value = ''; showForm = true">Change Address</a>
</div>
<div class="m-walletSettings__currentAddressContainer">
<div class="m-walletPrimaryText">{{ currentAddress }}</div>
<a (click)="addressInput.value = ''; showForm = true">Change Address</a>
</div>
</div>
</div>
......@@ -46,7 +46,8 @@ export class WalletCashBankFormComponent implements OnInit {
accountNumber: ['', Validators.required],
routingNumber: ['', requiredFor(['US'])],
});
this.initCountry = this.hasBankAccount
this.initCountry = this.hasBankAccount()
? this.account.bankAccount.country
: this.account.country;
this.country.patchValue(this.initCountry);
......@@ -111,9 +112,13 @@ export class WalletCashBankFormComponent implements OnInit {
async addBank() {
this.error = '';
this.inProgress = true;
this.detectChanges();
this.walletService
.addStripeBank(this.form.value)
.then((response: any) => {
console.log('addBank response', response);
this.editing = false;
const toasterMessage = 'Your bank account has been successfully added';
......
<div class="m-walletOnboardingExtrasForm" *ngIf="account">
<div class="m-walletCashOnboardingExtrasForm" *ngIf="account">
<p>Start receiving cash payouts by adding your bank details.</p>
<!-- **** INPUT: PHOTO ID -->
<ng-container
......
......@@ -17,7 +17,7 @@ import { Session } from '../../../../../services/session';
})
export class WalletCashOnboardingComponent implements OnInit {
@Input() allowedCountries: string[];
@Input() account;
// @Input() account;
@Output() submitted: EventEmitter<any> = new EventEmitter();
form;
user;
......
<div *ngIf="!loaded" class="m-wallet__spinner">
<div *ngIf="inProgress || !init" class="m-wallet__spinner">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
<div class="m-walletSettings" *ngIf="loaded">
<h4>Bank Information</h4>
<div class="m-walletSettings" *ngIf="!inProgress && init">
<h2>Bank Information</h2>
<!-- ONBOARDING FORM ------------------ -->
<m-walletCashOnboarding
*ngIf="view === 'onboarding'"
[account]="account"
[allowedCountries]="allowedCountries"
(submitted)="setView()"
></m-walletCashOnboarding>
......@@ -25,5 +24,7 @@
(submitted)="setView()"
></m-walletCashOnboardingExtras>
<!-- ERROR ----------------------------- -->
<p *ngIf="view === 'error'" class="m-walletForm__error">{{ error }}</p>
<p *ngIf="view === 'error'" class="m-walletTertiaryText--error">
{{ error }}
</p>
</div>
// additional shared styles located in dashboard.component.scss
m-walletSettings--cash {
.m-walletSettings {
h4 {
margin-bottom: 15px;
}
}
.m-walletSettingsView--hasAccount__detailsWrapper {
max-width: 460px;
margin: 38px 0 59px 0;
......@@ -34,21 +28,51 @@ m-walletSettings--cash {
}
}
// FORM -------------------
[class*='m-walletForm__field'] {
margin-bottom: 19px;
}
.m-tooltip--bubble {
right: 12px;
}
// TOS checkbox
m-walletCashOnboarding {
.m-walletForm__field--checkbox {
margin-top: 100px;
span {
font-size: 14px;
////////////////////////////////////////////
// FORMS ///////////////////////////////////
////////////////////////////////////////////
// [class*='m-walletForm__field'] {
// margin-bottom: 19px;
// }
.m-walletForm__nameFieldsContainer {
display: flex;
box-sizing: border-box;
flex-flow: row wrap;
[class*='m-walletForm__field'] {
flex: 1 0 auto;
min-width: 300px;
&:first-child {
margin-right: 19px;
}
}
}
.m-walletForm__multifieldGroup {
margin-top: 58px;
}
.m-walletForm__field--checkbox {
margin-top: 100px;
@media screen and (max-width: $max-mobile) {
margin-top: 40px;
}
}
m-date__dropdowns {
select {
outline: none;
@include m-theme() {
color: themed($m-textColor--primary);
border: 1px solid themed($m-borderColor--primary);
box-shadow: 0 1px 4px 0 rgba(themed($m-black), 0.1);
}
&:focus {
@include m-theme() {
border: 1px solid themed($m-blue);
}
}
}
}
......
......@@ -8,23 +8,32 @@ import {
} from '@angular/core';
import { WalletDashboardService, WalletCurrency } from '../dashboard.service';
import { Session } from '../../../../services/session';
@Component({
selector: 'm-walletSettings--cash',
templateUrl: './settings-cash.component.html',
})
export class WalletSettingsCashComponent implements OnInit {
@Input() cashWallet: WalletCurrency; // TODOOJM handle
@Output() accountChanged: EventEmitter<any> = new EventEmitter<any>();
@Output() scrollToCashSettings: EventEmitter<any> = new EventEmitter<any>();
loaded: boolean = false;
private _cashWallet: WalletCurrency;
@Input() set cashWallet(c: WalletCurrency) {
this._cashWallet = c;
this.detectChanges();
if (this.init) {
this.setView();
}
}
get cashWallet(): WalletCurrency {
return this._cashWallet;
}
init: boolean = false;
inProgress: boolean = true;
user;
account;
error: string = '';
view: 'onboarding' | 'bank' | 'extras' | 'error';
view: string;
allowedCountries: string[] = [
'AT',
......@@ -58,47 +67,36 @@ export class WalletSettingsCashComponent implements OnInit {
) {}
ngOnInit() {
this.user = this.session.getLoggedInUser();
this.setView();
this.loaded = true;
this.detectChanges();
}
async setView() {
// Flow should be:
// 1. onboarding
// 2. bank
// 3. (if necessary) extras
// 4. (once verified) bank
console.log('888 ... setting view');
const previousView = this.view;
// this.view = null;
this.inProgress = true;
this.detectChanges();
const previousView = this.view || 'onboarding';
const hasMerchant = this.user && this.user.merchant.service === 'stripe';
// const user = this.session.getLoggedInUser();
// const hasMerchant = user && user.merchant.service === 'stripe';
if (!hasMerchant) {
// if (!hasMerchant) {
if (!this.cashWallet.stripeDetails.hasAccount) {
this.view = 'onboarding';
} else {
this.account = await this.getAccount();
console.log('888settingscashaccount', this.account);
if (this.error) {
this.detectChanges();
return;
}
await this.getAccount();
if (!this.hasBankAccount() || this.account.verified) {
if (
this.cashWallet.stripeDetails.verified ||
!this.cashWallet.stripeDetails.hasBank
) {
this.view = 'bank';
} else if (!this.account.verified && this.account.requirement) {
} else {
this.view = 'extras';
}
}
if (this.loaded && previousView === this.view && this.view !== 'error') {
if (this.init && previousView !== this.view && this.view !== 'error') {
this.accountChanged.emit();
}
this.inProgress = false;
this.init = true;
this.detectChanges();
}
......@@ -110,24 +108,14 @@ export class WalletSettingsCashComponent implements OnInit {
.getStripeAccount()
.then((account: any) => {
this.account = account;
this.setView();
this.detectChanges();
})
.catch(e => {
this.error = e.message;
this.view = 'error';
this.inProgress = false;
this.detectChanges();
});
}
hasBankAccount() {
if (this.account && this.account.requirement) {
return this.account.requirement.indexOf('external_account') === -1;
} else {
return true;
}
}
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
......
<!-- <div *ngIf="!ethWallet" class="m-wallet__spinner">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div> -->
<!-- <div class="m-walletSettings" *ngIf="ethWallet"> -->
<!-- -------------------------------------------- -->
<!--- ADDRESS - SETUP - ---------------------------->
<!-- -------------------------------------------- -->
<div class="m-walletSettings">
<h2>Ether Address</h2>
<p>
Your Ether address is the same as your on-chain address.<m-tooltip
icon="help"
>
Why? On-chain tokens run on the Ethereum network and require Ether to
send.
</m-tooltip>
</p>
<p>
To view or change your address, go to
<a (click)="scrollToTokenSettings.emit()">token settings</a>.
</p>
<div class="m-walletTertiaryText--desc">
<p>
Your Ether address is the same as your on-chain address.<m-tooltip
icon="help"
>
Why? On-chain tokens run on the Ethereum network and require Ether to
send.
</m-tooltip>
</p>
<p>
To view or change your address, go to
<a (click)="scrollToTokenSettings.emit()">token settings</a>.
</p>
</div>
<div *ngIf="ethWallet.address" class="m-walletSettings--eth__balanceWrapper">
<div>
<p class="m-walletSettings--eth__balanceLabel">Ether total</p>
<p class="m-walletSettings--eth__balanceLabel m-walletTertiaryText--16">
Ether total
</p>
<p class="m-walletSettings--eth__balanceVal">{{ ethWallet.balance }}</p>
</div>
<m-shadowboxSubmitButton [routerLink]="['/token', { purchaseEth: 'open' }]">
......
......@@ -9,11 +9,13 @@ m-walletSettings--eth {
& > div {
margin-right: 24px;
}
@media screen and (max-width: $max-mobile) {
margin-top: 34px;
}
}
.m-walletSettings--eth__balanceLabel {
font-size: 16px;
line-height: 21px;
margin: 0 0 3px 0;
}
.m-walletSettings--eth__balanceVal {
......
<div *ngIf="!wallet" class="m-wallet__spinner">
<div *ngIf="!wallet" class="m-wallet__spinner m-wallet__spinner--tokenSettings">
<div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
</div>
<div class="m-walletSettings" *ngIf="wallet">
<div class="m-walletSettingsView--setup" *ngIf="!display">
<h4>
<!-- -------------------------------------------- -->
<!--- ADDRESS - OPTIONS - -------------------------->
<!-- -------------------------------------------- -->
<div *ngIf="!display">
<h2>
On-chain address
</h4>
</h2>
<ng-container *ngTemplateOutlet="onchainDesc"></ng-container>
<div class="m-walletSettings__setupOptions__recommendation">
<div class="m-walletSettings__recommendation">
<i class="material-icons">thumb_up</i><span>RECOMMENDED</span>
</div>
<ul class="m-walletSettingsView__setupOptions__container">
<li class="m-walletSettingsView__setupOption--metamask">
<ul class="m-walletSettings__tokenSetupOptionsContainer">
<li class="m-walletSettings__tokenSetupOption--metamask">
<div>
<img
class="metamask"
......@@ -58,7 +61,7 @@
</ng-container>
</li>
<li class="m-walletSettingsView__setupOption--custom">
<li class="m-walletSettings__tokenSetupOption--custom">
<h2>
Custom
</h2>
......@@ -74,26 +77,26 @@
</li>
<p *ngIf="currentAddress">
<a
class="m-walletSettings__backButton"
class="m-walletTertiaryText--backButton"
(click)="display = Views.CurrentAddress"
><i class="material-icons"></i
><span>Back to current address</span></a
>
</p>
</ul>
<p class="m-walletTertiaryText--error" *ngIf="error">{{ error }}</p>
</div>
<ul *ngIf="display">
<!---CUSTOM - CREATE ADDRESS----------------------------------------->
<li
class="m-walletSettingsView--addressCreate"
*ngIf="display === Views.CreateAddress"
>
<!-- -------------------------------------------- -->
<!--- ADDRESS - CREATE ----------------------------->
<!-- -------------------------------------------- -->
<li *ngIf="display === Views.CreateAddress">
<!-- Address not created yet -->
<h2>
Create Address
</h2>
<p *ngIf="!generatedAccount">
<p *ngIf="!generatedAccount" class="m-walletTertiaryText--desc">
Generate a custom address to use instead of MetaMask. Once the address
is generated, you will be provided with a link to download the address
and private key.
......@@ -106,9 +109,9 @@
Create Address
</m-shadowboxSubmitButton>
<!-- Address created -->
<p *ngIf="generatedAccount">
<p *ngIf="generatedAccount" class="m-walletTertiaryText--desc">
The address
<span class="m-walletSettings__address--emphasis">{{
<span class="m-walletTertiaryText--emphasis">{{
generatedAccount.address
}}</span>
was successully saved as your on-chain address. Click the button below
......@@ -123,67 +126,69 @@
>
Download Private Key
</m-shadowboxSubmitButton>
<a class="m-walletSettings__backButton" (click)="display = null"
<a class="m-walletTertiaryText--backButton" (click)="display = null"
><i class="material-icons"></i><span>Back to settings</span></a
>
</li>
<!---CUSTOM - PROVIDE ADDRESS---------------------------->
<li
class="m-walletSettingsView--addressProvide"
*ngIf="display === Views.ProvideAddress"
>
<!-- -------------------------------------------- -->
<!--- ADDRESS - PROVIDE ---------------------------->
<!-- -------------------------------------------- -->
<li *ngIf="display === Views.ProvideAddress">
<h2>
Provide Address
</h2>
<p>
<p class="m-walletTertiaryText--desc">
Enter the address that will be stored as your wallet for Minds on-chain
tokens and Ether payments. To conduct transactions you will need your
wallet's private key and MetaMask cannot be installed in your browser.
</p>
<form *ngIf="form" [formGroup]="form">
<div class="m-walletForm__wrapper">
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label">
<label for="addressInput" i18n>On-chain Address</label>
<m-tooltip icon="help">
<ng-container i18n
>This address is where you will receive on-chain Minds
tokens and Ether payments</ng-container
>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid:
(form.dirty || form.touched) &&
addressInput.hasError('format')
}"
>
<input
type="text"
id="addressInput"
name="addressInput"
formControlName="addressInput"
class="form-control"
[readonly]="inProgress"
/>
</div>
<div class="m-walletForm__row--validation">
<p
*ngIf="
(form.dirty || form.touched) &&
addressInput.hasError('format')
"
<form
*ngIf="form"
[formGroup]="form"
class="m-walletButtonLayout--buttonOffsetRight"
>
<div class="m-walletForm__fieldsContainer">
<div class="m-walletForm__field--text stretchedField">
<div class="m-walletForm__row--label">
<label for="addressInput" i18n>On-chain Address</label>
<m-tooltip icon="help">
<ng-container i18n
>This address is where you will receive on-chain Minds tokens
and Ether payments</ng-container
>
Invalid address format
</p>
</div>
</m-tooltip>
</div>
<div
class="m-walletForm__row--input"
[ngClass]="{
invalid:
(form.dirty || form.touched) &&
addressInput.hasError('format')
}"
>
<input
type="text"
id="addressInput"
name="addressInput"
formControlName="addressInput"
class="form-control"
[readonly]="inProgress"
/>
</div>
<div class="m-walletForm__row--validation">
<p
*ngIf="
(form.dirty || form.touched) &&
addressInput.hasError('format')
"
>
Invalid address format
</p>
</div>
</div>
</div>
<div class="m-walletForm__buttonsContainer">
<m-shadowboxSubmitButton
[disabled]="
inProgress ||
......@@ -196,34 +201,37 @@
</m-shadowboxSubmitButton>
</div>
</form>
<a class="m-walletSettings__backButton" (click)="display = null"
<a class="m-walletTertiaryText--backButton" (click)="display = null"
><i class="material-icons"></i><span>Back to settings</span></a
>
</li>
<!---CURRENT ADDRESS ----------------------------------------------->
<li
class="m-walletSettingsView--addressCurrent"
*ngIf="display === Views.CurrentAddress"
>
<!-- -------------------------------------------- -->
<!--- ADDRESS - CURRENT ---------------------------->
<!-- -------------------------------------------- -->
<li *ngIf="display === Views.CurrentAddress">
<h2>
On-chain Address
</h2>
<ng-container *ngTemplateOutlet="onchainDesc"></ng-container>
<p class="m-walletSettingsView--addressCurrent__title">
<p class="m-walletTertiaryText--label">
Current address
</p>
<div class="m-walletSettingsView--addressCurrent__addressContainer">
<div>{{ currentAddress }}</div>
<div><a (click)="display = null">Change Address</a></div>
<div class="m-walletSettings__currentAddressContainer">
<div class="m-walletPrimaryText">{{ currentAddress }}</div>
<a (click)="display = null">Change Address</a>
</div>
</li>
</ul>
<p class="m-walletTertiaryText--error" *ngIf="error">{{ error }}</p>
</div>
<!-- -------------------------------------------- -->
<!--- ONCHAIN DESCRIPTION TEMPLATE ----------------->
<!-- -------------------------------------------- -->
<ng-template #onchainDesc>
<p>
<p class="m-walletTertiaryText--desc">
To receive on-chain payments from other channels (e.g. from a Wire or a
Boost), you will need an on-chain address. You can change it here at any
time. Note: your on-chain address is the same as your Ether address.
......
m-walletSettings--tokens {
.m-wallet__spinner.m-wallet__spinner--tokenSettings {
margin-top: 40px;
}
.m-walletSettings {
ul {
list-style: none;
margin: 0;
padding: 0;
}
.m-walletSettings__recommendation {
display: flex;
flex-flow: row nowrap;
align-items: flex-end;
font-size: 12px;
line-height: 16px;
margin: 31px 0 0 0;
@include m-theme() {
color: themed($m-textColor--tertiary);
}
i {
font-size: 18px;
margin-right: 8px;
}
}
.m-walletSettings__tokenSetupOptionsContainer {
display: flex;
flex-flow: row wrap;
li {
box-sizing: border-box;
flex: 1 1 50%;
padding: 16px 0 16px 54px;
@media screen and (max-width: 520px) {
flex-basis: 100%;
}
}
p {
@include m-theme() {
color: themed($m-textColor--primary);
}
}
.m-walletSettings__tokenSetupOption--metamask {
padding-right: 32px;
padding-left: 0;
border-width: 0;
border-right-width: 1px;
border-style: solid;
@include m-theme() {
border-image: linear-gradient(
transparent,
rgba(themed($m-grey-200), 0.6),
transparent
)
10 100%;
}
a {
font-weight: 300;
}
div {
display: flex;
flex-flow: row nowrap;
align-items: center;
img {
height: 34px;
margin-right: 12px;
}
}
@media screen and (max-width: 520px) {
padding: 16px 0 32px 0;
border-right-width: 0;
}
}
.m-walletSettings__tokenSetupOption--custom {
div {
margin-top: 16px;
display: inline-block;
a,
span {
display: inline-block;
margin-right: 5px;
font-weight: 300;
}
span {
@include m-theme() {
color: themed($m-textColor--tertiary);
}
}
}
@media screen and (max-width: $min-tablet) {
padding-left: 32px;
}
@media screen and (max-width: 520px) {
padding: 32px 0 0 0;
}
}
}
span.m-walletSettings__createdAddress {
@include m-theme() {
color: themed($m-textColor--primary);
}
}
}
}
......@@ -26,8 +26,7 @@ import { LocalWalletService } from '../../../blockchain/local-wallet.service';
import { BlockchainService } from '../../../blockchain/blockchain.service';
import { Web3WalletService } from '../../../blockchain/web3-wallet.service';
import { getBrowser } from '../../../../utils/browser';
import { FormToastService } from '../../../../common/services/form-toast.service';
import { WalletDashboardService } from '../dashboard.service';
import { WalletDashboardService, Wallet } from '../dashboard.service';
enum Views {
CreateAddress = 1,
......@@ -42,10 +41,9 @@ enum Views {
})
export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
@Output() onchainAddressChanged: EventEmitter<any> = new EventEmitter();
wallet;
inProgress: boolean = false;
linkingMetamask: boolean = false;
error: string;
error: string = '';
display: Views;
generatedAccount: any;
providedAddress: string = '';
......@@ -53,12 +51,26 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
currentAddress: string = '';
downloadingMetamask: boolean = false;
form;
init;
private _wallet: Wallet;
@Input() set wallet(value: Wallet) {
this._wallet = value;
this.error = '';
if (this.init) {
this.load();
}
}
get wallet(): Wallet {
return this._wallet;
}
readonly cdnAssetsUrl: string;
readonly Views = Views;
private _externalTimer;
private _downloadTimer;
constructor(
protected client: Client,
......@@ -68,7 +80,6 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
protected localWallet: LocalWalletService,
protected blockchain: BlockchainService,
protected web3Wallet: Web3WalletService,
private formToastService: FormToastService,
protected walletService: WalletDashboardService,
configs: ConfigsService,
@Inject(PLATFORM_ID) protected platformId: Object
......@@ -76,33 +87,38 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
this.cdnAssetsUrl = configs.get('cdn_assets_url');
}
// TODOOJM add fx to reload whenever the current setting is updated
ngOnInit() {
//TODOOJM remove
console.log(
'*** tksettings-- session.user.rewards:',
this.session.getLoggedInUser().rewards
);
this.form = new FormGroup({
addressInput: new FormControl('', {
validators: [Validators.required, this.validateAddressFormat],
}),
});
this.load();
this.init = true;
}
async load() {
this.wallet = await this.walletService.getWallet();
// this.wallet = await this.walletService.getWallet();
// Check if already has an address
this.currentAddress =
this.session.getLoggedInUser().eth_wallet || this.wallet.receiver.address;
this.currentAddress = this.wallet.receiver.address;
if (this.currentAddress) {
this.display = Views.CurrentAddress;
this.onchainAddressChanged.emit();
}
this.form = new FormGroup({
addressInput: new FormControl('', {
validators: [Validators.required, this.validateAddressFormat],
}),
});
this.checkExternal();
this.detectChanges();
}
ngOnDestroy() {
if (this._downloadTimer) {
clearTimeout(this._downloadTimer);
}
if (this._externalTimer) {
clearInterval(this._externalTimer);
}
......@@ -114,6 +130,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async createAddress() {
this.error = '';
try {
this.inProgress = true;
this.detectChanges();
......@@ -125,8 +142,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
this.currentAddress = this.generatedAccount.address;
} catch (e) {
console.error(e);
// TODOOJM get rid of form toast
// this.formToastService.error(e);
this.error = e.message;
} finally {
this.inProgress = false;
this.detectChanges();
......@@ -134,6 +150,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async downloadPrivateKey() {
this.error = '';
try {
this.inProgress = true;
this.detectChanges();
......@@ -159,7 +176,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
document.body.removeChild(link);
if (isPlatformBrowser(this.platformId)) {
setTimeout(() => {
this._downloadTimer = setTimeout(() => {
URL.revokeObjectURL(objectUrl);
this.generatedAccount = null;
this.onchainAddressChanged.emit();
......@@ -173,8 +190,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
this.display = Views.CurrentAddress;
} catch (e) {
console.error(e);
// TODOOJM get rid of form toast
// this.formToastService.error(e);
this.error = e.message;
this.inProgress = false;
}
}
......@@ -187,6 +203,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async provideAddress() {
this.error = '';
if (this.form.invalid || this.inProgress) {
return;
}
......@@ -197,9 +214,8 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
await this.blockchain.setWallet({ address: this.addressInput.value });
this.onchainAddressChanged.emit();
} catch (e) {
// TODOOJM get rid of form toast
this.formToastService.error(e);
console.error(e);
this.error = e.message;
} finally {
this.inProgress = false;
this.linkingMetamask = false;
......@@ -229,6 +245,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async useExternal() {
this.error = '';
this.linkingMetamask = true;
this.inProgress = true;
await this.web3Wallet.ready();
......@@ -244,6 +261,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async detectExternal() {
this.error = '';
const address: string =
(await this.web3Wallet.getCurrentWallet(true)) || '';
......@@ -253,7 +271,6 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
if (isPlatformBrowser(this.platformId)) {
if (address) {
clearInterval(this._externalTimer);
// this.provideAddress();
this.provideMetamaskAddress(address);
this.detectChanges();
}
......@@ -263,6 +280,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
}
async provideMetamaskAddress(address) {
this.error = '';
try {
this.inProgress = true;
this.detectChanges();
......@@ -272,8 +290,7 @@ export class WalletSettingsTokensComponent implements OnInit, OnDestroy {
this.display = Views.CurrentAddress;
this.onchainAddressChanged.emit();
} catch (e) {
// TODOOJM get rid of form toast
this.formToastService.error(e);
this.error = e.message;
console.error(e);
} finally {
this.inProgress = false;
......
......@@ -34,6 +34,9 @@ m-walletTokenOnboarding {
box-sizing: border-box;
flex-basis: 50%;
min-width: 200px;
@media screen and (max-width: $max-mobile) {
padding: 19px;
}
}
.m-walletTokenOnboardingStep--verifyPhone {
@include m-theme() {
......@@ -48,7 +51,7 @@ m-walletTokenOnboarding {
font-weight: 500;
display: flex;
flex-flow: row nowrap;
align-items: center;
align-items: flex-start;
@include m-theme() {
color: themed($m-grey-800);
}
......@@ -80,13 +83,6 @@ m-walletTokenOnboarding {
}
}
.m-walletForm__wrapper {
margin-bottom: 38px;
}
.m-phoneInput__countryList {
max-height: 114px;
}
// ***************************************************
@media screen and (max-width: 890px) {
......
......@@ -3,7 +3,8 @@
.m-walletTransactions {
margin: 40px 70px;
font-weight: 300;
@include m-walletText--14;
font-size: 14px;
line-height: 19px;
@include m-theme() {
color: themed($m-textColor--secondary);
}
......@@ -108,21 +109,23 @@ m-walletTransactionsTable {
}
}
span {
@include m-walletText--14;
font-size: 14px;
line-height: 19px;
@include m-theme() {
color: themed($m-textColor--secondary);
}
}
}
.m-walletTransactionsTable__total--int {
@include m-walletText--15;
font-size: 15px;
line-height: 20px;
@include m-theme() {
color: themed($m-textColor--primary);
}
}
.m-walletTransactionsTable__total--frac {
@include m-walletText--12;
font-size: 12px;
line-height: 16px;
@include m-theme() {
color: themed($m-textColor--secondary);
}
......