...
 
Commits (2)
......@@ -26,6 +26,9 @@ import { FeaturesService } from '../../../services/features.service';
import { activityServiceMock } from '../../../../tests/activity-service-mock.spec';
import { storageMock } from '../../../../tests/storage-mock.spec';
import { featuresServiceMock } from '../../../../tests/features-service-mock.spec';
import { Storage } from '../../../services/storage';
import { PermissionsService } from '../../services/permissions.service';
import { MockService } from '../../../utils/mock';
/* tslint:disable */
/* Mock section */
......@@ -99,6 +102,10 @@ describe('PostMenuComponent', () => {
{ provide: OverlayModalService, useValue: overlayModalServiceMock },
{ provide: ActivityService, useValue: activityServiceMock },
{ provide: FeaturesService, useValue: featuresServiceMock },
{
provide: PermissionsService,
useValue: MockService(PermissionsService),
},
{ provide: Storage, useValue: storageMock },
{
provide: BlockListService,
......@@ -114,6 +121,7 @@ describe('PostMenuComponent', () => {
// synchronous beforeEach
beforeEach(() => {
featuresServiceMock.mock('allow-comments-toggle', true);
featuresServiceMock.mock('permissions', false);
fixture = TestBed.createComponent(PostMenuComponent);
comp = fixture.componentInstance;
......
......@@ -145,6 +145,15 @@
>
Subscriptions ({{ user.subscriptions_count }})
</a>
<a
[routerLink]="['/', user.username, 'requests']"
*ngIf="user.mode === 2 && user.guid == session.getLoggedInUser().guid"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'requests' }"
>
Requests
</a>
</div>
</div>
......@@ -174,6 +183,15 @@
>
Subscriptions ({{ user.subscriptions_count }})
</a>
<a
[routerLink]="['/', user.username, 'requests']"
*ngIf="user.mode === 2 && user.guid == session.getLoggedInUser().guid"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'requests' }"
>
Requests
</a>
</div>
</div>
......@@ -182,6 +200,10 @@
class="mdl-grid"
></m-channel--subscribers>
</section>
<section class="mdl-cell mdl-cell--8-col" *ngIf="filter == 'requests'">
<m-subscriptionsRequests__list></m-subscriptionsRequests__list>
</section>
</div>
<m-channel--explicit-overlay [channel]="user"></m-channel--explicit-overlay>
......@@ -39,6 +39,7 @@ import { BlockListService } from '../../common/services/block-list.service';
import { ChannelMode } from '../../interfaces/entities';
import { ClientMetaService } from '../../common/services/client-meta.service';
import { clientMetaServiceMock } from '../../../tests/client-meta-service-mock.spec';
import { PermissionsService } from '../../common/services/permissions.service';
describe('ChannelComponent', () => {
let comp: ChannelComponent;
......@@ -50,6 +51,14 @@ describe('ChannelComponent', () => {
MaterialMock,
MaterialSwitchMock,
ChannelComponent,
MockComponent({
selector: 'minds-avatar',
inputs: ['object', 'src', 'editMode', 'waitForDoneSignal'],
}),
MockComponent({
selector: 'minds-button-subscribe',
inputs: ['user', 'request'],
}),
MockComponent({
selector: 'm-channel--supporters',
inputs: ['channel'],
......@@ -62,6 +71,10 @@ describe('ChannelComponent', () => {
selector: 'm-channel--subscribers',
inputs: ['channel'],
}),
MockComponent({
selector: 'm-subscriptionsRequests__list',
inputs: [],
}),
MockComponent({
selector: 'm-channel--carousel',
inputs: ['banners', 'editMode'],
......@@ -108,6 +121,10 @@ describe('ChannelComponent', () => {
{ provide: FeaturesService, useValue: featuresServiceMock },
{ provide: BlockListService, useValue: MockService(BlockListService) },
{ provide: ClientMetaService, useValue: clientMetaServiceMock },
{
provide: PermissionsService,
useValue: MockService(PermissionsService),
},
],
}).compileComponents(); // compile template and css
}));
......@@ -122,6 +139,7 @@ describe('ChannelComponent', () => {
featuresServiceMock.mock('es-feeds', false);
featuresServiceMock.mock('top-feeds', false);
featuresServiceMock.mock('channel-filter-feeds', false);
featuresServiceMock.mock('permissions', false);
comp = fixture.componentInstance;
comp.username = 'username';
comp.user = {
......
......@@ -29,6 +29,8 @@ import { HashtagsModule } from '../hashtags/hashtags.module';
import { ChannelSortedComponent } from './sorted/sorted.component';
import { ChannelSortedModuleComponent } from './sorted/module.component';
import { ReferralsModule } from '../wallet/tokens/referrals/referrals.module';
import { SubscriptionsRequestsListComponent } from './requests/list.component';
import { SubscriptionsRequestsRequestComponent } from './requests/request.component';
const routes: Routes = [
{ path: 'channels/:filter', component: ChannelsListComponent },
......@@ -65,6 +67,8 @@ const routes: Routes = [
ExplicitOverlayComponent,
ChannelSortedComponent,
ChannelSortedModuleComponent,
SubscriptionsRequestsListComponent,
SubscriptionsRequestsRequestComponent,
],
exports: [
ChannelModulesComponent,
......
<ul class="m-subscriptionsRequests__list">
<li
*ngFor="let request of requests"
class="m-subscriptionsRequestsList__item"
>
<m-subscriptionsRequests__request
[request]="request"
></m-subscriptionsRequests__request>
</li>
</ul>
.m-subscriptionsRequests__list {
// @include m-theme() {
// background-color: themed($m-white);
// }
position: relative;
list-style: none;
padding: 0;
margin: 0;
}
.m-subscriptionRequest__card {
@include m-theme() {
background-color: themed($m-white);
}
padding: $minds-padding * 2;
margin-bottom: $minds-margin;
display: flex;
flex-direction: row;
align-items: center;
.m-subscriptionRequestCard__avatar {
width: 36px;
height: 36px;
border-radius: 50%;
}
.m-subscriptionRequestCard__body {
flex: 1;
display: flex;
align-items: center;
margin-left: $minds-margin * 2;
h4 {
padding: 0;
margin: 0;
font-weight: 600;
font-size: 16px;
}
span {
font-size: 11px;
color: #888;
}
.m-btn {
margin-left: $minds-margin;
}
}
}
import { Component } from '@angular/core';
import { Client } from '../../../services/api';
@Component({
selector: 'm-subscriptionsRequests__list',
templateUrl: './list.component.html',
})
export class SubscriptionsRequestsListComponent {
minds = window.Minds;
requests: Array<any> = [];
constructor(private client: Client) {}
ngOnInit() {
this.load();
}
async load() {
const { requests } = <any>(
await this.client.get(`api/v2/subscriptions/incoming`)
);
this.requests = requests;
}
}
<a class="m-subscriptionRequest__card m-border">
<div
class="m-subscriptionRequestCard__avatar"
[style.background-image]="
'url(' + minds.cdn_url + '/icon/' + request.subscriber.guid + ')'
"
></div>
<div class="m-subscriptionRequestCard__body">
<div [title]="request.subscriber.briefdescription">
<h4>{{ request.subscriber.username }}</h4>
<span>{{ request.subscriber.briefdescription }}</span>
</div>
<div class="m-layout__spacer"></div>
<ng-container *ngIf="!request.completed; else completed">
<button class="m-btn m-btn--action m-btn--slim" (click)="accept($event)">
Accept
</button>
<button
class="m-btn m-btn--destructive m-btn--slim"
(click)="decline($event)"
>
Decline
</button>
</ng-container>
<ng-template #completed>
Saved
</ng-template>
</div>
</a>
import { Component, Input } from '@angular/core';
import { Client } from '../../../services/api';
@Component({
selector: 'm-subscriptionsRequests__request',
templateUrl: './request.component.html',
})
export class SubscriptionsRequestsRequestComponent {
minds = window.Minds;
@Input() request;
constructor(private client: Client) {}
async accept() {
this.request.declined = false;
this.request.completed = true;
<any>(
await this.client.put(
`api/v2/subscriptions/incoming/${this.request.subscriber_guid}/accept`
)
);
}
async decline() {
this.request.declined = true;
this.request.completed = true;
<any>(
await this.client.put(
`api/v2/subscriptions/incoming/${this.request.subscriber_guid}/decline`
)
);
}
}
......@@ -90,7 +90,7 @@ describe('ChannelSidebar', () => {
}),
MockComponent({
selector: 'minds-button-subscribe',
inputs: ['user'],
inputs: ['user', 'request'],
}),
MockComponent({
selector: 'm-hashtags-selector',
......
......@@ -50,7 +50,7 @@ describe('ChannelsTileComponent', () => {
}),
MockComponent({
selector: 'minds-button-subscribe',
inputs: ['user'],
inputs: ['user', 'request'],
}),
MockComponent({
selector: 'm-safe-toggle',
......
......@@ -19,6 +19,9 @@ import { MockComponent, MockDirective, MockService } from '../../../utils/mock';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { overlayModalServiceMock } from '../../../../tests/overlay-modal-service-mock.spec';
import { GroupsService } from '../groups-service';
import { FeaturesService } from '../../../services/features.service';
import { featuresServiceMock } from '../../../../tests/features-service-mock.spec';
import { PermissionsService } from '../../../common/services/permissions.service';
let groupConfig = {
countMembers: Promise.resolve(1),
......@@ -63,11 +66,17 @@ describe('GroupsSettingsButton', () => {
{ provide: Client, useValue: clientMock },
{ provide: Session, useValue: sessionMock },
{ provide: OverlayModalService, useValue: overlayModalServiceMock },
{ provide: FeaturesService, useValue: featuresServiceMock },
{
provide: PermissionsService,
useValue: MockService(PermissionsService),
},
],
}).compileComponents();
}));
beforeEach(() => {
featuresServiceMock.mock('permissions', false);
jasmine.MAX_PRETTY_PRINT_DEPTH = 2;
jasmine.clock().uninstall();
jasmine.clock().install();
......
......@@ -9,7 +9,7 @@ import { SignupModalService } from '../../../../modules/modals/signup/service';
template: `
<button
class="m-btn m-btn--with-icon m-btn--subscribe"
*ngIf="!_user.subscribed"
*ngIf="!_user.subscribed && !_user.pending_subscribe"
(click)="subscribe($event)"
>
<i class="material-icons">person_add</i>
......@@ -25,6 +25,18 @@ import { SignupModalService } from '../../../../modules/modals/signup/service';
</ng-container>
</span>
</button>
<button
class="m-btn m-btn--with-icon m-btn--subscribe subscribed"
*ngIf="_user.pending_subscribe"
(click)="unSubscribe($event)"
>
<i class="material-icons">close</i>
<span>
<ng-container i18n="@@MINDS__BUTTONS__UNSUBSCRIBE__SUBSCRIBED_LABEL"
>Pending</ng-container
>
</span>
</button>
<button
class="m-btn m-btn--with-icon m-btn--subscribe subscribed"
*ngIf="_user.subscribed"
......@@ -72,6 +84,10 @@ export class SubscribeButton {
return false;
}
if (this._user.mode === 2) {
return this.requestSubscribe();
}
this._user.subscribed = true;
this.onSubscribed.next();
......@@ -90,6 +106,17 @@ export class SubscribeButton {
});
}
async requestSubscribe() {
this._user.pending_subscribe = true;
try {
await this.client.put(`api/v2/subscriptions/outgoing/${this._user.guid}`);
} catch (err) {
this._user.pending_subscribe = false;
alert('There was an error requesting to subscribe');
}
}
unSubscribe(e) {
e.preventDefault();
e.stopPropagation();
......
......@@ -42,6 +42,41 @@
</a>
</ng-template>
<!-- subscription_request_declined -->
<ng-template ngSwitchCase="subscription_request_declined">
<a [routerLink]="['/', notification.fromObj.username || '']">
<p>
<span class="pseudo-link mdl-color-text--blue-grey-400">{{
notification.fromObj.name
}}</span>
rejected your subscription request.
</p>
</a>
</ng-template>
<!-- subscription_request_accepted -->
<ng-template ngSwitchCase="subscription_request_accepted">
<a [routerLink]="['/', notification.fromObj.username || '']">
<p>
<span class="pseudo-link mdl-color-text--blue-grey-400">{{
notification.fromObj.name
}}</span>
accepted your subscription request. You are now subscribed.
</p>
</a>
</ng-template>
<ng-template ngSwitchCase="subscription_request_received">
<a [routerLink]="['/', session.getLoggedInUser().username, 'requests']">
<p>
<span class="pseudo-link mdl-color-text--blue-grey-400">{{
notification.fromObj.name
}}</span>
has requested to subscribe to you.
</p>
</a>
</ng-template>
<!-- referral ping -->
<ng-template ngSwitchCase="referral_ping">
<a [routerLink]="['/wallet/tokens/contributions']">
......