Commit 6e151fc9 authored by Emiliano Balbuena's avatar Emiliano Balbuena

(feat): Admin Withdrawals console

1 merge request!652(feat): Withdrawal status support
Pipeline #95459560 passed with stages
in 33 minutes and 48 seconds
......@@ -114,9 +114,7 @@
></minds-admin-monetization>
<minds-admin-programs *ngIf="filter == 'programs'"></minds-admin-programs>
<minds-admin-payouts *ngIf="filter == 'payouts'"></minds-admin-payouts>
<minds-admin-withdrawals
*ngIf="filter == 'withdrawals'"
></minds-admin-withdrawals>
<m-admin-withdrawals *ngIf="filter == 'withdrawals'"></m-admin-withdrawals>
<minds-admin-featured *ngIf="filter == 'featured'"></minds-admin-featured>
<minds-admin-tagcloud *ngIf="filter == 'tagcloud'"></minds-admin-tagcloud>
<m-admin--verify *ngIf="filter == 'verify'"></m-admin--verify>
......
<div class="mdl-grid m-admin-withdrawals" style="max-width: 900px">
<div class="m-admin-withdrawals--user">
<ng-container *ngIf="user"
><b>@{{ user }}</b
>'s withdrawals</ng-container
>
<ng-container *ngIf="!user">Pending Withdrawals</ng-container>
<div class="m-admin-withdrawals">
<div class="m-admin-withdrawals__legend">
<ng-container *ngIf="user" i18n>
<b>@{{ user }}</b
>'s withdrawals
</ng-container>
<ng-container *ngIf="!user" i18n>
Pending Withdrawals
</ng-container>
</div>
<table class="mdl-data-table mdl-js-data-table m-border" [mdl]>
<thead>
<tr class="m-admin--withdrawals--ledger-header">
<th
class="mdl-data-table__cell--non-numeric m-data-title"
i18n="@@M__ADMIN__WITHDRAWALS__DATE_COL"
>
Date
</th>
<th
class="mdl-data-table__cell--non-numeric m-data-title"
i18n="Transaction@@M__ADMIN__WITHDRAWALS__TX_COL"
>
Tx
</th>
<th
class="mdl-data-table__cell--non-numeric m-data-title"
i18n="@@M__ADMIN__WITHDRAWALS__AMOUNT_COL"
>
Amount
</th>
<th class="mdl-data-table__cell--non-numeric m-data-title">
&nbsp;
</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let withdrawal of withdrawals; let i = index">
<tr class="m-admin--withdrawals--ledger-row">
<td class="mdl-data-table__cell--non-numeric">
{{ withdrawal.timestamp * 1000 | date: 'short' }}
</td>
<td
class="mdl-data-table__cell--non-numeric m-admin--withdrawals--ledger-tx"
<div
class="m-admin-withdrawals__card"
*ngFor="let request of withdrawals; let i = index"
>
<ng-container *ngIf="request">
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>Requested</div>
<div class="m-admin-withdrawalsCardCell__body">
{{ request.timestamp * 1000 | date: 'short' }}
</div>
</div>
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>User</div>
<div class="m-admin-withdrawalsCardCell__body">
<a [routerLink]="['/', request.user?.username]"
>@{{ request.user?.username }}</a
>
{{ withdrawal.tx }}
</td>
<td>{{ withdrawal.amount | token: 18 | number: '1.0-4' }}</td>
<td class="mdl-data-table__cell--non-numeric">
<ng-container
*ngIf="withdrawal.status === 'pending_approval'; else showStatus"
</div>
</div>
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>Signed up</div>
<div class="m-admin-withdrawalsCardCell__body">
{{ request.user?.time_created * 1000 | date: 'shortDate' }}
</div>
</div>
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>Referrer</div>
<div class="m-admin-withdrawalsCardCell__body">
<ng-container *ngIf="request.referrer; else organicText">
<a [routerLink]="['/', request.referrer.username]"
>@{{ request.referrer.username }}</a
>
<button (click)="approve(withdrawal)">Approve</button>
<button (click)="reject(withdrawal)">Reject</button>
</ng-container>
<ng-template #showStatus>
{{ withdrawal.status.toUpperCase() }}
</ng-template>
</td>
</tr>
</ng-container>
<tr
class="m-admin--withdrawals--ledger-row m-wire-console--ledger-row-placeholder"
*ngIf="!inProgress && (!withdrawals || !withdrawals.length)"
>
<td
colspan="4"
style="text-align:center"
i18n="@@M__ADMIN__WITHDRAWALS__NO_WITHDRAWALS_NOTE"
</ng-container>
<ng-template #organicText>
<ng-container>(organic)</ng-container>
</ng-template>
</div>
</div>
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>Amount</div>
<div
class="m-admin-withdrawalsCardCell__body m-admin-withdrawalsCardCell__body--bolder"
>
No withdrawals to show. You can access a user's withdrawal ledger by
using the admin drop-down on their channel.
</td>
</tr>
</tbody>
</table>
{{ request.amount | token: 18 | number: '1.0-4' }}
</div>
</div>
<div class="m-admin-withdrawalsCard__cell">
<div class="m-admin-withdrawalsCardCell__label" i18n>Status</div>
<div class="m-admin-withdrawalsCardCell__body">
{{ request.status?.replace('_', ' ') | uppercase }}
</div>
</div>
<div
class="m-admin-withdrawalsCard__cell m-admin-withdrawalsCard__cell--actions"
*ngIf="request.status === 'pending_approval'"
>
<div class="m-admin-withdrawalsCardCell__body">
<a
[routerLink]="[
'/admin/withdrawals',
{ user: request.user?.username }
]"
>History</a
>
<button
class="mf-button mf-button--smaller"
(click)="approve(request)"
>
Approve
</button>
<button
class="mf-button mf-button--destructive mf-button--smaller"
(click)="reject(request)"
>
Reject
</button>
</div>
</div>
</ng-container>
</div>
<div
class="m-admin-withdrawals__notice"
*ngIf="!inProgress && !withdrawals?.length"
>
No withdrawals to show. You can access a user's withdrawal ledger by using
the admin drop-down on their channel.
</div>
<infinite-scroll
distance="25%"
(load)="load()"
[moreData]="moreData"
[inProgress]="inProgress"
>
</infinite-scroll>
></infinite-scroll>
</div>
.m-admin-withdrawals {
.mdl-data-table {
width: 100%;
max-width: 900px;
margin: 16px auto 0;
.m-admin-withdrawals__legend {
font-size: 16px;
font-weight: 600;
text-align: center;
margin: 8px 0 16px;
letter-spacing: 1px;
}
.m-admin--withdrawals--ledger-tx {
font-size: 12px;
.m-admin-withdrawals__card {
display: flex;
flex-direction: row;
flex-wrap: wrap;
max-width: 600px;
margin: 0 auto 32px;
padding: 8px;
border: 1px solid;
border-radius: 4px;
@include m-theme() {
background: themed($m-white);
color: themed($m-black);
border-color: themed($m-grey-50);
}
}
.m-admin-withdrawalsCard__cell {
flex-grow: 1;
flex-shrink: 0;
box-sizing: border-box;
min-width: 25%;
padding: 8px;
&--actions {
width: 100%;
text-align: right;
padding-top: 24px;
margin-top: 16px;
border-top: 1px dotted;
@include m-theme() {
border-color: themed($m-grey-50);
}
}
a {
color: inherit;
font: inherit;
text-decoration: none;
border-bottom: 1px dotted;
cursor: pointer;
@include m-theme() {
border-color: themed($m-grey-300);
}
}
.m-admin-withdrawalsCardCell__label {
font-weight: 600;
margin-bottom: 2px;
@include m-theme() {
color: themed($m-grey-300);
}
}
.m-admin-withdrawalsCardCell__body {
&--bolder {
font-weight: bold;
letter-spacing: 0.5px;
}
}
&--actions .m-admin-withdrawalsCardCell__body {
> * {
display: inline-block;
vertical-align: middle;
margin: 0 8px 8px;
}
}
}
.m-admin-withdrawals--user {
width: 100%;
font-size: 14px;
font-weight: 300;
.m-admin-withdrawals__notice {
max-width: 600px;
margin: 32px 0;
padding: 16px;
border: 1px solid;
border-radius: 4px;
text-align: center;
padding: 8px 8px 32px;
@include m-theme() {
background: themed($m-white);
color: themed($m-black);
border-color: themed($m-grey-50);
}
}
}
......@@ -4,7 +4,7 @@ import { ActivatedRoute } from '@angular/router';
@Component({
moduleId: module.id,
selector: 'minds-admin-withdrawals',
selector: 'm-admin-withdrawals',
templateUrl: 'withdrawals.component.html',
})
export class AdminWithdrawals {
......@@ -80,6 +80,10 @@ export class AdminWithdrawals {
}
async approve(withdrawal) {
if (!confirm("Do you want to approve this withdrawal? There's no UNDO.")) {
return;
}
try {
const endpoint = `api/v2/admin/rewards/withdrawals/${[
withdrawal.user_guid,
......@@ -96,6 +100,10 @@ export class AdminWithdrawals {
}
async reject(withdrawal) {
if (!confirm("Do you want to reject this withdrawal? There's no UNDO.")) {
return;
}
try {
const endpoint = `api/v2/admin/rewards/withdrawals/${[
withdrawal.user_guid,
......
Please register or to comment