...
 
Commits (4)
......@@ -21,6 +21,8 @@ Options (* indicates it is required):"
*\-p ,\--password \<Parameter>\ The password of the user.
\-h ,\--url \<Parameter>\ The URL of the host e.g. https://www.minds.com/ - defaults to use localhost.
\-u ,\--username \<Parameter>\ The username - defaults to cypress_e2e_test.
\-pu ,\--pro_username \<Parameter>\ The pro users username.
\-pp ,\--pro_password \<Parameter>\ The pro users password
\-v ,\---video \<Parameter>\ true if you want video providing.
\-e, \--env \<Parameter>\ add additional env variables e.g. production=true
"
......@@ -54,6 +56,8 @@ POSITIONAL=()
# set default arguments
url="http://localhost"
username="minds_cypress_tests"
pro_username="minds_cypress_tests_pro"
pro_password="123123213"
env=""
_video=false
while [[ $# -gt 0 ]]
......@@ -77,6 +81,14 @@ case $key in
_video="$2"
shift 2
;;
-pu|--pro-username)
pro_username="$2"
shift 2
;;
-pp|--pro-password)
pro_password="$2"
shift 2
;;
-e|--env)
env=",$2"
shift 2
......@@ -108,5 +120,5 @@ init_args $@
# while [[ $PWD != '/' && ${PWD##*/} != 'front' ]]; do cd ..; done
#run cypress with args.
echo $(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password$env $POSITIONAL
$(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password$env $POSITIONAL
echo $(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password,pro_username=$pro_username,pro_password=$pro_password$env $POSITIONAL
$(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password,pro_username=$pro_username,pro_password=$pro_password$env $POSITIONAL
......@@ -2,6 +2,7 @@ import { Injectable, Injector } from '@angular/core';
import { Location } from '@angular/common';
import hashCode from '../../helpers/hash-code';
import { Session } from '../../services/session';
import { Client } from '../../services/api';
let uniqId = 0;
......@@ -23,7 +24,11 @@ export class ClientMetaService {
protected inherited: boolean = false;
constructor(protected location: Location, protected session: Session) {
constructor(
protected location: Location,
protected session: Session,
protected client: Client
) {
this.id = ++uniqId;
this.timestamp = Date.now();
......@@ -146,6 +151,12 @@ export class ClientMetaService {
};
}
async recordView(entity) {
await this.client.post('api/v2/analytics/views/entity/' + entity.guid, {
client_meta: this.build(),
});
}
protected checkInheritance() {
if (!this.inherited) {
console.warn(
......
......@@ -6,6 +6,8 @@ import {
OnDestroy,
OnInit,
ViewChild,
Injector,
SkipSelf,
} from '@angular/core';
import { Router } from '@angular/router';
......@@ -22,6 +24,7 @@ import { optimizedResize } from '../../../utils/optimized-resize';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { ActivityService } from '../../../common/services/activity.service';
import { ShareModalComponent } from '../../../modules/modals/share/share';
import { ClientMetaService } from '../../../common/services/client-meta.service';
@Component({
moduleId: module.id,
......@@ -30,7 +33,7 @@ import { ShareModalComponent } from '../../../modules/modals/share/share';
class: 'm-blog',
},
templateUrl: 'view.html',
providers: [ActivityService],
providers: [ActivityService, ClientMetaService],
})
export class BlogView implements OnInit, OnDestroy {
minds;
......@@ -98,8 +101,15 @@ export class BlogView implements OnInit, OnDestroy {
public analyticsService: AnalyticsService,
protected activityService: ActivityService,
private cd: ChangeDetectorRef,
private overlayModal: OverlayModalService
private overlayModal: OverlayModalService,
private clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector
) {
this.clientMetaService
.inherit(injector)
.setSource('single')
.setMedium('single');
this.minds = window.Minds;
this.element = _element.nativeElement;
optimizedResize.add(this.onResize.bind(this));
......@@ -108,6 +118,7 @@ export class BlogView implements OnInit, OnDestroy {
ngOnInit() {
this.isVisible();
this.context.set('object:blog');
this.clientMetaService.recordView(this.blog);
}
isVisible() {
......
<ng-container *ngIf="channel; else loader">
<ng-container *ngIf="error || channel; else loader">
<ng-container
*ngIf="!proEnabled || !channel.pro || isOwner || isAdmin; else isProChannel"
*ngIf="
error || !proEnabled || !channel.pro || isOwner || isAdmin;
else isProChannel
"
>
<m-channel #channelComponent></m-channel>
</ng-container>
......
......@@ -23,6 +23,7 @@ import { FeaturesService } from '../../services/features.service';
})
export class ChannelContainerComponent implements OnInit, OnDestroy {
inProgress: boolean = false;
error: string;
channel: MindsUser;
......@@ -100,6 +101,7 @@ export class ChannelContainerComponent implements OnInit, OnDestroy {
});
}
} catch (e) {
this.error = e.message;
console.error(e);
}
......
......@@ -37,6 +37,8 @@ import { FeaturesService } from '../../services/features.service';
import { featuresServiceMock } from '../../../tests/features-service-mock.spec';
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';
describe('ChannelComponent', () => {
let comp: ChannelComponent;
......@@ -105,6 +107,7 @@ describe('ChannelComponent', () => {
},
{ provide: FeaturesService, useValue: featuresServiceMock },
{ provide: BlockListService, useValue: MockService(BlockListService) },
{ provide: ClientMetaService, useValue: clientMetaServiceMock },
],
}).compileComponents(); // compile template and css
}));
......
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, SkipSelf, Injector } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
......@@ -17,11 +17,13 @@ import { Observable } from 'rxjs';
import { DialogService } from '../../common/services/confirm-leave-dialog.service';
import { BlockListService } from '../../common/services/block-list.service';
import { ChannelSortedComponent } from './sorted/sorted.component';
import { ClientMetaService } from '../../common/services/client-meta.service';
@Component({
moduleId: module.id,
selector: 'm-channel',
templateUrl: 'channel.component.html',
providers: [ClientMetaService],
})
export class ChannelComponent {
minds = window.Minds;
......@@ -53,8 +55,15 @@ export class ChannelComponent {
private recent: RecentService,
private context: ContextService,
private dialogService: DialogService,
private blockListService: BlockListService
) {}
private blockListService: BlockListService,
private clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector
) {
this.clientMetaService
.inherit(injector)
.setSource('single')
.setMedium('single');
}
ngOnInit() {
this.title.setTitle('Channel');
......@@ -132,6 +141,8 @@ export class ChannelComponent {
if (this.session.getLoggedInUser()) {
this.addRecent();
}
this.clientMetaService.recordView(this.user);
})
.catch(e => {
if (e.status === 0) {
......
......@@ -62,33 +62,37 @@ export class ActivityAnalyticsOnViewService implements OnDestroy {
});
this.scroll$ = this.scroll.listenForView().subscribe(() => {
if (!this.element) {
console.warn('Missing element ref');
return;
}
if (!this.element.offsetHeight || !this.enabled) {
return;
}
const top = this.element.offsetTop;
const bottom = top + this.element.offsetHeight;
const vpTop = this.scroll.view.scrollTop;
const vpBottom = vpTop + this.scroll.view.clientHeight;
const totalH = Math.max(bottom, vpBottom) - Math.min(top, vpTop);
const vpComp = totalH - this.scroll.view.clientHeight;
const vpEl = this.element.offsetHeight - vpComp;
const visible = vpEl <= 0 ? 0 : vpEl / this.element.offsetHeight;
if (visible > 0 && !this.visible) {
this.visible = true;
this.visibilitySubject.next(this.visible);
} else {
this.visible = false;
}
this.checkVisibility();
});
}
checkVisibility() {
if (!this.element) {
console.warn('Missing element ref');
return;
}
if (!this.element.offsetHeight || !this.enabled) {
return;
}
const top = this.element.offsetTop;
const bottom = top + this.element.offsetHeight;
const vpTop = this.scroll.view.scrollTop;
const vpBottom = vpTop + this.scroll.view.clientHeight;
const totalH = Math.max(bottom, vpBottom) - Math.min(top, vpTop);
const vpComp = totalH - this.scroll.view.clientHeight;
const vpEl = this.element.offsetHeight - vpComp;
const visible = vpEl <= 0 ? 0 : vpEl / this.element.offsetHeight;
if (visible > 0 && !this.visible) {
this.visible = true;
this.visibilitySubject.next(this.visible);
} else {
this.visible = false;
}
}
ngOnDestroy() {
this.scroll.unListen(this.scroll$);
......
......@@ -239,6 +239,8 @@ export class Activity implements OnInit {
this.activity.time_created || Math.floor(Date.now() / 1000);
this.allowComments = this.activity.allow_comments;
this.activityAnalyticsOnViewService.checkVisibility(); // perform check
}
getOwnerIconTime() {
......
......@@ -5,6 +5,8 @@ import {
OnDestroy,
OnInit,
ViewChild,
SkipSelf,
Injector,
} from '@angular/core';
import { Location } from '@angular/common';
import { Event, NavigationStart, Router } from '@angular/router';
......@@ -23,6 +25,7 @@ import { MindsVideoComponent } from '../components/video/video.component';
import isMobileOrTablet from '../../../helpers/is-mobile-or-tablet';
import { ActivityService } from '../../../common/services/activity.service';
import { SiteService } from '../../../common/services/site.service';
import { ClientMetaService } from '../../../common/services/client-meta.service';
export type MediaModalParams = {
redirectUrl?: string;
......@@ -58,7 +61,7 @@ export type MediaModalParams = {
transition(':leave', [animate('300ms', style({ opacity: 0 }))]),
]),
],
providers: [ActivityService],
providers: [ActivityService, ClientMetaService],
})
export class MediaModalComponent implements OnInit, OnDestroy {
minds = window.Minds;
......@@ -120,8 +123,15 @@ export class MediaModalComponent implements OnInit, OnDestroy {
private overlayModal: OverlayModalService,
private router: Router,
private location: Location,
private site: SiteService
) {}
private site: SiteService,
private clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector
) {
this.clientMetaService
.inherit(injector)
.setSource('single')
.setMedium('modal');
}
ngOnInit() {
// Prevent dismissal of modal when it's just been opened
......@@ -212,6 +222,7 @@ export class MediaModalComponent implements OnInit, OnDestroy {
url = `/pro/${this.site.pro.user_guid}${url}`;
}
this.clientMetaService.recordView(this.entity);
this.analyticsService.send('pageview', {
url,
});
......
import { ChangeDetectorRef, Component, OnInit, OnDestroy } from '@angular/core';
import {
ChangeDetectorRef,
Component,
OnInit,
OnDestroy,
SkipSelf,
Injector,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
......@@ -11,6 +18,8 @@ import { AttachmentService } from '../../../services/attachment';
import { ContextService } from '../../../services/context.service';
import { MindsTitle } from '../../../services/ux/title';
import { ActivityService } from '../../../common/services/activity.service';
import { AnalyticsService } from '../../../services/analytics';
import { ClientMetaService } from '../../../common/services/client-meta.service';
@Component({
moduleId: module.id,
......@@ -23,6 +32,7 @@ import { ActivityService } from '../../../common/services/activity.service';
deps: [Client],
},
ActivityService,
ClientMetaService,
],
})
export class MediaViewComponent implements OnInit, OnDestroy {
......@@ -63,8 +73,15 @@ export class MediaViewComponent implements OnInit, OnDestroy {
public attachment: AttachmentService,
public context: ContextService,
private cd: ChangeDetectorRef,
protected activityService: ActivityService
) {}
protected activityService: ActivityService,
private clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector
) {
this.clientMetaService
.inherit(injector)
.setSource('single')
.setMedium('single');
}
ngOnInit() {
this.title.setTitle('');
......@@ -125,6 +142,8 @@ export class MediaViewComponent implements OnInit, OnDestroy {
}
}
this.clientMetaService.recordView(this.entity);
this.detectChanges();
})
.catch(e => {
......