feat(demo): demo version additions

This commit is contained in:
Dmitry Nehaychik 2018-06-21 17:09:29 +03:00 committed by Sergey Andrievskiy
parent d3238ddb49
commit 93d800b676
14 changed files with 253 additions and 29 deletions

View file

@ -21,6 +21,7 @@
"src/assets",
"src/favicon.ico",
"src/favicon.png",
"src/google46533d2e7a851062.html",
{
"glob": "**/*",
"input": "node_modules/leaflet/dist/images",
@ -122,6 +123,7 @@
"src/assets",
"src/favicon.ico",
"src/favicon.png",
"src/google46533d2e7a851062.html",
{
"glob": "**/*",
"input": "node_modules/leaflet/dist/images",

View file

@ -51,6 +51,7 @@ import { StatsProgressBarService } from './mock/stats-progress-bar.service';
import { VisitorsAnalyticsService } from './mock/visitors-analytics.service';
import { SecurityCamerasService } from './mock/security-cameras.service';
import { MockDataModule } from './mock/mock-data.module';
import { AbService } from './utils/ab.service';
const socialLinks = [
{
@ -141,6 +142,7 @@ export const NB_CORE_PROVIDERS = [
LayoutService,
PlayerService,
StateService,
AbService,
];
@NgModule({

View file

@ -0,0 +1,43 @@
import { Injectable } from '@angular/core';
import { fromEvent as observableFromEvent } from 'rxjs/observable/fromEvent';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { filter } from 'rxjs/operators/filter';
@Injectable()
export class AbService {
static readonly VARIANT_THEME_DEFAULT = 'theme-change-default';
static readonly VARIANT_THEME_COSMIC = 'theme-change-cosmic';
static readonly VARIANT_THEME_CORPORATE = 'theme-change-corporate';
static readonly VARIANT_HIGHLIGHT_HIRE = 'highlight-hire';
static readonly VARIANT_DEVELOPERS_HIRE = 'developers-hire';
static readonly VARIANT_SOLUTION_HIRE = 'solution-hire';
// static readonly VARIANT_BANNER_HIRE = 'banner-hire';
private static readonly EVENT_NAME = 'ab-variant';
private static readonly AB_ENABLED = true;
private events$ = new BehaviorSubject<{ name: string }>(null);
constructor() {
if (AbService.AB_ENABLED) {
observableFromEvent<any>(document, AbService.EVENT_NAME)
.subscribe((e: { detail: any }) => {
if (e && e.detail) {
this.events$.next(e.detail);
}
});
}
}
onAbEvent(name: string = ''): Observable<{ name: string }> {
return this.events$.asObservable()
.pipe(
filter(e => !!(e && e.name)),
filter(e => name ? e.name === name : true),
);
}
}

View file

@ -1,16 +1,19 @@
import { Injectable } from '@angular/core';
import { Inject, Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Location } from '@angular/common';
import { filter } from 'rxjs/operators';
import { NB_WINDOW } from '@nebular/theme';
declare const ga: any;
@Injectable()
export class AnalyticsService {
private enabled: boolean;
private enabled = false;
constructor(private location: Location, private router: Router) {
this.enabled = false;
constructor(@Inject(NB_WINDOW) private window,
private location: Location,
private router: Router) {
this.enabled = this.window.location.href.indexOf('akveo.com') >= 0;
}
trackPageViews() {
@ -24,9 +27,9 @@ export class AnalyticsService {
}
}
trackEvent(eventName: string) {
trackEvent(eventName: string, eventVal: string = '') {
if (this.enabled) {
ga('send', 'event', eventName);
ga('send', 'event', eventName, eventVal);
}
}
}

View file

@ -4,12 +4,21 @@ import { Component } from '@angular/core';
selector: 'ngx-footer',
styleUrls: ['./footer.component.scss'],
template: `
<span class="created-by">Created with by <b><a href="https://akveo.com" target="_blank">Akveo</a></b> 2017</span>
<span class="created-by">
Created with by <b><a href="http://akveo.com?utm_source=ngx-admin-demo&utm_medium=footer"
target="_blank">Akveo</a></b> 2018.
Made with
<b>
<a href="https://akveo.github.io/nebular/?utm_source=ngx-admin&utm_medium=footer_link" target="_blank">
Nebular.
</a>
</b>
</span>
<div class="socials">
<a href="#" target="_blank" class="ion ion-social-github"></a>
<a href="#" target="_blank" class="ion ion-social-facebook"></a>
<a href="#" target="_blank" class="ion ion-social-twitter"></a>
<a href="#" target="_blank" class="ion ion-social-linkedin"></a>
<a href="https://github.com/akveo/ngx-admin" target="_blank" class="ion ion-social-github"></a>
<a href="https://www.facebook.com/akveo/" target="_blank" class="ion ion-social-facebook"></a>
<a href="https://twitter.com/akveo_inc" target="_blank" class="ion ion-social-twitter"></a>
<a href="https://www.linkedin.com/company/akveo" target="_blank" class="ion ion-social-linkedin"></a>
</div>
`,
})

View file

@ -17,10 +17,25 @@
<nb-action *nbIsGranted="['view', 'user']" >
<nb-user [nbContextMenu]="userMenu" [name]="user?.name" [picture]="user?.picture"></nb-user>
</nb-action>
<nb-action class="control-item" disabled icon="nb-notifications"></nb-action>
<nb-action class="control-item" icon="nb-email"></nb-action>
<nb-action class="control-item">
<nb-action class="control-item notifications" disabled icon="nb-notifications"></nb-action>
<nb-action class="control-item email" icon="nb-email"></nb-action>
<nb-action class="control-item search">
<nb-search type="rotate-layout" (click)="startSearch()"></nb-search>
</nb-action>
</nb-actions>
<nb-action class="control-item github-start">
<iframe src="https://ghbtns.com/github-btn.html?user=akveo&repo=ngx-admin&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe>
</nb-action>
<nb-action class="control-item email-text" *ngIf="!hireTextVariant">
<strong>Need some help? <a (click)="trackEmailClick()" href="mailto:contact@akveo.com">contact@akveo.com</a></strong>
</nb-action>
<nb-action class="control-item email-text text-success" *ngIf="hireTextVariant === 'highlight-hire'">
<strong>Need some help? <a (click)="trackEmailClick()" href="mailto:contact@akveo.com">contact@akveo.com</a></strong>
</nb-action>
<nb-action class="control-item email-text text-success" *ngIf="hireTextVariant === 'developers-hire'">
<strong>Looking for developers for your project? <a (click)="trackEmailClick()" href="mailto:contact@akveo.com">contact@akveo.com</a></strong>
</nb-action>
<nb-action class="control-item email-text text-success" *ngIf="hireTextVariant === 'solution-hire'">
<strong>Need a custom solution? <a (click)="trackEmailClick()" href="mailto:contact@akveo.com">contact@akveo.com</a></strong>
</nb-action>
</nb-actions>
</div>

View file

@ -12,10 +12,12 @@
width: 100%;
order: 0;
flex-direction: row;
flex: 1;
}
.right {
order: 1;
flex-direction: row-reverse;
flex: 1.5;
}
.logo-containter {
@ -26,6 +28,22 @@
.control-item {
display: block;
&.email-text {
height: auto;
a {
text-decoration: underline;
}
}
&.github-start {
width: 140px;
display: flex;
iframe {
width: 100px;
}
}
}
.header-container {
@ -153,6 +171,19 @@
}
}
@include media-breakpoint-down(xl) {
.control-item.email, .control-item.notifications {
display: none;
}
}
@include media-breakpoint-down(lg) {
.control-item.search {
display: none;
}
}
@include media-breakpoint-down(md) {
nb-action:not(.toggle-settings) {
@ -181,9 +212,10 @@
nb-user /deep/ .user-name {
display: none;
}
}
@include media-breakpoint-down(is) {
.control-item.github-start {
display: none;
}
.header-container {
.logo {

View file

@ -1,8 +1,11 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { NbMenuService, NbSidebarService } from '@nebular/theme';
import { UserData } from '../../../@core/data/users';
import { AnalyticsService } from '../../../@core/utils';
import { AnalyticsService } from '../../../@core/utils/analytics.service';
import { takeWhile } from 'rxjs/operators/takeWhile';
import { fromEvent as observableFromEvent } from 'rxjs/observable/fromEvent';
import { AbService } from '../../../@core/utils/ab.service';
import { LayoutService } from '../../../@core/utils';
@Component({
@ -10,24 +13,44 @@ import { LayoutService } from '../../../@core/utils';
styleUrls: ['./header.component.scss'],
templateUrl: './header.component.html',
})
export class HeaderComponent implements OnInit {
export class HeaderComponent implements OnInit , OnDestroy {
@Input() position = 'normal';
user: any;
hireTextVariant: string = 'solution-hire';
userMenu = [{ title: 'Profile' }, { title: 'Log out' }];
private alive = true;
constructor(private sidebarService: NbSidebarService,
private menuService: NbMenuService,
private userService: UserData,
private analyticsService: AnalyticsService,
private analytics: AnalyticsService,
private abService: AbService,
private layoutService: LayoutService) {
observableFromEvent(document, 'mouseup')
.pipe(takeWhile(() => this.alive))
.subscribe(() => {
let selection: any;
if (window.getSelection) {
selection = window.getSelection();
} else if ((<any> document).selection) {
selection = (<any> document).selection.createRange();
}
if (selection && selection.toString() === 'contact@akveo.com') {
this.analytics.trackEvent('contactEmail', 'select');
}
});
}
ngOnInit() {
this.userService.getUsers()
.subscribe((users: any) => this.user = users.nick);
this.listenForVariants();
}
toggleSidebar(): boolean {
@ -42,6 +65,29 @@ export class HeaderComponent implements OnInit {
}
startSearch() {
this.analyticsService.trackEvent('startSearch');
this.analytics.trackEvent('startSearch');
}
trackEmailClick() {
this.analytics.trackEvent('contactEmail', 'click');
}
ngOnDestroy() {
this.alive = false;
}
listenForVariants() {
const variants = [
AbService.VARIANT_DEVELOPERS_HIRE,
AbService.VARIANT_HIGHLIGHT_HIRE,
AbService.VARIANT_SOLUTION_HIRE,
];
this.abService.onAbEvent()
.subscribe((e: { name: string }) => {
if (variants.includes(e.name)) {
this.hireTextVariant = e.name;
}
});
}
}

View file

@ -1,6 +1,7 @@
import { Component, OnDestroy, Input } from '@angular/core';
import { NbLayoutDirectionService, NbLayoutDirection } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators';
import { AnalyticsService } from '../../../@core/utils/analytics.service';
@Component({
selector: 'ngx-layout-direction-switcher',
@ -24,7 +25,8 @@ export class LayoutDirectionSwitcherComponent implements OnDestroy {
@Input() vertical: boolean = false;
constructor(private directionService: NbLayoutDirectionService) {
constructor(private directionService: NbLayoutDirectionService,
private analyticsService: AnalyticsService) {
this.currentDirection = this.directionService.getDirection();
this.directionService.onDirectionChange()
@ -34,6 +36,8 @@ export class LayoutDirectionSwitcherComponent implements OnDestroy {
toggleDirection(newDirection) {
this.directionService.setDirection(newDirection);
this.analyticsService.trackEvent('toggleDirection', newDirection);
}
ngOnDestroy() {

View file

@ -26,7 +26,7 @@ import { StateService } from '../../../@core/utils';
responsive
[end]="sidebar.id === 'end'">
<nb-sidebar-header *ngIf="currentTheme !== 'corporate'">
<a href="#" class="btn btn-hero-success main-btn">
<a href="https://github.com/akveo/nebular" target="_blank" class="btn btn-hero-success main-btn">
<i class="ion ion-social-github"></i> <span>Support Us</span>
</a>
</nb-sidebar-header>

View file

@ -4,7 +4,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { NbThemeService } from '@nebular/theme';
import { AnalyticsService } from './@core/utils/analytics.service';
import { AbService } from './@core/utils/ab.service';
import { withLatestFrom, filter } from 'rxjs/operators';
@Component({
selector: 'ngx-app',
@ -12,10 +17,45 @@ import { AnalyticsService } from './@core/utils/analytics.service';
})
export class AppComponent implements OnInit {
constructor(private analytics: AnalyticsService) {
themes = ['default', 'cosmic', 'corporate'];
constructor(private analytics: AnalyticsService,
private activatedRoute: ActivatedRoute,
private abService: AbService,
private themeService: NbThemeService) {
this.themeService.onThemeChange()
.subscribe((theme: any) => {
this.analytics.trackEvent('themeUsed', theme.name);
});
this.activatedRoute.queryParams
.subscribe((params: any) => {
if (params.theme && this.themes.includes(params.theme)) {
this.themeService.changeTheme(params.theme);
}
});
}
ngOnInit(): void {
const variants = [
AbService.VARIANT_THEME_CORPORATE,
AbService.VARIANT_THEME_DEFAULT,
AbService.VARIANT_THEME_CORPORATE,
];
this.analytics.trackPageViews();
this.abService.onAbEvent()
.pipe(
withLatestFrom(this.activatedRoute.queryParams),
filter(([e, params]: [{ name: string }, any]) => !params.theme),
)
.subscribe(([e, params]: [{ name: string }, any]) => {
const themeName = e.name.replace('theme-change-', '');
if (variants.includes(e.name) && this.themes.includes(themeName)) {
this.themeService.changeTheme(themeName);
}
});
}
}

View file

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { MENU_ITEMS } from './pages-menu';
@ -12,7 +12,13 @@ import { MENU_ITEMS } from './pages-menu';
</ngx-sample-layout>
`,
})
export class PagesComponent {
export class PagesComponent implements OnInit {
menu = MENU_ITEMS;
ngOnInit() {
if (window['dataLayer']) {
window['dataLayer'].push({'event': 'optimize.activate'});
}
}
}

View file

@ -0,0 +1 @@
google-site-verification: google46533d2e7a851062.html

View file

@ -2,11 +2,32 @@
<html>
<head>
<meta charset="utf-8">
<title>ngx-admin Demo Application</title>
<title>ngx-admin - Angular 6, Bootstrap 4 Admin dashboard template</title>
<meta name="description" content="Free Angular 6 Bootstrap admin dashboard template.">
<meta name="keywords" content="admin,dashboard,template,angular 6,bootstrap,panel,html,css,javascript">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-N2M4S3J':true});</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-102084081-3', 'auto');
ga('require', 'GTM-N2M4S3J');
</script>
</head>
<body>
<ngx-app>Loading...</ngx-app>