...
 
Commits (2)
......@@ -4,15 +4,20 @@ import {
Component,
ComponentFactoryResolver,
ComponentRef,
Injector,
Input,
OnInit,
SkipSelf,
ViewChild
} from "@angular/core";
import { FeaturedContentService } from "./featured-content.service";
import { DynamicHostDirective } from "../../directives/dynamic-host.directive";
import { Activity } from "../../../modules/legacy/components/cards/activity/activity";
import { ClientMetaService } from "../../services/client-meta.service";
@Component({
selector: 'm-featured-content',
providers: [ ClientMetaService ],
templateUrl: 'featured-content.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
......@@ -20,13 +25,20 @@ export class FeaturedContentComponent implements OnInit {
entity: any;
@Input() slot: number = -1;
@ViewChild(DynamicHostDirective) dynamicHost: DynamicHostDirective;
constructor(
protected featuredContentService: FeaturedContentService,
protected componentFactoryResolver: ComponentFactoryResolver,
protected cd: ChangeDetectorRef,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.clientMetaService
.inherit(injector)
.setMedium('featured-content');
}
ngOnInit() {
......@@ -78,6 +90,7 @@ export class FeaturedContentComponent implements OnInit {
component: Activity,
injector: (componentRef, entity) => {
componentRef.instance.object = entity;
componentRef.instance.slot = this.slot;
componentRef.changeDetectorRef.detectChanges();
}
};
......
import { Injectable, Injector } from "@angular/core";
import { Location } from "@angular/common";
import hashCode from "../../helpers/hash-code";
import { Session } from "../../services/session";
let uniqId = 0;
@Injectable()
export class ClientMetaService {
protected source: string;
protected timestamp: number;
protected salt: string;
protected medium: string;
protected campaign: string;
protected id: number;
protected injector: Injector;
protected inherited: boolean = false;
constructor(
protected location: Location,
protected session: Session,
) {
this.id = ++uniqId;
this.timestamp = Date.now();
this.salt = (Math.random()).toString(36).replace(/[^a-z]+/g, '');
}
inherit(injector: Injector) {
const parentClientMeta: ClientMetaService = injector.get(ClientMetaService, null);
if (parentClientMeta) {
if (parentClientMeta.getId() === this.id) {
throw new Error('[ClientMetaService] Cannot inherit client meta from itself. Did you forget to add to @Component({ providers }) or the @SkipSelf() decorator on Injector?')
}
this.source = parentClientMeta.getSource();
this.timestamp = parentClientMeta.getTimestamp();
this.salt = parentClientMeta.getSalt();
this.medium = parentClientMeta.getMedium();
this.campaign = parentClientMeta.getCampaign();
}
this.inherited = true;
return this;
}
getId() {
return this.id;
}
setSource(source: string) {
this.checkInheritance();
this.source = source;
this.timestamp = Date.now();
this.salt = (Math.random()).toString(36).replace(/[^a-z]+/g, '');
return this;
}
getSource() {
return this.source;
}
getTimestamp() {
return this.timestamp;
}
getSalt() {
return this.salt;
}
buildDelta() {
return Math.floor((Date.now() - this.timestamp) / 1000);
}
setMedium(medium: string) {
this.checkInheritance();
this.medium = medium;
return this;
}
getMedium() {
return this.medium;
}
setCampaign(campaign: string) {
this.checkInheritance();
this.campaign = campaign;
return this;
}
getCampaign() {
return this.campaign;
}
buildPageToken() {
const user = this.session.getLoggedInUser() || {};
const tokenParts = [
this.salt, // NOTE: Salt + hash so individual user activity can't be tracked
this.location.path() || '/',
user.guid || '000000000000000000',
this.timestamp || '',
];
return hashCode(tokenParts.join(':'), 5);
}
build(overrides: { source?, medium?, page_token?, campaign?, delta?, position? } = {}) {
this.checkInheritance();
return {
platform: 'web',
source: this.source,
medium: this.medium,
page_token: this.buildPageToken(),
campaign: this.campaign,
delta: this.buildDelta(),
...overrides
};
}
protected checkInheritance() {
if (!this.inherited) {
console.warn('[ClientMetaService] This instance did not call inherit() before doing any operations.');
}
}
}
......@@ -3,8 +3,8 @@
<div class="minds-list">
<m-onboarding-feed *ngIf="session.isLoggedIn() && session.getLoggedInUser().guid == user.guid"></m-onboarding-feed>
<m-newsfeed--boost-rotator [channel]="user" interval="12" *ngIf="user.guid !== session.getLoggedInUser().guid && user.show_boosts"></m-newsfeed--boost-rotator>
<minds-activity *ngFor="let activity of pinned" [object]="activity" [boostToggle]="activity.boostToggle" class="mdl-card m-border item" (delete)="delete(activity)"></minds-activity>
<minds-activity *ngFor="let activity of feed" [object]="activity" [boostToggle]="activity.boostToggle" class="mdl-card m-border item" (delete)="delete(activity)"></minds-activity>
<minds-activity *ngFor="let activity of pinned; let i = index" [object]="activity" [boostToggle]="activity.boostToggle" class="mdl-card m-border item" (delete)="delete(activity)" [slot]="i + 1"></minds-activity>
<minds-activity *ngFor="let activity of feed; let i = index" [object]="activity" [boostToggle]="activity.boostToggle" class="mdl-card m-border item" (delete)="delete(activity)" [slot]="i + pinned.length + 1"></minds-activity>
<infinite-scroll
distance="25%"
(load)="loadFeed()"
......
import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Component, Injector, Input, OnDestroy, OnInit, SkipSelf, ViewChild } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
......@@ -11,10 +11,12 @@ import { MindsUser } from '../../../interfaces/entities';
import { PosterComponent } from '../../../modules/newsfeed/poster/poster.component';
import { WireChannelComponent } from '../../../modules/wire/channel/channel.component';
import { debounceTime } from "rxjs/operators";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
moduleId: module.id,
selector: 'm-channel--feed',
providers: [ ClientMetaService ],
templateUrl: 'feed.html'
})
......@@ -49,7 +51,14 @@ export class ChannelFeedComponent implements OnInit, OnDestroy {
public client: Client,
public upload: Upload,
public scroll: ScrollService,
) { }
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.clientMetaService
.inherit(injector)
.setSource('feed/channel')
.setMedium('feed');
}
ngOnInit() {
this.loadFeedObservableSubscription = this.loadFeedObservable
......
......@@ -26,8 +26,9 @@
</ng-container>
<ng-template #entityListView>
<m-newsfeed__entity
*ngFor="let entity of getAllEntities()"
*ngFor="let entity of getAllEntities(); let i = index"
[entity]="entity"
[slot]="i + 1"
></m-newsfeed__entity>
</ng-template>
......
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Input, OnInit, Output, EventEmitter, ViewChild } from "@angular/core";
import {
Component,
ChangeDetectionStrategy,
ChangeDetectorRef,
Input,
OnInit,
Output,
EventEmitter,
ViewChild,
SkipSelf, Injector
} from "@angular/core";
import { FeedsService } from "../../../common/services/feeds.service";
import { Session } from "../../../services/session";
import { PosterComponent } from "../../newsfeed/poster/poster.component";
import { SortedService } from "./sorted.service";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
selector: 'm-channel--sorted',
providers: [SortedService],
providers: [SortedService, ClientMetaService],
templateUrl: 'sorted.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
......@@ -55,8 +66,14 @@ export class ChannelSortedComponent implements OnInit {
protected feedsService: FeedsService,
protected service: SortedService,
protected session: Session,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
protected cd: ChangeDetectorRef,
) {
this.clientMetaService
.inherit(injector)
.setSource('feed/channel')
.setMedium('feed');
}
ngOnInit() {
......
import { Component, OnDestroy, OnInit } from "@angular/core";
import { Component, Injector, OnDestroy, OnInit, SkipSelf } from "@angular/core";
import { GroupsService } from "../../groups-service";
import { Subscription } from "rxjs";
import { ActivatedRoute } from "@angular/router";
import { ClientMetaService } from "../../../../common/services/client-meta.service";
@Component({
selector: 'm-group-profile__feed',
templateUrl: 'feed.component.html'
providers: [ ClientMetaService ],
templateUrl: 'feed.component.html',
})
export class GroupProfileFeedComponent implements OnInit, OnDestroy {
group: any;
......@@ -17,7 +19,13 @@ export class GroupProfileFeedComponent implements OnInit, OnDestroy {
constructor(
protected service: GroupsService,
protected route: ActivatedRoute,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.clientMetaService
.inherit(injector)
.setSource('feed/group')
.setMedium('feed');
}
ngOnInit() {
......
......@@ -26,11 +26,12 @@
<div class="minds-list" [class.m-groupProfileFeed__mediaList]="filter !== 'activity'">
<minds-activity
*ngFor="let activity of pinned"
*ngFor="let activity of pinned; let i = index"
[object]="activity"
[canDelete]="group['is:owner'] || group['is:moderator']"
(delete)="delete(activity)"
[showRatingToggle]="true"
[slot]="i + 1"
class="mdl-card item">
</minds-activity>
......@@ -40,6 +41,7 @@
[object]="a"
[canDelete]="group['is:owner'] || group['is:moderator']"
(delete)="delete(a)"
[slot]="i + pinned.length + 1"
>
<!-- Menu Actions -->
<li post-menu
......
......@@ -41,6 +41,7 @@
[object]="entity"
[canDelete]="group['is:owner'] || group['is:moderator']"
(delete)="delete(entity)"
[slot]="i + 1"
>
<!-- Menu Actions -->
......
......@@ -3,7 +3,6 @@ import { debounceTime } from "rxjs/operators";
import { Subject, Subscription } from "rxjs";
import { ScrollService } from "../../../../../services/ux/scroll";
import { NewsfeedService } from "../../../../newsfeed/services/newsfeed.service";
@Injectable()
export class ActivityAnalyticsOnViewService implements OnDestroy {
......@@ -20,13 +19,12 @@ export class ActivityAnalyticsOnViewService implements OnDestroy {
protected visible: boolean = false;
protected onViewFn: () => void;
protected onViewFn: (entity) => void;
protected enabled: boolean = true;
constructor(
protected scroll: ScrollService,
protected newsfeedService: NewsfeedService,
) {
this.init();
}
......@@ -41,7 +39,7 @@ export class ActivityAnalyticsOnViewService implements OnDestroy {
return this;
}
onView(fn: () => void) {
onView(fn: (entity) => void) {
this.onViewFn = fn;
return this;
}
......@@ -57,10 +55,11 @@ export class ActivityAnalyticsOnViewService implements OnDestroy {
.subscribe(() => {
if (this.entity && this.visible) {
this.scroll.unListen(this.scroll$);
this.newsfeedService.recordView(this.entity);
if (this.onViewFn) {
this.onViewFn();
this.onViewFn(this.entity);
} else {
console.warn('Missing onView handler for Activity');
}
}
});
......
......@@ -35,6 +35,8 @@ import { IfFeatureDirective } from '../../../../../common/directives/if-feature.
import { NSFWSelectorConsumerService } from '../../../../../common/components/nsfw-selector/nsfw-selector.service';
import { FeaturesService } from '../../../../../services/features.service';
import { BlockListService } from "../../../../../common/services/block-list.service";
import { ClientMetaService } from "../../../../../common/services/client-meta.service";
import { clientMetaServiceMock } from "../../../../../../tests/client-meta-service-mock.spec";
/* tslint:disable */
// START MOCKS
......@@ -482,6 +484,7 @@ describe('Activity', () => {
{ provide: TranslationService, useValue: translationServiceMock },
{ provide: OverlayModalService, useValue: overlayModalServiceMock },
{ provide: EntitiesService, useValue: entitiesServiceMock },
{ provide: ClientMetaService, useValue: clientMetaServiceMock },
{
provide: NSFWSelectorConsumerService,
useValue: NSFWSelectorServiceMock,
......
......@@ -6,7 +6,9 @@ import {
ElementRef,
Input,
ViewChild,
OnInit
OnInit,
SkipSelf,
Injector,
} from '@angular/core';
import { Client } from '../../../../../services/api';
......@@ -21,6 +23,8 @@ import { EntitiesService } from "../../../../../common/services/entities.service
import { Router } from "@angular/router";
import { BlockListService } from "../../../../../common/services/block-list.service";
import { ActivityAnalyticsOnViewService } from "./activity-analytics-on-view.service";
import { NewsfeedService } from "../../../../newsfeed/services/newsfeed.service";
import { ClientMetaService } from "../../../../../common/services/client-meta.service";
@Component({
moduleId: module.id,
......@@ -30,7 +34,7 @@ import { ActivityAnalyticsOnViewService } from "./activity-analytics-on-view.ser
},
inputs: ['object', 'commentsToggle', 'focusedCommentGuid', 'visible', 'canDelete', 'showRatingToggle'],
outputs: ['_delete: delete', 'commentsOpened', 'onViewed'],
providers: [ActivityAnalyticsOnViewService],
providers: [ ClientMetaService, ActivityAnalyticsOnViewService ],
templateUrl: 'activity.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
......@@ -50,6 +54,7 @@ export class Activity implements OnInit {
@Input() boost: boolean = false;
@Input('boost-toggle')
@Input() showBoostMenuOptions: boolean = false;
@Input() slot: number = -1;
visibilityEvents: boolean = true;
@Input('visibilityEvents') set _visibilityEvents(visibilityEvents: boolean) {
......@@ -106,12 +111,23 @@ export class Activity implements OnInit {
private router: Router,
protected blockListService: BlockListService,
protected activityAnalyticsOnViewService: ActivityAnalyticsOnViewService,
protected newsfeedService: NewsfeedService,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
elementRef: ElementRef,
) {
this.clientMetaService
.inherit(injector);
this.activityAnalyticsOnViewService
.setElementRef(elementRef)
.onView(() => {
this.onViewed.emit({activity: this.activity, visible: true});
.onView(activity => {
this.newsfeedService.recordView(activity, true, null, this.clientMetaService.build({
campaign: activity.boosted_guid ? activity.urn : '',
position: this.slot,
}));
this.onViewed.emit({ activity: activity, visible: true });
});
}
......
......@@ -30,6 +30,7 @@
visible="true"
[hidden]="i != currentPosition"
[showBoostMenuOptions]="true"
[slot]="i + 1"
[visibilityEvents]="false"
#activities
></minds-activity>
......
import { ChangeDetectorRef, Component, ElementRef, QueryList, ViewChildren } from '@angular/core';
import { ChangeDetectorRef, Component, ElementRef, Injector, QueryList, SkipSelf, ViewChildren } from '@angular/core';
import { ScrollService } from '../../../services/ux/scroll';
import { Client } from '../../../services/api';
......@@ -12,6 +12,7 @@ import { NewsfeedBoostService } from '../newsfeed-boost.service';
import { SettingsService } from '../../settings/settings.service';
import { FeaturesService } from "../../../services/features.service";
import { BoostedContentService } from "../../../common/services/boosted-content.service";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
moduleId: module.id,
......@@ -23,7 +24,8 @@ import { BoostedContentService } from "../../../common/services/boosted-content.
'(mouseout)': 'mouseOut()'
},
inputs: ['interval', 'channel'],
templateUrl: 'boost-rotator.component.html'
providers: [ ClientMetaService ],
templateUrl: 'boost-rotator.component.html',
})
export class NewsfeedBoostRotatorComponent {
......@@ -65,6 +67,8 @@ export class NewsfeedBoostRotatorComponent {
private cd: ChangeDetectorRef,
protected featuresService: FeaturesService,
protected boostedContentService: BoostedContentService,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.subscriptions = [
......@@ -74,7 +78,9 @@ export class NewsfeedBoostRotatorComponent {
this.service.explicitChanged.subscribe((event) => this.onExplicitChanged(event))
];
this.clientMetaService
.inherit(injector)
.setMedium('boost-rotator');
}
ngOnInit() {
......@@ -244,7 +250,11 @@ export class NewsfeedBoostRotatorComponent {
recordImpression(position: number, force: boolean) {
//ensure was seen for at least 1 second
if ((Date.now() > this.lastTs + 1000 || force) && this.boosts[position].boosted_guid) {
this.newsfeedService.recordView(this.boosts[position], true, this.channel);
this.newsfeedService.recordView(this.boosts[position], true, this.channel, this.clientMetaService.build({
position: position + 1,
campaign: this.boosts[position].urn,
}));
console.log('Boost rotator recording impressions for ' + position + ' ' + this.boosts[position].boosted_guid, this.windowFocused);
}
this.lastTs = Date.now();
......
<div class="minds-list">
<m-newsfeed--boost-rotator interval="12" *ngIf="showBoostRotator"></m-newsfeed--boost-rotator>
<minds-activity *ngFor="let activity of newsfeed" [object]="activity" [boostToggle]="activity.boostToggle" [boost]="boostFeed" [showBoostMenuOptions]="boostFeed" (delete)="delete(activity)" class="mdl-card m-border item"></minds-activity>
<minds-activity *ngFor="let activity of newsfeed; let i = index" [object]="activity" [boostToggle]="activity.boostToggle" [boost]="boostFeed" [showBoostMenuOptions]="boostFeed" (delete)="delete(activity)" [slot]="i + 1" class="mdl-card m-border item"></minds-activity>
<infinite-scroll
distance="25%"
(load)="load()"
[moreData]="moreData"
[inProgress]="inProgress">
</infinite-scroll>
</div>
\ No newline at end of file
</div>
......@@ -12,6 +12,7 @@
[boostToggle]="entity.boostToggle"
(delete)="delete(entity)"
[showRatingToggle]="true"
[slot]="slot"
class="mdl-card m-border item"
></minds-activity>
</ng-container>
......
......@@ -37,6 +37,8 @@ export class NewsfeedEntityComponent {
return type === 'user' ? ChannelsTileComponent : GroupsTileComponent;
}
@Input() slot: number;
// Clear the view container
clear() {
this.cd.detectChanges();
......
......@@ -25,11 +25,13 @@
<ng-container *ngIf="isActivityFeed()">
<m-featured-content
*ngIf="shouldShowBoost(i)"
[slot]="i + 1"
></m-featured-content>
</ng-container>
<m-newsfeed__entity
[entity]="entity"
[slot]="i + 1"
></m-newsfeed__entity>
</ng-container>
......
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Component, Injector, OnDestroy, OnInit, SkipSelf, ViewChild } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
......@@ -17,10 +17,12 @@ import { TopbarHashtagsService } from "../../hashtags/service/topbar.service";
import { NewsfeedHashtagSelectorService } from "../services/newsfeed-hashtag-selector.service";
import { FeedsService } from "../../../common/services/feeds.service";
import { FeaturesService } from "../../../services/features.service";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
selector: 'm-newsfeed--sorted',
templateUrl: 'sorted.component.html'
providers: [ ClientMetaService ],
templateUrl: 'sorted.component.html',
})
export class NewsfeedSortedComponent implements OnInit, OnDestroy {
......@@ -63,9 +65,16 @@ export class NewsfeedSortedComponent implements OnInit, OnDestroy {
protected newsfeedHashtagSelectorService: NewsfeedHashtagSelectorService,
protected feedsService: FeedsService,
protected featuresService: FeaturesService,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.title.setTitle('Newsfeed');
this.clientMetaService
.inherit(injector)
.setSource('feed/discovery')
.setMedium('feed');
if (this.session.isLoggedIn()) {
this.rating = this.session.getLoggedInUser().boost_rating;
}
......
......@@ -12,6 +12,7 @@
<ng-container *mIfFeature="'es-feeds'">
<m-featured-content
*ngIf="(i > 0 && (i % 8) === 0 && i <= 40) || i === 2"
[slot]="i + 1"
></m-featured-content>
</ng-container>
......@@ -21,6 +22,7 @@
[boostToggle]="activity.boostToggle"
(delete)="delete(activity)"
[showRatingToggle]="true"
[slot]="i + 1"
></minds-activity>
</ng-container>
......
import { Component, ViewChild } from '@angular/core';
import { Component, Injector, SkipSelf, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
......@@ -15,10 +15,12 @@ import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { FeaturesService } from "../../../services/features.service";
import { FeedsService } from "../../../common/services/feeds.service";
import { NewsfeedService } from "../services/newsfeed.service";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
selector: 'm-newsfeed--subscribed',
templateUrl: 'subscribed.component.html'
providers: [ ClientMetaService ],
templateUrl: 'subscribed.component.html',
})
export class NewsfeedSubscribedComponent {
......@@ -61,8 +63,15 @@ export class NewsfeedSubscribedComponent {
protected featuresService: FeaturesService,
protected feedsService: FeedsService,
protected newsfeedService: NewsfeedService,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.title.setTitle('Newsfeed');
this.clientMetaService
.inherit(injector)
.setSource('feed/subscribed')
.setMedium('feed');
}
ngOnInit() {
......
<div class="minds-list">
<minds-activity *ngFor="let activity of newsfeed" [object]="activity" [boostToggle]="activity.boostToggle"
(delete)="delete(activity)" [showRatingToggle]="true" class="mdl-card m-border item"></minds-activity>
<minds-activity *ngFor="let activity of newsfeed; let i = index" [object]="activity" [boostToggle]="activity.boostToggle"
(delete)="delete(activity)" [showRatingToggle]="true" class="mdl-card m-border item" [slot]="i + 1"></minds-activity>
<infinite-scroll
distance="25%"
(load)="load()"
[moreData]="moreData"
[inProgress]="inProgress">
</infinite-scroll>
</div>
\ No newline at end of file
</div>
<div class="minds-list">
<minds-newsfeed-poster (load)="prepend($event)"></minds-newsfeed-poster>
<minds-activity *ngFor="let activity of newsfeed" [object]="activity" [boostToggle]="activity.boostToggle" (delete)="delete(activity)" [showRatingToggle]="true" class="mdl-card m-border item"></minds-activity>
<minds-activity *ngFor="let activity of newsfeed; let i = index" [object]="activity" [boostToggle]="activity.boostToggle" (delete)="delete(activity)" [showRatingToggle]="true" [slot]="i + 1" class="mdl-card m-border item"></minds-activity>
<infinite-scroll
distance="25%"
(load)="load()"
......
......@@ -21,7 +21,7 @@ export class NewsfeedService {
.map(reason => reason.value);
}
public async recordView(entity, visible: boolean = true, channel = null) {
public async recordView(entity, visible: boolean = true, channel = null, clientMeta = {}) {
if (!this.session.isLoggedIn()) {
return;
}
......@@ -36,10 +36,14 @@ export class NewsfeedService {
if (!visible)
url += `/stop`;
return await this.client.post(url);
return await this.client.post(url, {
client_meta: clientMeta,
});
}
return await this.client.post(`api/v2/analytics/views/activity/${entity.guid}`);
return await this.client.post(`api/v2/analytics/views/activity/${entity.guid}`, {
client_meta: clientMeta,
});
}
public reloadFeed(allHashtags: boolean = false) {
......
......@@ -23,6 +23,7 @@
[focusedCommentGuid]="focusedCommentGuid"
(delete)="delete(activity)"
[showRatingToggle]="true"
[slot]="1"
class="mdl-card mdl-shadow--2dp item"
>
</minds-activity>
......
import { Component } from '@angular/core';
import { Component, Injector, SkipSelf } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
......@@ -8,9 +8,11 @@ import { ContextService } from '../../../services/context.service';
import { EntitiesService } from "../../../common/services/entities.service";
import { Client } from "../../../services/api/client";
import { FeaturesService } from "../../../services/features.service";
import { ClientMetaService } from "../../../common/services/client-meta.service";
@Component({
selector: 'm-newsfeed--single',
providers: [ ClientMetaService ],
templateUrl: 'single.component.html'
})
......@@ -32,7 +34,13 @@ export class NewsfeedSingleComponent {
public entitiesService: EntitiesService,
protected client: Client,
protected featuresService: FeaturesService,
protected clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector,
) {
this.clientMetaService
.inherit(injector)
.setSource('single')
.setMedium('single');
}
ngOnInit() {
......
export const clientMetaServiceMock = new function() {
this.source = null;
this.timestamp = null;
this.salt = null;
this.medium = null;
this.campaign = null;
this.id = null;
this.injector = null;
this.inherit = jasmine.createSpy('inherit').and.callFake(() => this);
this.getId = jasmine.createSpy('getId').and.callFake(() => this.id);
this.setSource = jasmine.createSpy('setSource').and.callFake(source => this);
this.getSource = jasmine.createSpy('getSource').and.callFake(() => this.source);
this.getTimestamp = jasmine.createSpy('getTimestamp').and.callFake(() => this.timestamp);
this.getSalt = jasmine.createSpy('getSalt').and.callFake(() => this.salt);
this.buildDelta = jasmine.createSpy('buildDelta').and.callFake(() => this);
this.setMedium = jasmine.createSpy('setMedium').and.callFake(() => this);
this.getMedium = jasmine.createSpy('getMedium').and.callFake(() => this.medium);
this.setCampaign = jasmine.createSpy('setCampaign').and.callFake(() => this);
this.getCampaign = jasmine.createSpy('getCampaign').and.callFake(() => this.campaign);
this.buildPageToken = jasmine.createSpy('buildPageToken').and.callFake(() => this);
this.build = jasmine.createSpy('build').and.callFake(() => ({}));
};