Commit e627d4f4 authored by Mark Harding's avatar Mark Harding

(chore): various wire fixes

No related merge requests found
Pipeline #81760931 running with stages
......@@ -53,6 +53,17 @@
>
</a>
<a
class="m-page--sidebar--navigation--item"
routerLink="/settings/tiers"
routerLinkActive="m-page--sidebar--navigation--item-active"
>
<i class="material-icons">card_giftcard</i>
<span i18n="@@SETTINGS__NAVIGATION__SUBSCRIPTIONS_NAV"
>Subscription Tiers</span
>
</a>
<a
class="m-page--sidebar--navigation--item"
routerLink="/settings/billing"
......
......@@ -26,6 +26,7 @@ import { SettingsWireComponent } from './wire/wire.component';
import { WireModule } from '../wire/wire.module';
import { SettingsP2PMediaComponent } from './p2pmedia/p2pmedia.component';
import { SettingsBlockedChannelsComponent } from './blocked-channels/blocked-channels.component';
import { SettingsTiersComponent } from './tiers/tiers.component';
const settingsRoutes: Routes = [
{
......@@ -43,6 +44,7 @@ const settingsRoutes: Routes = [
{ path: 'reported-content', component: SettingsReportedContentComponent },
{ path: 'p2pmedia', component: SettingsP2PMediaComponent },
{ path: 'blocked-channels', component: SettingsBlockedChannelsComponent },
{ path: 'tiers', component: SettingsTiersComponent },
],
},
];
......@@ -76,6 +78,7 @@ const settingsRoutes: Routes = [
SettingsWireComponent,
SettingsP2PMediaComponent,
SettingsBlockedChannelsComponent,
SettingsTiersComponent,
],
providers: [SettingsService],
exports: [
......
<div class="m-settings--section m-layout__row m-border">
<div
class="minds-error mdl-color--red mdl-color-text--white"
[hidden]="!error"
>
{{ error }}
</div>
<div class="m-layout__spacer"></div>
<button
class="m-btn m-btn--slim m-btn--action"
*ngIf="!isSaving && !isSaved"
(click)="save()"
>
<ng-container i18n="@@M__ACTION__SAVE">Save</ng-container>
</button>
<button class="m-btn m-btn--slim" *ngIf="isSaved">
<ng-container i18n="@@M__COMMON__SAVED">Saved</ng-container>
</button>
<div
id="p2"
class="mdl-progress mdl-js-progress mdl-progress__indeterminate"
[hidden]="!isSaving"
></div>
</div>
<div class="m-border m-settings--section">
<h4>Subscription Tiers</h4>
<p>
Create tiers below to incentivise supporters to wire you. These tiers will
be displayed on the sidebar of your channel page on in the wire screen.
</p>
<m-wire__subscriptionTiers
[user]="session.getLoggedInUser()"
[editing]="true"
(isSaving)="isSaving = $event"
(isSaved)="isSaved = $event"
[saveEventListener]="triggerSave"
>
</m-wire__subscriptionTiers>
</div>
m-settings__tiers .m-settings--section {
display: block;
@include m-theme() {
background-color: themed($m-white);
}
textarea {
padding: 16px;
width: 100%;
}
m-wire-channel-table {
display: block;
margin-top: $minds-margin * 2;
table {
width: 100%;
.m-wire-channel--reward-amount {
display: inline-flex;
width: 100%;
}
}
}
}
import { Component, EventEmitter } from '@angular/core';
import { Session } from '../../../services/session';
import { Client } from '../../../services/api';
@Component({
selector: 'm-settings__tiers',
templateUrl: 'tiers.component.html',
})
export class SettingsTiersComponent {
isSaving = false;
isSaved = false;
triggerSave = new EventEmitter(true);
error: string;
constructor(public session: Session, public client: Client) {}
save() {
this.triggerSave.next(true);
}
}
......@@ -34,38 +34,8 @@
</span>
</div>
<div
class="mdl-card__supporting-text mdl-color-text--grey-600 m-wire-channel--rewards"
>
<p
*ngIf="!editing && rewards.description"
class="m-wire-channel--description"
[innerText]="rewards.description"
></p>
<textarea
*ngIf="editing"
class="m-wire-channel--description-editor"
[(ngModel)]="rewards.description"
[autoGrow]
placeholder="About your offerings. eg. Describe what your supporters will receive…"
i18n-placeholder="@@WIRE__CHANNEL__REWARD_DESCRIPTION_PLACEHOLDER"
></textarea>
<m-wire-channel-table
type="tokens"
[(rewards)]="rewards.rewards.tokens"
[(editing)]="editing"
[channel]="channel"
></m-wire-channel-table>
<p
class="m-wire-channel--disclaimer"
*ngIf="false"
i18n="@@WIRE__CHANNEL__REWARD_CHANGE_NOTICE"
>
<span>@</span>{{ channel.username }} reserves the right to change rewards
at anytime without notice
</p>
</div>
<m-wire__subscriptionTiers
[user]="channel"
[editing]="editing"
></m-wire__subscriptionTiers>
</div>
......@@ -86,7 +86,8 @@ m-wire-channel {
.m-wire-channel--description-editor {
line-height: 1.3;
letter-spacing: 0.5px;
margin: 0 0 ($minds-padding * 2);
margin: 0;
padding: $minds-padding * 2;
}
.m-wire-channel--description {
......
<table
class="m-wire-channel--rewards"
[ngClass]="['m-wire-channel--rewards-' + type]"
[class.m-wire-channel--rewards--is-editing]="editing"
cellspacing="0"
cellspacing="0"
>
......@@ -8,7 +9,8 @@
*ngFor="let reward of rewards; let i = index"
(click)="openWireModal(reward)"
>
<td>
<td [class.m-border]="editing">
<label *ngIf="editing">Threshold</label>
<div class="m-wire-channel--reward-amount">
<span *ngIf="!editing && type == 'money'"
>{{ reward.amount || 0 | currency: 'USD':true:'1.0-0' }}+</span
......@@ -30,6 +32,7 @@
[ngModel]="reward.amount"
(ngModelChange)="setAmount(i, $event)"
[placeholder]="getAmountPlaceholder()"
class="m-input"
/>
<ng-container *ngIf="type == 'points'" i18n="@@M__COMMON__POINTS_SUFFIX"
>points</ng-container
......@@ -43,26 +46,29 @@
<div class="m-wire-channel--reward-description">
<p *ngIf="!editing">{{ reward.description }}</p>
<textarea
*ngIf="editing"
[ngModel]="reward.description"
(ngModelChange)="setDescription(i, $event)"
class="m-border"
[autoGrow]
placeholder="Describe the reward"
i18n-placeholder="@@WIRE__CHANNEL__TABLE__REWARD_PLACEHOLDER"
>
</textarea>
<ng-container *ngIf="editing">
<label>Description</label>
<textarea
*ngIf="editing"
[ngModel]="reward.description"
(ngModelChange)="setDescription(i, $event)"
class="m-border"
[autoGrow]
placeholder="Describe the reward"
i18n-placeholder="@@WIRE__CHANNEL__TABLE__REWARD_PLACEHOLDER"
>
</textarea>
</ng-container>
</div>
</td>
</tr>
</table>
<div
class="m-wire-channel--rewards--add-tier m-border"
class="m-wire-channel--rewards--add-tier"
*ngIf="session.getLoggedInUser().guid == channel.guid"
>
<a (click)="addTier()">
<a (click)="addTier()" class="m-btn m-btn--action m-btn--slim">
<i class="material-icons">playlist_add</i>
<span i18n="@@WIRE__CHANNEL__TABLE__ADD_REWARD_ACTION">Add Reward</span>
</a>
......
.m-wire-channel--rewards > tr > td {
padding: $minds-padding * 2;
margin-bottom: $minds-margin * 2;
label {
font-weight: 600;
font-size: 13px;
line-height: 26px;
}
}
.m-wire-channel--reward-amount {
display: inline-flex;
align-items: center;
.m-input {
flex: 1;
border-radius: 24px;
}
> span {
flex: 1;
}
}
.m-wire-channel--rewards--is-editing {
.m-wire-channel--rewards {
padding: $minds-padding $minds-padding * 2;
}
.m-wire-channel--reward-amount > span {
margin-left: $minds-margin * 2;
}
}
.m-wire-channel--reward-description {
margin-top: $minds-margin * 2;
}
.m-wire-channel--rewards--add-tier {
line-height: 56px;
.m-btn > * {
vertical-align: middle;
}
}
<div class="m-wire-channel--rewards">
<p
*ngIf="!editing && rewards.description"
class="m-wire-channel--description"
[innerText]="rewards.description"
></p>
<textarea
*ngIf="editing"
class="m-wire-channel--description-editor m-border"
[(ngModel)]="rewards.description"
[autoGrow]
placeholder="About your offerings. eg. Describe what your supporters will receive…"
i18n-placeholder="@@WIRE__CHANNEL__REWARD_DESCRIPTION_PLACEHOLDER"
></textarea>
<m-wire-channel-table
type="tokens"
[(rewards)]="rewards.rewards.tokens"
[(editing)]="editing"
[channel]="user"
></m-wire-channel-table>
<m-wire-channel-table
type="money"
[(rewards)]="rewards.rewards.money"
[(editing)]="editing"
[channel]="user"
></m-wire-channel-table>
</div>
import { Component, Input, EventEmitter, Output } from '@angular/core';
import { Session } from '../../../services/session';
import { Client } from '../../../services/api';
import {
WireRewardsType,
WireRewardsStruc,
} from '../interfaces/wire.interfaces';
import { WireTypeLabels } from '../wire';
@Component({
selector: 'm-wire__subscriptionTiers',
templateUrl: 'tiers.component.html',
})
export class WireSubscriptionTiersComponent {
@Input() user;
@Input() editing;
@Input() saveEventListener = new EventEmitter();
@Output() isSaving = new EventEmitter();
@Output() isSaved = new EventEmitter();
rewards = {
description: '',
rewards: {
points: [],
money: [],
tokens: [],
},
};
constructor(public session: Session, private client: Client) {}
ngOnInit() {
if (this.user && this.user.wire_rewards) {
this.rewards = this.user.wire_rewards;
}
this.saveEventListener.subscribe(() => this.save());
}
async save() {
this.rewards.rewards.points = this._cleanAndSortRewards(
this.rewards.rewards.points
);
this.rewards.rewards.money = this._cleanAndSortRewards(
this.rewards.rewards.money
);
this.rewards.rewards.tokens = this._cleanAndSortRewards(
this.rewards.rewards.tokens
);
try {
await this.client.post('api/v1/wire/rewards', {
rewards: this.rewards,
});
this.session.getLoggedInUser().wire_rewards = this.rewards;
this.isSaved.next(true);
} catch (e) {
alert((e && e.message) || 'Server error');
} finally {
this.isSaving.next(false);
}
}
// Internal
private _cleanAndSortRewards(rewards: any[]) {
if (!rewards) {
return [];
}
return rewards
.filter(reward => reward.amount || `${reward.description}`.trim())
.map(reward => ({
...reward,
amount: Math.abs(Math.floor(reward.amount || 0)),
}))
.sort((a, b) => (a.amount > b.amount ? 1 : -1));
}
}
......@@ -416,6 +416,7 @@ export class WireCreatorComponent {
switch (this.wire.payloadType) {
case 'onchain':
case 'eth':
if (!this.wire.payload && !this.wire.payload.receiver) {
throw new Error('Invalid receiver.');
}
......@@ -447,9 +448,11 @@ export class WireCreatorComponent {
break;
case 'usd':
//if (!this.wire.payload) {
// throw new Error('Payment method not processed.');
//}
if (!this.owner.merchant || !this.owner.merchant.id) {
throw new VisibleWireError(
'This channel is not able to receive USD at the moment'
);
}
break;
case 'btc':
if (!this.wire.payload.receiver) {
......
......@@ -67,6 +67,11 @@ export class WireCreatorRewardsComponent {
@Input('rewards') set _rewards(rewards) {
this.rewards = [];
if (!rewards || !rewards.rewards) {
return;
}
const methodsMap = [{ method: 'tokens', currency: 'tokens' }];
if (this.featuresService.has('wire-multi-currency')) {
......@@ -74,6 +79,9 @@ export class WireCreatorRewardsComponent {
}
for (const { method, currency } of methodsMap) {
if (!rewards.rewards[method]) {
continue;
}
for (const reward of rewards.rewards[method]) {
this.rewards.push({
amount: parseInt(reward.amount),
......
......@@ -26,6 +26,7 @@ import { WireMarketingComponent } from './marketing.component';
import { WireConsoleOverviewComponent } from './console/overview/overview.component';
import { WireConsoleRewardsInputsComponent } from './console/rewards-table/inputs/wire-console-rewards-inputs.component';
import { WireConsoleRewardsComponent } from './console/rewards-table/rewards.component';
import { WireSubscriptionTiersComponent } from './channel/tiers.component';
const wireRoutes: Routes = [
{ path: 'wire', component: WireMarketingComponent },
......@@ -60,6 +61,7 @@ const wireRoutes: Routes = [
WireConsoleSettingsComponent,
WireMarketingComponent,
WireConsoleOverviewComponent,
WireSubscriptionTiersComponent,
],
providers: [WireService],
exports: [
......@@ -74,6 +76,7 @@ const wireRoutes: Routes = [
WireConsoleRewardsComponent,
WireConsoleSettingsComponent,
WireConsoleOverviewComponent,
WireSubscriptionTiersComponent,
],
entryComponents: [
WireCreatorComponent,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment