+
+
+
+
+
+
+
+
+
+
+
+
No. of Essential Purchases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Your Purchases by Category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Global Puchases by Category
+
+
+
+
+
+ -
+
+
+
{{ category.category || 'N/A' }}
+
+
+
Bought
+
{{ category.value || 'N/A' }}
+
+
+ - totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
+
+
+
+
+
+
+
+
+
diff --git a/src/app/dashboard/dashboard-customer.component.ts b/src/app/dashboard/dashboard-customer.component.ts
index 39230e3..8870b69 100644
--- a/src/app/dashboard/dashboard-customer.component.ts
+++ b/src/app/dashboard/dashboard-customer.component.ts
@@ -1,16 +1,25 @@
import { Directive, Component, OnInit } from '@angular/core';
+import { CurrencyPipe } from '@angular/common';
import { ApiService } from '../providers/api-service';
import { Router } from '@angular/router';
+import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import { GraphWidget } from '../widgets/graph-widget.component';
+import { Color, Label } from 'ng2-charts';
+import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
+import { PiePanel } from '../panels/pie-panel.component';
+import { DataType } from '../shared/data-types.enum';
+import * as moment from 'moment';
+import { MoreStuffComponent } from '../dashboard/more-graphs-and-tables.component';
+// import { StackedBarChartComponent } from '../panels/stacked-bar.component';
+
+interface SuppliersComponent {
+ name : string;
+}
@Component({
templateUrl: 'dashboard-customer.component.html'
})
export class DashboardCustomerComponent implements OnInit {
- customersThisMonth: any;
- moneySpentThisMonth: any;
- pointsTotal: any;
- averageTransactionToday: any;
/* Setting up dashboard's main variables*/
name: any;
@@ -19,27 +28,178 @@ export class DashboardCustomerComponent implements OnInit {
trends: any;
myRank: any;
username: any;
+ maxPurchase: number = 0;
- basicStats = {
- today_sum: 0,
- today_count: 0,
- week_sum: 0,
- week_count: 0,
- month_sum: 0,
- month_count: 0,
- user_sum: 0,
- user_count: 0,
- global_sum: 0,
- global_count: 0,
- user_position: 0,
+ disableCategoryButton: boolean = false;
+
+ public bootstrapColours: string[] = ['bg-primary', 'bg-secondary', 'bg-success',
+'bg-danger', 'bg-warning', 'bg-info'];
+
+ public chartType = 'doughnut';
+ public chartLegend = true;
+ public doughnutChartDataCategory: any[] = [];
+ public doughnutChartLabelsCategory: string[] = [];
+ public doughnutChartColoursCategory: any[] = [
+ {
+ backgroundColor:[
+ '#ffa1b5',
+ '#3cde52',
+ '#52afed',
+ '#c133e3',
+ '#f7fa08',
+ '#75152d',
+ '#ee12ee',
+ '#15eaea',
+ '#eaa015',
+ '#ea1515',
+ '#2d4fcc'
+ ]
+ }];
+
+ public doughnutChartOptionsCategory:any = {
+ tooltips: {
+ callbacks: {
+ label: (tooltip, data) => {
+ return this.tooltipLabelCallback(tooltip, data);
+ },
+ },
+ },
+ }
+
+ myWeek1: any;
+
+ weekList1 = [];
+
+ public purchaseNotEssential: number;
+ public purchaseEssential: number;
+ public showEssentialBarChart = false;
+ public showCategoryBarChart = false;
+ public showCategoryDoughnutChart = false;
+
+ public barChartDataEssential:any[]=[
+ {data: 0, label: 'Essential', stack: '1'},
+ {data: 0, label: 'Non-Essential', stack: '1'},
+ ];
+ public barChartLabelsEssential:string[] = ['All Purchases'];
+ public barChartOptionsEssential:any = {
+ responsive: true,
+ scales:{
+ xAxes:[{
+ scaleLabel: {
+ display:true,
+ },
+ stacked:true,
+
+ }],
+ }
+ };
+ public barChartTypeEssential:string = 'horizontalBar';
+
+ public barChartOptionsCategory:any = {
+ scaleShowVerticalLines: false,
+ responsive: true,
+ scales: {
+ yAxes: [{
+ ticks: {
+ beginAtZero: true,
+ callback: label => `£${label}`
+ }
+ }]
+ },
+ tooltips: {
+ callbacks: {
+ label: (tooltip, data) => {
+ return this.tooltipLabelCallback(tooltip, data);
+ },
+ },
+ },
};
+ public barChartTypeCategory:string = 'bar';
+ public barChartLegendCategory:boolean = false;
+ public barChartDataCategory:any[]=[];
+ public barChartLabelsCategory:string[] = [];
+ public barChartColoursCategory: any[] = [
+ {
+ backgroundColor:[
+ '#ffa1b5',
+ '#3cde52',
+ '#52afed',
+ '#c133e3',
+ '#f7fa08',
+ '#75152d',
+ '#ee12ee',
+ '#15eaea',
+ '#eaa015',
+ '#ea1515',
+ '#2d4fcc'
+ ]
+ }];
+
+
+ weekPurchaseList = {
+ first: 0,
+ second: 0,
+ max: 0,
+ sum: 0,
+ count: 0,
+ };
+
+ showTotalCategoryList: boolean = false;
+ totalCategoryLimit: number = 10;
+ totalCategoryList: any[]=[];
+
+
+ // Graph widgets
+ public widgetList = [
+ {
+ type: 'graph',
+ name: 'total_last_week',
+ icon: 'icon-diamond',
+ title: 'Last Week Total',
+ dataType: DataType.currency,
+ },
+ {
+ type: 'graph',
+ name: 'avg_spend_last_week',
+ icon: 'icon-diamond',
+ title: 'Last Week Avg. Spend',
+ dataType: DataType.currency,
+ },
+ {
+ type: 'graph',
+ name: 'total_last_month',
+ title: 'Last Month Total',
+ dataType: DataType.currency,
+ },
+ {
+ type: 'graph',
+ name: 'avg_spend_last_month',
+ title: 'Last Month Avg. Spend',
+ dataType: DataType.currency,
+ },
+ ];
constructor(
private api: ApiService,
+ private currencyPipe: CurrencyPipe,
) {
- this.api.basicStats().subscribe(
+ this.setDate();
+ this.api.customerStats().subscribe(
result => {
- this.basicStats = result;
+ this.setWeekPurchaseList(result.weeks);
+ this.setWeekData(result);
+ this.setChartData(result.data.cat_total);
+ this.totalCategoryList = result.data.cat_list;
+ if (this.totalCategoryList) {
+ this.showTotalCategoryList = true;
+ }
+ this.purchaseEssential = result.data.essentials.purchase_no_essential_total;
+ this.purchaseNotEssential = result.data.essentials.purchase_no_total - this.purchaseEssential;
+ this.barChartDataEssential = [
+ {data: [this.purchaseEssential], label: 'Essential', stack: '1'},
+ {data: [this.purchaseNotEssential], label: 'Non-Essential', stack: '1'},
+ ];
+ this.showEssentialBarChart = true;
},
error => {
console.log('Retrieval Error');
@@ -48,6 +208,77 @@ export class DashboardCustomerComponent implements OnInit {
);
}
+ private setChartData(dataCat: any) {
+ this.barChartLabelsCategory = Object.keys(dataCat);
+ let barChartDataCategoryInitial = Object.keys(dataCat).map(key => dataCat[key]);
+ this.barChartDataCategory = [
+ {data: barChartDataCategoryInitial, label: 'Series A'},
+ ];
+ this.showCategoryBarChart = true;
+ if (this.weekList1) {
+ let doughnutChartDataCategoryInitial = this.weekList1.map(function(a) {return a.value;});
+ this.doughnutChartDataCategory = [
+ {data: doughnutChartDataCategoryInitial, label: 'Series A'},
+ ];
+ // setTimeout is currently a workaround for ng2-charts labels
+ setTimeout(() => this.doughnutChartLabelsCategory = this.weekList1.map(function(a) {return a.category;}), 0);
+ this.showCategoryDoughnutChart = true;
+ }
+ }
+
+ private setDate () {
+ this.myWeek1 = moment().startOf('isoWeek').format('YYYY-MM-DD');
+ }
+
+ private setWeekData (data: any) {
+ function prop
(obj: T, key: K) {
+ return obj[key];
+ }
+ this.weekList1 = prop(data.data.categories, this.myWeek1);
+ }
+
+ public setWeekPurchaseList (data: any) {
+ this.weekPurchaseList = {
+ first: data.first,
+ second: data.second,
+ max: data.max,
+ sum: data.sum,
+ count: data.count,
+ };
+ }
+
+ private categoryLoadMore () {
+ this.disableCategoryButton = true;
+ this.totalCategoryLimit = 30;
+ }
+
+ public getBootstrapColour(index: number) {
+ return this.bootstrapColours[index % this.bootstrapColours.length];
+ }
+
+ public convertHex(hex: string, opacity: number) {
+ hex = hex.replace('#', '');
+ const r = parseInt(hex.substring(0, 2), 16);
+ const g = parseInt(hex.substring(2, 4), 16);
+ const b = parseInt(hex.substring(4, 6), 16);
+
+ const rgba = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + opacity / 100 + ')';
+ return rgba;
+ }
+
+ private tooltipLabelCallback(tooltipItem: any, data: any) {
+ var dataset = data.datasets[tooltipItem.datasetIndex];
+ var value = dataset.data[tooltipItem.index];
+ return this.currencyPipe.transform(value, 'GBP', 'symbol', '1.2-2');
+ }
+
+ // events
+ public chartClicked(e: any): void {
+ }
+
+ public chartHovered(e: any): void {
+ }
+
ngOnInit(): void {
}
}
diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html
index 4ee858b..98901c3 100644
--- a/src/app/dashboard/dashboard.component.html
+++ b/src/app/dashboard/dashboard.component.html
@@ -1,3 +1,4 @@
+
@@ -6,8 +7,107 @@
[graphName]="widget.name"
[graphTitle]="widget.title"
[graphIcon]="widget.icon"
- [dataType]="widget.dataType">
+ [dataType]="widget.dataType">
+
-
+
+
+
+
+
+
Number of Essential Purchases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
All Organisation Purchases by Category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This weeks' spending by Category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Global Puchases by Category
+
+
+
+
+
+ -
+
+
+
{{ category.category || 'N/A' }}
+
+
+
Bought
+
{{ category.value || 'N/A' }}
+
+
+ - totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
+
+
+
+
+
+
+
+
+
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts
index 444a17c..f15669b 100644
--- a/src/app/dashboard/dashboard.component.ts
+++ b/src/app/dashboard/dashboard.component.ts
@@ -1,9 +1,16 @@
import { Component } from '@angular/core';
-import { Router } from '@angular/router';
+import { Router, NavigationEnd } from "@angular/router";
+import { CurrencyPipe } from '@angular/common';
+import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
+import { Color, Label } from 'ng2-charts';
import { GraphWidget } from '../widgets/graph-widget.component';
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
import { GraphPanel } from '../panels/graph-panel.component';
+import { OrgPiePanel } from '../panels/org-pie-panel.component';
import { DataType } from '../shared/data-types.enum';
+import { ApiService } from '../providers/api-service';
+import { environment } from '../../environments/environment';
+import * as moment from 'moment';
@Component({
templateUrl: 'dashboard.component.html'
@@ -37,6 +44,13 @@ export class DashboardComponent {
title: 'Sales Last 30 Days',
dataType: DataType.currency,
},
+ {
+ type: 'graph',
+ name: 'sales_last_quart',
+ icon: 'icon-diamond',
+ title: 'Sales Last Quart',
+ dataType: DataType.currency,
+ },
{
type: 'graph',
name: 'purchases_last_7_days',
@@ -49,7 +63,307 @@ export class DashboardComponent {
title: 'Purchases Last 30 Days',
dataType: DataType.currency,
},
+ {
+ type: 'graph',
+ name: 'purchases_last_quart;',
+ title: 'Purchases Last Quart',
+ dataType: DataType.currency,
+ },
];
- constructor() { }
+ disableCategoryButton: boolean = false;
+
+ public bootstrapColours: string[] = ['bg-primary', 'bg-secondary', 'bg-success',
+'bg-danger', 'bg-warning', 'bg-info'];
+
+ public chartType = 'doughnut';
+ public chartLegend = true;
+ public doughnutChartDataCategory: any[] = [];
+ public doughnutChartLabelsCategory: string[] = [];
+ public doughnutChartColoursCategory: any[] = [
+ {
+ backgroundColor:[
+ '#ffa1b5',
+ '#3cde52',
+ '#52afed',
+ '#c133e3',
+ '#f7fa08',
+ '#75152d',
+ '#ee12ee',
+ '#15eaea',
+ '#eaa015',
+ '#ea1515',
+ '#2d4fcc'
+ ]
+ }];
+
+
+ public doughnutChartOptionsCategory:any = {
+ tooltips: {
+ callbacks: {
+ label: (tooltip, data) => {
+ return this.tooltipLabelCallback(tooltip, data);
+ },
+ },
+ },
+ }
+
+ myWeek1: any;
+
+ weekList1 = [];
+
+ public purchaseNotEssential: number;
+ public purchaseEssential: number;
+ public showEssentialBarChart:boolean = false;
+ public showCategoryBarChart = false;
+ public showCategoryDoughnutChart = false;
+
+ public barChartDataEssential: ChartDataSets[] = [
+ {data: [0], label: 'Essential', stack: '1'},
+ {data: [0], label: 'Non-Essential', stack: '1'},
+ ];
+ public barChartLabelsEssential:string[] = ['All Purchases'];
+ public barChartOptionsEssential:any = {
+ responsive: true,
+ scales:{
+ xAxes:[{
+ stacked:true
+ }],
+ yAxes:[{
+ stacked:true
+ }]
+ }
+ };
+ public barChartTypeEssential:string = 'horizontalBar';
+ public barChartColoursCategory: any[] = [
+ {
+ backgroundColor:[
+ '#ffa1b5',
+ '#3cde52',
+ '#52afed',
+ '#c133e3',
+ '#f7fa08',
+ '#75152d',
+ '#ee12ee',
+ '#15eaea',
+ '#eaa015',
+ '#ea1515',
+ '#2d4fcc'
+ ]
+ }];
+
+ public barChartOptionsCategory:any = {
+ scaleShowVerticalLines: false,
+ responsive: true,
+ scales: {
+ yAxes: [{
+ ticks: {
+ beginAtZero: true,
+ callback: label => `£${label}`
+ }
+ }]
+ },
+ tooltips: {
+ callbacks: {
+ label: (tooltip, data) => {
+ return this.tooltipLabelCallback(tooltip, data);
+ },
+ },
+ },
+ };
+ public barChartTypeCategory:string = 'bar';
+ public barChartLegendCategory:boolean = false;
+ public barChartDataCategory:any[]=[];
+ public barChartLabelsCategory:string[] = [];
+
+ public lineChartDataSector: ChartDataSets[] = [
+ { data: [], label: '' },
+ ];
+ public lineChartLabelsSector: Label[] = ['January', 'February', 'March', 'April', 'May', 'June', 'July','August','September','October','November','December'];
+ public lineChartOptionsSector: (ChartOptions & { annotation: any }) = {
+ responsive: true,
+ scales: {
+ // We use this empty structure as a placeholder for dynamic theming.
+ xAxes: [{}],
+ yAxes: [{}]
+ },
+ annotation: {
+ annotations: [
+ {
+ type: 'line',
+ mode: 'vertical',
+ scaleID: 'x-axis-0',
+ value: 'March',
+ borderColor: 'orange',
+ borderWidth: 2,
+ label: {
+ enabled: true,
+ fontColor: 'orange',
+ content: 'LineAnno'
+ }
+ },
+ ],
+ },
+ };
+ public lineChartColorsSector: Color[] = [
+ { // grey
+ backgroundColor: 'rgba(148,159,177,0.2)',
+ borderColor: 'rgba(148,159,177,1)',
+ pointBackgroundColor: 'rgba(148,159,177,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(148,159,177,0.8)'
+ },
+ { // dark grey
+ backgroundColor: 'rgba(77,83,96,0.2)',
+ borderColor: 'rgba(77,83,96,1)',
+ pointBackgroundColor: 'rgba(77,83,96,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(77,83,96,1)'
+ },
+ { // red
+ backgroundColor: 'rgba(255,0,0,0.3)',
+ borderColor: 'red',
+ pointBackgroundColor: 'rgba(148,159,177,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(148,159,177,0.8)'
+ }
+ ];
+ public lineChartLegendSector = true;
+ public lineChartTypeSector = 'line';
+
+ weekPurchaseList = {
+ first: 0,
+ second: 0,
+ max: 0,
+ sum: 0,
+ count: 0,
+ };
+
+ showTotalCategoryList: boolean = false;
+ totalCategoryLimit: number = 10;
+ totalCategoryList: any[]=[];
+
+ constructor(
+ private router: Router,
+ private api: ApiService,
+ private currencyPipe: CurrencyPipe,
+ ) {
+ if (environment.enableAnalytics) {
+ this.router.events.subscribe(event => {
+ if (event instanceof NavigationEnd) {
+ (
window).ga('set', 'page', event.urlAfterRedirects);
+ (window).ga('send', 'pageview');
+ }
+ });
+ }
+ this.setDate();
+ this.api.orgStats().subscribe(
+ result => {
+ this.setWeekPurchaseList(result.weeks);
+ this.setWeekData(result);
+ this.setChartDataCat(result.data.cat_total);
+ this.setChartDataEssential(result.data.essentials);
+ this.totalCategoryList = result.data.cat_list;
+ if (this.totalCategoryList) {
+ this.showTotalCategoryList = true;
+ }
+ },
+ error => {
+ console.log('Retrieval Error');
+ console.log( error._body );
+ }
+ );
+ }
+
+ private setChartDataEssential (dataEs: any) {
+ this.purchaseEssential = dataEs.purchase_no_essential_total;
+ this.purchaseNotEssential = dataEs.purchase_no_total - this.purchaseEssential;
+ this.barChartDataEssential = [
+ {data: [this.purchaseEssential], label: 'Essential', stack: '1'},
+ {data: [this.purchaseNotEssential], label: 'Non-Essential', stack: '1'},
+ ];
+ this.showEssentialBarChart = true;
+ console.log(this.barChartDataEssential);
+ }
+
+ private setChartDataCat(dataCat: any) {
+ this.barChartLabelsCategory = Object.keys(dataCat);
+ let barChartDataCategoryInitial = Object.keys(dataCat).map(key => dataCat[key]);
+ this.barChartDataCategory = [
+ {data: barChartDataCategoryInitial, label: 'Series A'},
+ ];
+ this.showCategoryBarChart = true;
+ if (this.weekList1) {
+ let doughnutChartDataCategoryInitial = this.weekList1.map(function(a) {return a.value;});
+ this.doughnutChartDataCategory = [
+ {data: doughnutChartDataCategoryInitial, label: 'Series A'},
+ ];
+ // setTimeout is currently a workaround for ng2-charts labels
+ setTimeout(() => this.doughnutChartLabelsCategory = this.weekList1.map(function(a) {return a.category;}), 0);
+ this.showCategoryDoughnutChart = true;
+ }
+ }
+
+ private setChartDataSector(dataSec: any) {
+
+ }
+
+ private setDate () {
+ this.myWeek1 = moment().startOf('isoWeek').format('YYYY-MM-DD');
+ }
+
+ private setWeekData (data: any) {
+ function prop(obj: T, key: K) {
+ return obj[key];
+ }
+ this.weekList1 = prop(data.data.categories, this.myWeek1);
+ }
+
+ public setWeekPurchaseList (data: any) {
+ this.weekPurchaseList = {
+ first: data.first,
+ second: data.second,
+ max: data.max,
+ sum: data.sum,
+ count: data.count,
+ };
+ }
+
+ private categoryLoadMore () {
+ this.disableCategoryButton = true;
+ this.totalCategoryLimit = 30;
+ }
+
+ public getBootstrapColour(index: number) {
+ return this.bootstrapColours[index % this.bootstrapColours.length];
+ }
+
+ public convertHex(hex: string, opacity: number) {
+ hex = hex.replace('#', '');
+ const r = parseInt(hex.substring(0, 2), 16);
+ const g = parseInt(hex.substring(2, 4), 16);
+ const b = parseInt(hex.substring(4, 6), 16);
+
+ const rgba = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + opacity / 100 + ')';
+ return rgba;
+ }
+
+ private tooltipLabelCallback(tooltipItem: any, data: any) {
+ var dataset = data.datasets[tooltipItem.datasetIndex];
+ var value = dataset.data[tooltipItem.index];
+ return this.currencyPipe.transform(value, 'GBP', 'symbol', '1.2-2');
+ }
+
+ // events
+ public chartClicked(e: any): void {
+ }
+
+ public chartHovered(e: any): void {
+ }
+
+ ngOnInit(): void {
+ }
}
diff --git a/src/app/dashboard/dashboard.module.ts b/src/app/dashboard/dashboard.module.ts
index 0e5302b..094216c 100644
--- a/src/app/dashboard/dashboard.module.ts
+++ b/src/app/dashboard/dashboard.module.ts
@@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { ChartsModule } from 'ng2-charts/ng2-charts';
+import { ChartsModule } from 'ng2-charts';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { NgxPaginationModule } from 'ngx-pagination';
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
@@ -16,19 +16,31 @@ import { AccountEditComponent } from './account-edit.component';
import { AddDataComponent } from './add-data.component';
import { FeedbackComponent } from './feedback.component';
import { TransactionLogComponent } from './transaction-log.component';
+import { CategoryMonthComponent } from './category-month.component';
import { PayrollLogComponent } from './payroll-log.component';
+import { SuppliersComponent } from './suppliers.component';
+import { MoreStuffComponent } from './more-graphs-and-tables.component';
import { LeaderboardComponent } from './leaderboard.component';
import { MapComponent } from './map.component';
import { TrailMapComponent } from './trail-map.component';
import { GraphWidget } from '../widgets/graph-widget.component';
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
+import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
import { GraphPanel } from '../panels/graph-panel.component';
+import { BubbleChartComponent } from '../panels/bubble-panel.component';
+import { PiePanel } from '../panels/pie-panel.component';
+import { OrgPiePanel } from '../panels/org-pie-panel.component';
import { DashboardRoutingModule } from './dashboard.routing';
import { OrgResultComponent } from '../shared/org-result.component';
import { OrgTableComponent } from '../shared/org-table.component';
+import { RecurResultComponent } from '../shared/recur-result.component';
+import { RecurTableComponent } from '../shared/recur-table.component';
import { TransactionResultComponent } from '../shared/transaction-result.component';
+import { SupplierResultComponent } from '../shared/supplier-result.component';
+import { WardResultComponent } from '../shared/ward-result.component';
+import { MetaTypeResultComponent } from '../shared/meta-type-result.component';
import { PayrollResultComponent } from '../shared/payroll-result.component';
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
@@ -58,8 +70,14 @@ import { environment } from '../../environments/environment';
AddDataComponent,
OrgResultComponent,
OrgTableComponent,
+ RecurResultComponent,
+ RecurTableComponent,
TransactionLogComponent,
+ CategoryMonthComponent,
TransactionResultComponent,
+ SupplierResultComponent,
+ WardResultComponent,
+ MetaTypeResultComponent,
PayrollLogComponent,
PayrollResultComponent,
LeaderboardComponent,
@@ -69,7 +87,13 @@ import { environment } from '../../environments/environment';
FeedbackComponent,
GraphWidget,
OrgBarSnippetComponent,
+ CustBarSnippetComponent,
GraphPanel,
+ PiePanel,
+ OrgPiePanel,
+ BubbleChartComponent,
+ SuppliersComponent,
+ MoreStuffComponent,
],
providers: [
CurrencyPipe,
diff --git a/src/app/dashboard/dashboard.routing.ts b/src/app/dashboard/dashboard.routing.ts
index 0ea44fb..6d554ef 100644
--- a/src/app/dashboard/dashboard.routing.ts
+++ b/src/app/dashboard/dashboard.routing.ts
@@ -12,10 +12,13 @@ import { AccountEditComponent } from './account-edit.component';
import { AddDataComponent } from './add-data.component';
import { FeedbackComponent } from './feedback.component';
import { TransactionLogComponent } from './transaction-log.component';
+import { CategoryMonthComponent } from './category-month.component';
import { PayrollLogComponent } from './payroll-log.component';
import { LeaderboardComponent } from './leaderboard.component';
import { MapComponent } from './map.component';
import { TrailMapComponent } from './trail-map.component';
+import { MoreStuffComponent } from './more-graphs-and-tables.component';
+import { SuppliersComponent } from './suppliers.component';
// Using child path to allow for FullLayout theming
const routes: Routes = [
@@ -58,6 +61,11 @@ const routes: Routes = [
component: TransactionLogComponent,
data: { title: 'Transaction Log' },
},
+ {
+ path: 'category-month',
+ component: CategoryMonthComponent,
+ data: { title: 'Budget' },
+ },
{
path: 'map',
component: MapComponent,
@@ -66,7 +74,7 @@ const routes: Routes = [
{
path: 'story-trail',
component: TrailMapComponent,
- data: { title: 'Lancaster Independent Story' },
+ data: { title: 'Story Trail' },
},
{
path: 'payroll-log',
@@ -78,6 +86,16 @@ const routes: Routes = [
path: 'feedback',
component: FeedbackComponent,
data: { title: 'Give Feedback' },
+ },
+ {
+ path: 'suppliers',
+ component: SuppliersComponent,
+ data: { title: 'Suppliers' }
+ },
+ {
+ path: 'more-graphs-and-tables',
+ component: MoreStuffComponent,
+ data: { title: 'Infographics'}
}
],
}
diff --git a/src/app/dashboard/feedback.component.ts b/src/app/dashboard/feedback.component.ts
index 5228a3c..2811183 100644
--- a/src/app/dashboard/feedback.component.ts
+++ b/src/app/dashboard/feedback.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
import { ApiService } from '../providers/api-service';
-import 'rxjs/add/operator/map';
+
@Component({
templateUrl: 'feedback.component.html',
@@ -55,9 +55,7 @@ export class FeedbackComponent implements OnInit {
result => {
if ( result.success === true ) {
console.log('Successful Upload');
- console.log(result);
this.feedbackFormStatus = 'success';
- console.log(this.feedbackFormStatus);
this.feedbackForm.patchValue({
feedbacktext: '',
});
@@ -65,22 +63,16 @@ export class FeedbackComponent implements OnInit {
console.log('Upload Error');
this.feedbackFormStatusError = JSON.stringify(result.status) + 'Error, ' + JSON.stringify(result.message);
this.feedbackFormStatus = 'send_failed';
- console.log(this.feedbackFormStatus);
}
},
error => {
console.log('Upload Error');
- console.log(error);
try {
- console.log(error.error);
- const jsonError = error.json();
- console.log('boop');
- this.feedbackFormStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message;
+ this.feedbackFormStatusError = '"' + error.error.error + '" Error, ' + error.error.message;
} catch (e) {
this.feedbackFormStatusError = 'There was a server error, please try again later.';
}
this.feedbackFormStatus = 'send_failed';
- console.log(this.feedbackFormStatus);
}
);
}
diff --git a/src/app/dashboard/leaderboard.component.html b/src/app/dashboard/leaderboard.component.html
index 34345f3..91f27f5 100644
--- a/src/app/dashboard/leaderboard.component.html
+++ b/src/app/dashboard/leaderboard.component.html
@@ -23,8 +23,8 @@
Position |
- Value |
- Purchase Time |
+ Name |
+ Gross amount |
diff --git a/src/app/dashboard/leaderboard.component.ts b/src/app/dashboard/leaderboard.component.ts
index 4c76fc7..5c8140f 100644
--- a/src/app/dashboard/leaderboard.component.ts
+++ b/src/app/dashboard/leaderboard.component.ts
@@ -5,7 +5,7 @@ import {PaginationInstance} from 'ngx-pagination';
// import { PaginationControlsComponent } from 'ngx-pagination';
// import { PaginationControlsDirective } from 'ngx-pagination';
// import { TransactionResultComponent } from '../shared/transaction-result.component';
-import 'rxjs/add/operator/map';
+
@Component({
templateUrl: 'leaderboard.component.html',
@@ -22,7 +22,7 @@ export class LeaderboardComponent implements OnInit {
public paginateConfig: PaginationInstance = {
id: 'leadpaginate',
- itemsPerPage: 10,
+ itemsPerPage: 20,
currentPage: 1,
totalItems: 0
};
@@ -70,7 +70,7 @@ export class LeaderboardComponent implements OnInit {
console.log(error);
}
);
- }
+ }org
// // dynamically changes the row style based on player's position
// // for instance, top three player and the player him/herself should
diff --git a/src/app/dashboard/map.component.html b/src/app/dashboard/map.component.html
index ab9a97e..4230fe4 100644
--- a/src/app/dashboard/map.component.html
+++ b/src/app/dashboard/map.component.html
@@ -3,8 +3,8 @@
diff --git a/src/app/dashboard/map.component.ts b/src/app/dashboard/map.component.ts
index 374aa66..d48c567 100644
--- a/src/app/dashboard/map.component.ts
+++ b/src/app/dashboard/map.component.ts
@@ -3,13 +3,13 @@ import { ApiService } from '../providers/api-service';
import { AgmCoreModule } from '@agm/core';
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
-import 'rxjs/add/operator/map';
+
@Component({
templateUrl: 'map.component.html',
})
export class MapComponent implements OnInit, AfterViewInit {
- @ViewChild('statusModal') myStatusModal: ModalDirective;
+ @ViewChild('statusModal', { static: true }) myStatusModal: ModalDirective;
lat: number = 54.0466;
lng: number = -2.8007;
zoom: number = 12;
diff --git a/src/app/dashboard/more-graphs-and-tables.component.html b/src/app/dashboard/more-graphs-and-tables.component.html
new file mode 100644
index 0000000..73cef98
--- /dev/null
+++ b/src/app/dashboard/more-graphs-and-tables.component.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+ Ward |
+ Amount of Transactions |
+ Sum of Transactions |
+
+
+
+
+
+
+
+
+ No Data available.
+
+
+
+
+
+
+
+
+
+
+ Ward |
+ Amount of Transactions |
+ Sum of Transactions |
+
+
+
+
+
+
+
+
+ No Data available.
+
+
+
+
+
+
+
+
+
+
+
Supplier spend amount and number of purchases
+
+
+
vertical shows number of purchases, size of bubble shows the total spend amount, horizontal shows date
+
+
+
+
+
+
+
+
+
+
+
Spend & Number of Transactions
+ Date against Value and Number of Transactions
+
+
+
+
+
+
+
+
+
+
+
+
Supplier Spend History
+
+
+
+
+ Page {{ _supplierHistoryPage }} of {{ _supplierHistoryPages }}
+
+
+
+
+
+
+
+
diff --git a/src/app/dashboard/more-graphs-and-tables.component.ts b/src/app/dashboard/more-graphs-and-tables.component.ts
new file mode 100644
index 0000000..2de09b7
--- /dev/null
+++ b/src/app/dashboard/more-graphs-and-tables.component.ts
@@ -0,0 +1,335 @@
+import {Component, OnInit, Input, Output, EventEmitter, ViewChild} from '@angular/core';
+import {ApiService} from '../providers/api-service';
+import {BaseChartDirective} from 'ng2-charts';
+import {CurrencyPipe} from '@angular/common';
+import {ChartType} from "chart.js";
+import * as moment from 'moment';
+
+@Component({
+ templateUrl: 'more-graphs-and-tables.component.html',
+})
+export class MoreStuffComponent implements OnInit {
+ @Output() public onClick = new EventEmitter();
+ @Input() public categories: any;
+
+ // Global Filter Setup
+ filterFrom: any;
+ filterTo: any;
+
+ isBubbleChartLoaded: boolean = false;
+ isSupplierChartLoaded: boolean = false;
+ wardList: any;
+ wardListAvailable = false;
+ metaTypeList: any;
+ metaTypeListAvailable = false;
+
+ constructor(
+ private api: ApiService,
+ private currencyPipe: CurrencyPipe,
+ ) {
+ let now = moment();
+ this.filterTo = now.format('YYYY-MM-DD');
+ now.subtract(1, 'months');
+ this.filterFrom = now.format('YYYY-MM-DD');
+ this.tableSummary();
+ }
+
+ ngOnInit(): void {
+ this.loadData();
+ }
+
+ public loadData() {
+ this.tableSummary();
+ this.loadYearSpend();
+ this.loadSupplierBubble();
+ this.loadSupplierHistory();
+ }
+
+ public showLegend = true;
+
+ /*
+ * Supplier Bubble Chart Setup
+ */
+
+ private formatGraphData(data: any): any[] {
+ let graph_data = [];
+
+ data.data.map(item => {
+ graph_data.push({
+ t: item.date,
+ r: item.value > 1000000 ? (item.value / 200000) : (item.value / 100000) + 5,
+ supplier: item.seller,
+ y: item.count,
+ value: item.value,
+ count: item.count,
+ });
+ });
+
+ return graph_data;
+ }
+
+ private loadSupplierBubble() {
+ this.api.loadMiscUrl('organisation/external/supplier_count', {
+ from: this.filterFrom,
+ to: this.filterTo,
+ }).subscribe(
+ result => {
+ this.supplierBubbleChartData[0].data = this.formatGraphData(result);
+ this.isBubbleChartLoaded = true;
+ }
+ )
+ }
+
+ public supplierBubbleChartType: ChartType = 'bubble';
+ public supplierBubbleChartData: any[] = [
+ {
+ data: [],
+ label: ["Spend"],
+ borderColor: 'blue',
+ hoverBorderColor: 'black',
+ radius: 5,
+ },
+ ];
+ public supplierBubbleChartLabels: string[] = [];
+ public supplierBubbleChartOptions: any = {
+ responsive: true,
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ unit: 'month'
+ },
+ scaleLabel: {
+ display: true,
+ labelString: 'Date'
+ }
+ }],
+ yAxes: [{
+ scaleLabel: {
+ display: true,
+ labelString: 'Number of purchases'
+ }
+ }]
+ },
+ tooltips: {
+ callbacks: {
+ label: (tooltip, data) => {
+ return this.bubbleTooltipCallback(tooltip, data);
+ },
+ },
+ },
+ };
+
+ private bubbleTooltipCallback(tooltipItem: any, data: any) {
+ let dataset = data.datasets[tooltipItem.datasetIndex];
+ let value = dataset.data[tooltipItem.index];
+ return `${value.supplier}: ${this.currencyPipe.transform(value.value, 'GBP', 'symbol', '1.2-2')} over ${value.count} purchases`;
+ }
+
+ private tableSummary() {
+ this.api.loadMiscUrl('organisation/external/lcc_tables', {
+ from: this.filterFrom,
+ to: this.filterTo,
+ }).subscribe(
+ result => {
+ this.wardList = result.wards;
+ this.metaTypeList = Object.keys(result.types).map(key => result.types[key]);
+ if (this.wardList) {
+ this.wardListAvailable = true;
+ }
+ if (this.metaTypeList) {
+ this.metaTypeListAvailable = true;
+ }
+ },
+ error => {
+ console.log('Retrieval Error');
+ console.log(error._body);
+ }
+ )
+ }
+
+ private loadYearSpend() {
+ this.api.loadMiscUrl('organisation/external/year_spend', {
+ from: this.filterFrom,
+ to: this.filterTo,
+ }).subscribe(
+ result => {
+ let value_data = [];
+ let count_data = [];
+
+ result.data.map(item => {
+ value_data.push({
+ t: item.date,
+ y: item.value,
+ });
+
+ count_data.push({
+ t: item.date,
+ y: item.count,
+ });
+ });
+
+ this.yearSpendChartData[0].data = value_data;
+ this.yearSpendChartData[1].data = count_data;
+ }
+ )
+ }
+
+ public yearSpendChartData: any[] = [
+ {
+ data: [],
+ label: ["Value £"],
+ fill: false,
+ borderColor: 'red',
+ hoverBackgroundColor: '#ffa1b5',
+ hoverBorderColor: 'red',
+ yAxisID: 'y-value',
+ },
+ {
+ data: [],
+ label: ["Count"],
+ fill: false,
+ borderColor: 'blue',
+ hoverBackgroundColor: '#52afed',
+ hoverBorderColor: 'blue',
+ yAxisID: 'y-count',
+ },
+ ];
+ public yearSpendChartOptions: any = {
+ elements: {line: {tension: 0}},
+ responsive: true,
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ unit: 'month'
+ },
+ scaleLabel: {
+ display: true,
+ labelString: 'Date'
+ }
+ }],
+ yAxes: [
+ {id: 'y-value', position: 'left', beginAtZero: true, type: 'linear'},
+ {id: 'y-count', position: 'right', beginAtZero: true, type: 'linear'},
+ ]
+ },
+ };
+ public yearSpendChartLabels: string[] = [];
+ public yearSpendChartType: ChartType = 'line';
+
+ randomData() {
+ return Math.random();
+ }
+
+ lineChartUpdate() {
+ this.loadYearSpend();
+
+ }
+
+ @ViewChild('supplierChart', {read: BaseChartDirective, static: false}) supplierChart: BaseChartDirective;
+
+ private loadSupplierHistory() {
+ this.api.loadMiscUrl('organisation/external/supplier_history').subscribe(
+ result => {
+ this._supplierHistoryData = result.data;
+ this._supplierHistoryPage = 1;
+ this._supplierHistoryPages = Math.ceil(this._supplierHistoryData.length / this._supplierHistoryPerPage);
+ this.updateSupplierHistoryData();
+
+ this.isSupplierChartLoaded = true;
+ }
+ );
+ }
+
+ private updateSupplierHistoryData() {
+
+ const lastResult = this._supplierHistoryPerPage * this._supplierHistoryPage;
+ console.log(this._supplierHistoryPage);
+ const firstResult = lastResult - this._supplierHistoryPerPage;
+
+ const pageData = this._supplierHistoryData.slice(firstResult, lastResult);
+ console.log(pageData);
+
+ let labels = [];
+ let year = [];
+ let half = [];
+ let quarter = [];
+ pageData.map(item => {
+ labels.push(item.name);
+ year.push(item.year_total);
+ half.push(item.half_total);
+ quarter.push(item.quarter_total);
+ });
+
+ this.supplierMonthChartData[0].data = quarter;
+ this.supplierMonthChartData[1].data = half;
+ this.supplierMonthChartData[2].data = year;
+ this.supplierMonthChartLabels = labels;
+ }
+
+ public nextSupplierHistoryPage() {
+ if (this._supplierHistoryPage < this._supplierHistoryPages) {
+ this._supplierHistoryPage++;
+ }
+ this.updateSupplierHistoryData();
+ }
+
+ public previousSupplierHistoryPage() {
+ if (this._supplierHistoryPage > 1) {
+ this._supplierHistoryPage--;
+ }
+ this.updateSupplierHistoryData();
+ }
+
+ private _supplierHistoryData: any[];
+ private _supplierHistoryPerPage: number = 15;
+ public _supplierHistoryPage: number = 1;
+ public _supplierHistoryPages: number = 1;
+ public supplierMonthChartData: any[] = [
+ {
+ data: [],
+ label: ["3 Month"],
+ fill: false,
+ borderColor: 'red',
+ hoverBorderColor: 'red',
+ hoverBackgroundColor: 'red',
+ },
+ {
+ data: [],
+ label: ["6 Month"],
+ fill: false,
+ borderColor: 'blue',
+ hoverBorderColor: 'blue',
+ hoverBackgroundColor: 'blue',
+ },
+ {
+ data: [],
+ label: ["12 Month"],
+ fill: false,
+ borderColor: 'orange',
+ hoverBorderColor: 'orange',
+ hoverBackgroundColor: 'orange',
+ },
+ ];
+ public supplierMonthChartOptions: any = {
+ //maintainAspectRatio: false,
+ responsive: true,
+ scales: {
+ xAxes: [{
+ scaleLabel: {
+ display: true,
+ labelString: 'Spend amount £'
+ }
+ }],
+ yAxes: [{
+ scaleLabel: {
+ display: true,
+ labelString: 'Supplier Names'
+ }
+ }]
+ },
+ };
+ public supplierMonthChartLabels: string[] = [];
+ public supplierMonthChartType: ChartType = 'horizontalBar';
+}
diff --git a/src/app/dashboard/payroll-log.component.ts b/src/app/dashboard/payroll-log.component.ts
index 3b92ae7..95ef8ec 100644
--- a/src/app/dashboard/payroll-log.component.ts
+++ b/src/app/dashboard/payroll-log.component.ts
@@ -6,7 +6,7 @@ import {PaginationInstance} from 'ngx-pagination';
// import { PaginationControlsDirective } from 'ngx-pagination';
// import { TransactionResultComponent } from '../shared/transaction-result.component';
import * as moment from 'moment';
-import 'rxjs/add/operator/map';
+
@Component({
templateUrl: 'payroll-log.component.html',
diff --git a/src/app/dashboard/suppliers.component.html b/src/app/dashboard/suppliers.component.html
new file mode 100644
index 0000000..6543598
--- /dev/null
+++ b/src/app/dashboard/suppliers.component.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+ |
+ Postcode
+
+
+ |
+ Spend
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ No Suppliers available.
+
+
+
+
+
diff --git a/src/app/dashboard/suppliers.component.ts b/src/app/dashboard/suppliers.component.ts
new file mode 100644
index 0000000..50421cf
--- /dev/null
+++ b/src/app/dashboard/suppliers.component.ts
@@ -0,0 +1,74 @@
+import { Component, OnInit, AfterViewInit, Input, Output, EventEmitter, ViewChild, TemplateRef } from '@angular/core';
+import { ApiService } from '../providers/api-service';
+import { AgmCoreModule } from '@agm/core';
+import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
+import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
+import { PaginationInstance } from 'ngx-pagination';
+import { FilterPipeModule } from 'ngx-filter-pipe';
+@Component({
+ templateUrl: 'suppliers.component.html',
+})
+export class SuppliersComponent implements OnInit, AfterViewInit {
+ @Output() public onClick = new EventEmitter();
+ @Input() public categories: any;
+ public perPage: number = 10;
+
+ searchText: string;
+
+ supplierList: any;
+ supplierListAvailable = false;
+ sortBy = 'name';
+ sortDir = 'asc';
+
+ public paginateConfig: PaginationInstance = {
+ id: 'transpaginate',
+ itemsPerPage: this.perPage,
+ currentPage: 1,
+ totalItems: 0
+ };
+
+ constructor(
+ private api: ApiService,
+ ) { }
+
+ ngOnInit(): void {
+ this.loadSuppliers(1);
+ }
+
+ loadSuppliers(logPage: number) {
+ this.api.externalSuppliers(logPage, this.sortBy, this.sortDir, this.perPage, this.searchText).subscribe(
+ result => {
+ this.supplierList = result.suppliers;
+ if (this.supplierList) {
+ this.supplierListAvailable = true;
+ }
+ this.paginateConfig.totalItems = result.page_no;
+ this.paginateConfig.currentPage = logPage;
+ },
+ error => {
+ console.log('Retrieval Error');
+ console.log( error._body );
+ }
+ );
+ }
+
+
+ sortName() { this.sortByColumn('name'); }
+ sortPostcode() { this.sortByColumn('postcode'); }
+ sortSpend() { this.sortByColumn('spend'); }
+
+ sortByColumn(name) {
+ this.sortBy = name;
+ this.sortDir = this.sortDir === 'asc' ? 'desc' : 'asc';
+ this.loadSuppliers(1);
+ }
+
+ searchSuppliers() {
+ // Go back to page 1 when searching
+ this.loadSuppliers(1);
+ }
+
+ ngAfterViewInit() {
+ }
+
+}
diff --git a/src/app/dashboard/trail-map.component.html b/src/app/dashboard/trail-map.component.html
index 3d29aeb..e2d3c53 100644
--- a/src/app/dashboard/trail-map.component.html
+++ b/src/app/dashboard/trail-map.component.html
@@ -3,8 +3,40 @@