...
 
Commits (3)
.m-marketing__main,
.m-marketing__section {
// Common
overflow-x: hidden;
.m-marketing--hideMobile {
@media screen and (max-width: $m-grid-min-vp) {
......
<div class="m-marketing">
<div class="m-marketing--hero">
<div class="m-marketing--hero--video">
<img [src]="minds.cdn_assets_url + 'assets/photos/fractal.jpg'" />
</div>
<div class="m-marketing--hero--inner">
<div class="m-marketing--hero--overlay"></div>
<div class="m-marketing--hero--slogans">
<h1 i18n="@@PLUS__MKT__PLUS_TITLE">Minds Plus</h1>
<h3 i18n="@@PLUS__MKT__PLUS_DESC">
Upgrade your channel and unlock premium features
</h3>
</div>
<div class="m-marketing--hero--actions m-marketing--action-button">
<m-plus--subscription></m-plus--subscription>
</div>
</div>
</div>
<div class="m-marketing--contents m-layout--row">
<div
class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--6-col-phone"
>
<i class="material-icons mdl-color-text--blue-grey-700">trending_up</i>
<h2 i18n="@@PLUS__MKT__HIDE_BOOST_TITLE">Hide Boosts</h2>
<span i18n="@@PLUS__MKT__HIDE_BOOST_DESC"
>Hide all boosted content from your newsfeed and sidebars
(optional)</span
>
</div>
<div
class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--6-col-phone"
>
<i class="material-icons mdl-color-text--blue-grey-700">favorite</i>
<h2 i18n="@@PLUS__MKT__EXCLUSIVE_TITLE">Exclusive</h2>
<span i18n="@@PLUS__MKT__EXCLUSIVE_DESC"
>Access exclusive Minds content</span
>
</div>
<div
class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--6-col-phone"
>
<i class="material-icons mdl-color-text--blue-grey-700">verified_user</i>
<h2 i18n="@@PLUS__MKT__VERIFIED_TITLE">Verified</h2>
<span *ngIf="!user || !user.plus" i18n="@@PLUS__MKT__VERIFIED_DESC"
>Request to verify your channel</span
>
<span
*ngIf="user && user.plus && !user.verified"
i18n="@@PLUS__MKT__VERIFY_LINK"
>
<a (click)="showVerify = true; detectChanges()" style="cursor:pointer"
>Click here</a
>
to request to be verified
</span>
<span
*ngIf="user && user.plus && user.verified"
i18n="@@PLUS__MKT__YOURE_VERIFIED_LEGEND"
>You are verified!</span
>
</div>
<div
class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--6-col-phone"
>
<i class="material-icons mdl-color-text--blue-grey-700"
>add_circle_outline</i
>
<h2 i18n="@@PLUS__MKT__BADGE_TITLE">Badge</h2>
<span i18n="@@PLUS__MKT__BADGE_DESC"
>Make your channel stand out with a Minds Plus badge</span
>
</div>
</div>
<div class="m-marketing--faq">
<m-faq category="plus"></m-faq>
</div>
<m-plus--verify
*ngIf="showVerify"
(closed)="showVerify = false; detectChanges()"
></m-plus--verify>
</div>
<m-footer></m-footer>
.m-plus--marketing-header {
background: url('<%= APP_CDN %>/assets/photos/fractal.jpg');
width: 100%;
text-align: center;
display: flex;
align-content: center;
flex-direction: column;
padding: 224px 36px;
box-sizing: border-box;
position: relative;
@media only screen and (max-width: 400px) {
padding: 110px 0;
}
h1,
h3 {
font-family: 'Roboto', Helvetica, sans-serif;
@include m-theme() {
color: themed($m-white);
text-shadow: 0 0 3px themed($m-grey-900);
}
@media only screen and (max-width: 400px) {
margin: 0;
}
z-index: 1;
}
h1 {
word-spacing: 25px;
letter-spacing: 4px;
text-transform: uppercase;
@media only screen and (max-width: 400px) {
font-size: 30px;
}
}
h3 {
letter-spacing: 2px;
word-spacing: 3px;
font-weight: 300;
@media only screen and (max-width: 400px) {
font-size: 14px;
}
}
.m-plus--marketing-action-button {
button {
letter-spacing: 3px;
font-size: 18px;
line-height: 35px;
height: 53px;
padding: 0 24px;
font-weight: 300;
font-family: 'Roboto', Helvetica, sans-serif;
@include m-theme() {
color: themed($m-white);
}
}
z-index: 2;
}
.m-plus--overlay {
display: block;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 0;
@include m-theme() {
background-color: rgba(themed($m-black), 0.5);
}
}
}
.m-plus--marketing-contents {
max-width: 990px;
padding: 64px 0 !important;
justify-content: center;
.mdl-cell {
padding: 32px 16px;
text-align: center;
i {
font-size: 64px;
}
h2 {
padding: 0;
margin: 24px 0;
text-transform: uppercase;
font-family: 'Roboto', Helvetica, sans-serif;
font-weight: 300;
letter-spacing: 2px;
font-size: 30px;
}
span {
font-family: 'Roboto', Helvetica, sans-serif;
letter-spacing: 1px;
}
}
}
.m-plus--marketing m-plus--onboarding {
margin: -115px auto 0;
display: block;
position: relative;
max-width: 990px;
form {
padding: 16px;
}
}
.m-plus--marketing-faq {
max-width: 900px;
margin: auto;
padding: 16px;
}
.m-plus--marketing m-plus--terms {
max-width: 600px;
margin: 16px auto;
display: block;
padding: 16px;
max-height: 600px;
overflow: scroll;
@include m-theme() {
background-color: themed($m-white);
}
}
.m-marketing--action-button button {
margin: 5px;
}
///<reference path="../../../../node_modules/@types/jasmine/index.d.ts"/>
import {
async,
ComponentFixture,
fakeAsync,
TestBed,
tick,
} from '@angular/core/testing';
import {
Component,
DebugElement,
EventEmitter,
Input,
Output,
} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Client } from '../../services/api/client';
import { clientMock } from '../../../tests/client-mock.spec';
import { PlusVerify } from '../../mocks/modules/plus/verify';
import { FooterComponentMock } from '../../mocks/modules/plus/footer';
import { FaqMock } from '../../mocks/modules/plus/faq';
import { PlusSubscription } from '../../mocks/modules/plus/subscription';
import { PlusMarketingComponent } from './marketing.component';
import { RouterTestingModule } from '@angular/router/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { By } from '@angular/platform-browser';
describe('PlusMarketingComponent', () => {
let comp: PlusMarketingComponent;
let fixture: ComponentFixture<PlusMarketingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
PlusMarketingComponent,
PlusSubscription,
FooterComponentMock,
PlusVerify,
FaqMock,
],
imports: [RouterTestingModule, FormsModule, ReactiveFormsModule],
providers: [{ provide: Client, useValue: clientMock }],
}).compileComponents();
}));
beforeEach(done => {
jasmine.MAX_PRETTY_PRINT_DEPTH = 10;
jasmine.clock().uninstall();
jasmine.clock().install();
fixture = TestBed.createComponent(PlusMarketingComponent);
comp = fixture.componentInstance;
window.Minds.user = {
guid: '732337264197111809',
type: 'user',
subtype: false,
time_created: '1499978809',
time_updated: false,
container_guid: '0',
owner_guid: '0',
site_guid: false,
access_id: '2',
name: 'minds',
username: 'minds',
language: 'en',
icontime: '1506690756',
legacy_guid: false,
featured_id: false,
banned: 'no',
website: '',
dob: '',
gender: '',
city: '',
merchant: {},
boostProPlus: false,
fb: false,
mature: 0,
monetized: '',
signup_method: false,
social_profiles: [],
feature_flags: false,
programs: ['affiliate'],
plus: true,
verified: false,
disabled_boost: false,
show_boosts: false,
chat: true,
subscribed: false,
subscriber: false,
subscriptions_count: 1,
impressions: 10248,
boost_rating: '2',
spam: 0,
deleted: 0,
};
// Set up mock HTTP client
clientMock.response = {};
clientMock.response['api/v1/plus'] = {
status: 'success',
active: false,
};
fixture.detectChanges();
if (fixture.isStable()) {
done();
} else {
fixture.whenStable().then(() => {
done();
});
}
});
afterEach(() => {
// reset jasmine clock after each test
jasmine.clock().uninstall();
});
it('Should load correctly', () => {
const marketing = fixture.debugElement.query(By.css('.m-marketing--hero'));
const marketingInner = fixture.debugElement.query(
By.css('.m-marketing--hero--inner')
);
expect(marketing).not.toBeNull();
expect(marketingInner).not.toBeNull();
});
});
import {
Component,
ChangeDetectionStrategy,
ChangeDetectorRef,
ViewChild,
ElementRef,
} from '@angular/core';
import { PlusSubscriptionComponent } from './subscription.component';
import { Client } from '../../../common/api/client.service';
// @Component({
// selector: 'm-plus--marketing',
// templateUrl: 'marketing.component.html',
// changeDetection: ChangeDetectionStrategy.OnPush,
// })
export class PlusMarketingComponent {
@ViewChild('subscription', { static: false })
private subscription: PlusSubscriptionComponent;
user = window.Minds.user;
minds = window.Minds;
showVerify: boolean = false;
constructor(private client: Client, private cd: ChangeDetectorRef) {}
}
<button
class="mdl-button mdl-button--colored mdl-color--green"
*ngIf="user && !isPlus()"
(click)="purchase()"
[hidden]="active"
>
Upgrade - {{ minds.upgrades.plus['monthly']['tokens'] }} Tokens/month
</button>
<!--<button-->
<!-- class="mdl-button mdl-button&#45;&#45;colored mdl-color&#45;&#45;green"-->
<!-- *ngIf="user && !isPlus() && false"-->
<!-- (click)="purchase(200, 'year')"-->
<!-- [hidden]="active"-->
<!--&gt;-->
<!-- Upgrade - 200 Tokens/year-->
<!--</button>-->
<button
class="mdl-button mdl-button--colored mdl-color--green"
*ngIf="user && isPlus()"
(click)="cancel()"
i18n="@@PLUS__MKT__CANCEL_ACTION"
>
Cancel Plus
</button>
<button
class="mdl-button mdl-button--colored mdl-color--green"
*ngIf="!user"
routerLink="/login"
>
Upgrade - {{ minds.upgrades.plus['monthly']['tokens'] }} Tokens/month
</button>
<div class="m-plus--subscription mdl-card mdl-shadow--4dp" *ngIf="active">
<p
class="mdl-card__supporting-text"
i18n="@@PLUS__SUBSCRIPTION__CURRENTLY_MEMBER"
>
You are a currently a Plus member.
</p>
<button
(click)="cancel()"
class="mdl-button mdl-button--colored mdl-button--raised"
style="width:200px; margin: 0 16px 16px;"
i18n="@@PLUS__SUBSCRIPTION__CANCEL_PLUS_ACTION"
>
Cancel Plus
</button>
</div>
<div
class="m-plus--subscription mdl-card mdl-shadow--4dp"
*ngIf="completed && isPlus()"
>
<p
class="mdl-card__supporting-text"
i18n="@@PLUS__SUBSCRIPTION__CONGRATULATE_PLUS"
>
Congratulations, you are now a Minds Plus member!
</p>
</div>
<div
class="m-plus--subscription mdl-card mdl-shadow--4dp"
*ngIf="completed && !isPlus()"
>
<p
class="mdl-card__supporting-text"
i18n="@@PLUS__SUBSCRIPTION__REMOVED_PLUS"
>
You have stopped being a Minds Plus Member.
</p>
</div>
import {
Component,
ChangeDetectionStrategy,
ChangeDetectorRef,
EventEmitter,
Output,
Input,
} from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Subscription } from 'rxjs';
import { Client } from '../../../common/api/client.service';
import { Web3WalletService } from '../../blockchain/web3-wallet.service';
import { TokenContractService } from '../../blockchain/contracts/token-contract.service';
import { WireService } from '../../wire/wire.service';
import { WireStruc } from '../../wire/creator/creator.component';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { SignupModalService } from '../../modals/signup/service';
import { Session } from '../../../services/session';
import { WirePaymentsCreatorComponent } from '../../wire/creator/payments/payments.creator.component';
import { WirePaymentHandlersService } from '../../wire/wire-payment-handlers.service';
// @Component({
// selector: 'm-plus--subscription',
// templateUrl: 'subscription.component.html',
// changeDetection: ChangeDetectionStrategy.OnPush,
// })
export class PlusSubscriptionComponent {
user = window.Minds.user;
blockchain = window.Minds.blockchain;
source: string;
error: string;
inProgress: boolean = true;
completed: boolean = false;
active: boolean = false;
@Output('completed') completed$: EventEmitter<any> = new EventEmitter();
@Input('showSubscription') showSubscription: boolean;
payload: any;
minds = window.Minds;
currency: string;
interval: string;
paramSubscription: Subscription;
constructor(
private client: Client,
private tokenContract: TokenContractService,
private wireService: WireService,
private web3Wallet: Web3WalletService,
private overlayModal: OverlayModalService,
private modal: SignupModalService,
private wirePaymentHandlers: WirePaymentHandlersService,
public session: Session,
private cd: ChangeDetectorRef,
private route: ActivatedRoute
) {}
ngOnInit() {
this.paramSubscription = this.route.queryParams.subscribe(
(params: Params) => {
this.currency = params.c || 'tokens';
this.interval = params.i || 'yearly';
if (params.c || params.i) this.purchase();
}
);
}
load(): Promise<any> {
return this.client
.get('api/v1/plus')
.then(({ active }) => {
if (active) this.active = true;
return active;
})
.catch(e => {
throw e;
});
}
isPlus() {
if (this.active || (this.user && this.user.plus)) return true;
return false;
}
setSource(source: string) {
this.source = source;
this.purchase();
}
async purchase(/*amount: number = 20, period: 'month' | 'year' = 'month'*/) {
if (!this.session.isLoggedIn()) {
this.modal.open();
return;
}
const creator = this.overlayModal.create(
WirePaymentsCreatorComponent,
await this.wirePaymentHandlers.get('plus'),
{
interval: this.interval,
currency: this.currency,
amount: this.minds.upgrades.plus[this.interval][this.currency],
onComplete: wire => {
this.completed = true;
this.user.plus = true;
this.active = true;
this.detectChanges();
this.completed$.next(true);
},
}
);
creator.present();
}
cancel() {
this.inProgress = true;
this.error = '';
this.detectChanges();
return this.client
.delete('api/v1/plus/subscription')
.then((response: any) => {
this.inProgress = false;
this.user.plus = false;
this.active = false;
this.detectChanges();
});
}
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
}
ngOnDestroy() {
this.paramSubscription.unsubscribe();
}
}
/*m-plus--subscription*/
.--UNUSED-CSS {
max-width: 600px;
display: block;
margin: -120px auto 0;
z-index: 5;
position: relative;
button.mdl-color--green {
height: auto !important;
}
.m-plus--subscription--select-payment-option {
margin: 10px;
letter-spacing: 0.5px;
}
.m-plus--subscription-currencies {
display: flex;
align-items: center;
justify-content: space-around;
margin: 0;
padding: 0;
list-style: none;
li {
padding: 8px 24px;
padding-left: 24px;
cursor: pointer;
user-select: none;
h4,
span {
margin: 0;
font-weight: 300;
font-size: 24px;
font-weight: 400;
letter-spacing: 0.5px;
}
b {
font-weight: 400 !important;
letter-spacing: 3px;
}
&:first-child {
padding-left: 0;
}
}
}
m--crypto-token-symbol {
font-size: 32px;
.m--crypto-token-symbol--stroke {
@include m-theme() {
stroke: themed($m-grey-700);
}
}
.m--crypto-token-symbol--fill {
@include m-theme() {
fill: themed($m-grey-700);
}
}
}
}