diff --git a/src/app/main/content/apps/apps.module.ts b/src/app/main/content/apps/apps.module.ts index 56d93e17..64434a06 100644 --- a/src/app/main/content/apps/apps.module.ts +++ b/src/app/main/content/apps/apps.module.ts @@ -8,6 +8,10 @@ const routes = [ path : 'dashboards/project', loadChildren: './dashboards/project/project.module#FuseProjectDashboardModule' }, + { + path : 'dashboards/analytics', + loadChildren: './dashboards/analytics/analytics.module#FuseAnalyticsDashboardModule' + }, { path : 'mail', loadChildren: './mail/mail.module#FuseMailModule' diff --git a/src/app/main/content/apps/dashboards/analytics/analytics.component.html b/src/app/main/content/apps/dashboards/analytics/analytics.component.html new file mode 100644 index 00000000..803fdcd2 --- /dev/null +++ b/src/app/main/content/apps/dashboards/analytics/analytics.component.html @@ -0,0 +1,489 @@ +
+ + + +
+ +
+
+ Visitors + Unique visitors by month +
+
+
+ 2015 +
+
+ 2016 +
+
+ 2017 +
+
+
+ +
+ + +
+ +
+ +
+ +
+ +
+ How are your active users trending over time? +
+ +
+ + +
+ +
+ +
+
Conversion
+
+ {{widgets.widget2.conversion.value}} +
+
+ +
+ + {{widgets.widget2.conversion.ofTarget}}% + + + {{widgets.widget2.conversion.ofTarget}}% + + of target +
+ +
+ + +
+ +
+ +
+ + + +
+ +
+ +
+
Impressions
+
+ {{widgets.widget3.impressions.value}} +
+
+ +
+ + {{widgets.widget3.impressions.ofTarget}}% + + + {{widgets.widget3.impressions.ofTarget}}% + + of target +
+ +
+ + +
+ +
+ +
+ + + +
+ +
+ +
+
Visits
+
+ {{widgets.widget4.visits.value}} +
+
+ +
+ + {{widgets.widget4.visits.ofTarget}}% + + + {{widgets.widget4.visits.ofTarget}}% + + of target +
+ +
+ + +
+ +
+ +
+ + +
+ + +
+ How many pages your users visit? +
+ +
+ +
+
+ Visitors & Page views +
+
+
+ Yesterday +
+
+ Today +
+
+
+ +
+ + +
+ +
+ + + +
+ Where are your users? +
+ +
+ + + + + {{marker.label}} + + + + +
+ + + +
+ +
+ +
+ + +
+ What are your top devices? +
+ +
+ +
+
Sessions by device
+
+ +
+ + +
+ +
+ +
+ +
{{device.name}}
+
{{device.value}}%
+ +
+ + arrow_downward + + + + arrow_upward + + +
+ {{device.change}}% +
+
+ +
+ +
+ +
+ +
+ + + Today + Yesterday + Last 7 days + Last 28 days + Last 90 days + + + + +
+ +
+ + + +
+ How are your sales? +
+ +
+ +
+ +
+
+
Sales
+
Lifetime sum of your sales
+
+ +
+ + + + + + + +
+
+ +
+
{{widgets.widget8.today}}
+
+ trending_up + trending_down +
{{widgets.widget8.change.value}} + ({{widgets.widget8.change.percentage}}%) +
+
+
+ +
+ + + +
+ + +
+
+ + +
+ + +
+
+ + +
+ + +
+
+
+ +
+ + + +
+ What are your top campaigns? +
+ +
+ +
+
Top campaigns
+ +
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + +
ClicksConv
{{row.title}}{{row.clicks}}{{row.conversion}}
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ + +
diff --git a/src/app/main/content/apps/dashboards/analytics/analytics.component.scss b/src/app/main/content/apps/dashboards/analytics/analytics.component.scss new file mode 100644 index 00000000..b468e72c --- /dev/null +++ b/src/app/main/content/apps/dashboards/analytics/analytics.component.scss @@ -0,0 +1,64 @@ +#dashboard-analytics { + + /*#widget1 { + + .line-series { + + .line { + stroke-width: 2px; + } + } + + .gridline-path { + + &.gridline-path-horizontal { + stroke: rgba(255, 255, 255, 0.12); + } + + &.gridline-path-vertical { + stroke-width: 0; + } + } + + .tick { + + text { + fill: rgba(255, 255, 255, 0.37) + } + } + + .tooltip-anchor { + fill: rgba(255, 255, 255, 0.54); + } + }*/ + + .main-widget { + display: flex; + flex-direction: column; + } + + .content { + display: flex; + flex: 1 0 auto; + padding: 32px; + + .left { + display: flex; + flex-direction: column; + flex: 1 0 auto; + + .widget { + flex: 1 0 auto; + } + } + + .right { + display: flex; + flex: 0 0 auto; + width: 320px; + min-width: 320px; + max-width: 320px; + } + } + +} diff --git a/src/app/main/content/apps/dashboards/analytics/analytics.component.ts b/src/app/main/content/apps/dashboards/analytics/analytics.component.ts new file mode 100644 index 00000000..f4bb947b --- /dev/null +++ b/src/app/main/content/apps/dashboards/analytics/analytics.component.ts @@ -0,0 +1,91 @@ +import { Component, ViewEncapsulation } from '@angular/core'; + +import { AnalyticsDashboardService } from './analytics.service'; +import { fuseAnimations } from '../../../../../core/animations'; + +@Component({ + selector : 'fuse-analytics-dashboard', + templateUrl : './analytics.component.html', + styleUrls : ['./analytics.component.scss'], + encapsulation: ViewEncapsulation.None, + animations : fuseAnimations +}) +export class FuseAnalyticsDashboardComponent +{ + widgets: any; + widget1SelectedYear = '2016'; + widget5SelectedDay = 'today'; + + constructor( + private analyticsDashboardService: AnalyticsDashboardService + ) + { + // Get the widgets from the service + this.widgets = this.analyticsDashboardService.widgets; + + // Register the custom chart.js plugin + this.registerCustomChartJSPlugin(); + } + + /** + * Register a custom plugin + */ + registerCustomChartJSPlugin() + { + (window).Chart.plugins.register({ + afterDatasetsDraw: function (chart, easing) { + // Only activate the plugin if it's made available + // in the options + if ( + !chart.options.plugins.xLabelsOnTop || + (chart.options.plugins.xLabelsOnTop && chart.options.plugins.xLabelsOnTop.active === false) + ) + { + return; + } + + // To only draw at the end of animation, check for easing === 1 + const ctx = chart.ctx; + + chart.data.datasets.forEach(function (dataset, i) { + const meta = chart.getDatasetMeta(i); + if ( !meta.hidden ) + { + meta.data.forEach(function (element, index) { + + // Draw the text in black, with the specified font + ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'; + const fontSize = 13; + const fontStyle = 'normal'; + const fontFamily = 'Roboto, Helvetica Neue, Arial'; + ctx.font = (window).Chart.helpers.fontString(fontSize, fontStyle, fontFamily); + + // Just naively convert to string for now + const dataString = dataset.data[index].toString() + 'k'; + + // Make sure alignment settings are correct + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + const padding = 15; + const startY = 24; + const position = element.tooltipPosition(); + ctx.fillText(dataString, position.x, startY); + + ctx.save(); + + ctx.beginPath(); + ctx.setLineDash([5, 3]); + ctx.moveTo(position.x, startY + padding); + ctx.lineTo(position.x, position.y - padding); + ctx.strokeStyle = 'rgba(255,255,255,0.12)'; + ctx.stroke(); + + ctx.restore(); + }); + } + }); + } + }); + } +} + diff --git a/src/app/main/content/apps/dashboards/analytics/analytics.module.ts b/src/app/main/content/apps/dashboards/analytics/analytics.module.ts new file mode 100644 index 00000000..7466e8b0 --- /dev/null +++ b/src/app/main/content/apps/dashboards/analytics/analytics.module.ts @@ -0,0 +1,41 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { SharedModule } from '../../../../../core/modules/shared.module'; +import { NgxChartsModule } from '@swimlane/ngx-charts'; +import { AgmCoreModule } from '@agm/core'; + +import { FuseAnalyticsDashboardComponent } from './analytics.component'; +import { AnalyticsDashboardService } from './analytics.service'; +import { FuseWidgetModule } from '../../../../../core/components/widget/widget.module'; + +const routes: Routes = [ + { + path : '**', + component: FuseAnalyticsDashboardComponent, + resolve : { + data: AnalyticsDashboardService + } + } +]; + +@NgModule({ + imports : [ + SharedModule, + RouterModule.forChild(routes), + FuseWidgetModule, + NgxChartsModule, + AgmCoreModule.forRoot({ + apiKey: 'AIzaSyD81ecsCj4yYpcXSLFcYU97PvRsE_X8Bx8' + }) + ], + declarations: [ + FuseAnalyticsDashboardComponent + ], + providers : [ + AnalyticsDashboardService + ] +}) +export class FuseAnalyticsDashboardModule +{ +} + diff --git a/src/app/main/content/apps/dashboards/project/projects.service.ts b/src/app/main/content/apps/dashboards/analytics/analytics.service.ts similarity index 69% rename from src/app/main/content/apps/dashboards/project/projects.service.ts rename to src/app/main/content/apps/dashboards/analytics/analytics.service.ts index f9d9d219..ef95bd6c 100644 --- a/src/app/main/content/apps/dashboards/project/projects.service.ts +++ b/src/app/main/content/apps/dashboards/analytics/analytics.service.ts @@ -4,9 +4,8 @@ import { Observable } from 'rxjs/Observable'; import { HttpClient } from '@angular/common/http'; @Injectable() -export class ProjectsDashboardService implements Resolve +export class AnalyticsDashboardService implements Resolve { - projects: any[]; widgets: any[]; constructor( @@ -23,11 +22,9 @@ export class ProjectsDashboardService implements Resolve */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | any { - return new Promise((resolve, reject) => { Promise.all([ - this.getProjects(), this.getWidgets() ]).then( () => { @@ -38,21 +35,10 @@ export class ProjectsDashboardService implements Resolve }); } - getProjects(): Promise - { - return new Promise((resolve, reject) => { - this.http.get('api/projects-dashboard-projects') - .subscribe((response: any) => { - this.projects = response; - resolve(response); - }, reject); - }); - } - getWidgets(): Promise { return new Promise((resolve, reject) => { - this.http.get('api/projects-dashboard-widgets') + this.http.get('api/analytics-dashboard-widgets') .subscribe((response: any) => { this.widgets = response; resolve(response); diff --git a/src/app/navigation/navigation.model.ts b/src/app/navigation/navigation.model.ts index da8e126d..28499e8d 100644 --- a/src/app/navigation/navigation.model.ts +++ b/src/app/navigation/navigation.model.ts @@ -26,6 +26,12 @@ export class FuseNavigationModel implements FuseNavigationModelInterface 'title': 'Project', 'type' : 'item', 'url' : '/apps/dashboards/project' + }, + { + 'id' : 'analytics', + 'title': 'Analytics', + 'type' : 'item', + 'url' : '/apps/dashboards/analytics' } ] },