Merge branch 'finn/wards' into development
This commit is contained in:
commit
bab670f60b
71 changed files with 8238 additions and 8054 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,7 +22,6 @@ $RECYCLE.BIN/
|
||||||
/bower_components
|
/bower_components
|
||||||
|
|
||||||
# IDEs and editors
|
# IDEs and editors
|
||||||
/.idea
|
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
*.launch
|
*.launch
|
||||||
|
|
3
.idea/.gitignore
vendored
Normal file
3
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
# Default ignored files
|
||||||
|
/workspace.xml
|
6
.idea/misc.xml
Normal file
6
.idea/misc.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/Foodloop-Web.iml" filepath="$PROJECT_DIR$/Foodloop-Web.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
12
Foodloop-Web.iml
Normal file
12
Foodloop-Web.iml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -112,9 +112,6 @@
|
||||||
"karmaConfig": "./karma.conf.js",
|
"karmaConfig": "./karma.conf.js",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "src/tsconfig.spec.json",
|
"tsConfig": "src/tsconfig.spec.json",
|
||||||
"scripts": [
|
|
||||||
"node_modules/moment/min/moment.min.js"
|
|
||||||
],
|
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/scss/style.scss"
|
"src/scss/style.scss"
|
||||||
],
|
],
|
||||||
|
|
12
browserslist
Normal file
12
browserslist
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||||
|
# For additional information regarding the format and rule options, please see:
|
||||||
|
# https://github.com/browserslist/browserslist#queries
|
||||||
|
|
||||||
|
# You can see what browsers were selected by your queries by running:
|
||||||
|
# npx browserslist
|
||||||
|
|
||||||
|
> 0.5%
|
||||||
|
last 2 versions
|
||||||
|
Firefox ESR
|
||||||
|
not dead
|
||||||
|
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
|
@ -7,6 +7,7 @@ module.exports = function (config) {
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
plugins: [
|
plugins: [
|
||||||
require('karma-jasmine'),
|
require('karma-jasmine'),
|
||||||
|
require("readable-stream");
|
||||||
require('karma-chrome-launcher'),
|
require('karma-chrome-launcher'),
|
||||||
require('karma-jasmine-html-reporter'),
|
require('karma-jasmine-html-reporter'),
|
||||||
require('karma-coverage-istanbul-reporter'),
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
|
13959
package-lock.json
generated
13959
package-lock.json
generated
File diff suppressed because it is too large
Load diff
94
package.json
94
package.json
|
@ -8,6 +8,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
|
"start:dev": "ng serve --optimization=false --configuration=dev",
|
||||||
|
"start:local": "ng serve --optimization=false --configuration=local",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"test:ci": "ng test --watch=false",
|
"test:ci": "ng test --watch=false",
|
||||||
|
@ -18,51 +20,65 @@
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agm/core": "1.0.0-beta.3",
|
"@agm/core": "1.0.0-beta.6",
|
||||||
"@agm/js-marker-clusterer": "1.0.0-beta.3",
|
"@agm/js-marker-clusterer": "1.0.0-beta.6",
|
||||||
"@angular/common": "6.0.3",
|
"@angular/common": "8.1.0",
|
||||||
"@angular/compiler": "6.0.3",
|
"@angular/compiler": "8.1.0",
|
||||||
"@angular/core": "6.0.3",
|
"@angular/core": "8.1.0",
|
||||||
"@angular/forms": "6.0.3",
|
"@angular/forms": "8.1.0",
|
||||||
"@angular/platform-browser": "6.0.3",
|
"@angular/platform-browser": "8.1.0",
|
||||||
"@angular/platform-browser-dynamic": "6.0.3",
|
"@angular/platform-browser-dynamic": "8.1.0",
|
||||||
"@angular/router": "6.0.3",
|
"@angular/router": "8.1.0",
|
||||||
"@angular/upgrade": "6.0.3",
|
"@angular/upgrade": "8.1.0",
|
||||||
"@types/moment": "2.13.0",
|
"@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1",
|
||||||
"chart.js": "^2.7.2",
|
"@coreui/icons": "0.3.0",
|
||||||
"core-js": "^2.5.7",
|
"ajv": "^6.10.0",
|
||||||
"jasmine": "^3.1.0",
|
"ajv-keywords": "^3.4.0",
|
||||||
|
"angular2-datetimepicker": "^1.1.1",
|
||||||
|
"chart.js": "^2.8.0",
|
||||||
|
"chartjs-adapter-luxon": "^0.2.0",
|
||||||
|
"core-js": "^2.6.9",
|
||||||
|
"devextreme": "^19.1.4",
|
||||||
|
"devextreme-angular": "^19.1.4",
|
||||||
|
"jasmine": "^3.4.0",
|
||||||
|
"jquery": "^3.3.1",
|
||||||
"js-marker-clusterer": "1.0.0",
|
"js-marker-clusterer": "1.0.0",
|
||||||
"moment": "^2.22.2",
|
"jszip": "^3.2.2",
|
||||||
"ng2-charts": "1.6.0",
|
"luxon": "^1.16.1",
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"ng2-charts": "^2.3.0",
|
||||||
"ng2-validation-manager": "0.5.3",
|
"ng2-validation-manager": "0.5.3",
|
||||||
"ngx-bootstrap": "^2.0.5",
|
"ngx-bootstrap": "^5.0.0",
|
||||||
"ngx-pagination": "^3.1.1",
|
"ngx-filter-pipe": "^2.1.2",
|
||||||
"rxjs": "6.2.0",
|
"ngx-pagination": "^4.0.0",
|
||||||
"rxjs-compat": "^6.2.0",
|
"popper.js": "^1.15.0",
|
||||||
|
"rxjs": "6.5.2",
|
||||||
|
"stream": "0.0.2",
|
||||||
"ts-helpers": "1.1.2",
|
"ts-helpers": "1.1.2",
|
||||||
"webpack-dev-server": "^3.1.4",
|
"tslib": "^1.10.0",
|
||||||
"zone.js": "0.8.26"
|
"web-animations-js": "^2.3.2",
|
||||||
|
"webpack-dev-server": "^3.7.2",
|
||||||
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.6.6",
|
"@angular-devkit/build-angular": "~0.801.0",
|
||||||
"@angular/cli": "^6.0.7",
|
"@angular/cli": "^8.1.0",
|
||||||
"@angular/compiler-cli": "6.0.3",
|
"@angular/compiler-cli": "8.1.0",
|
||||||
"@types/jasmine": "2.8.2",
|
"@types/jasmine": "3.3.13",
|
||||||
"@types/jasminewd2": "2.0.3",
|
"@types/jasminewd2": "2.0.6",
|
||||||
"@types/node": "8.0.52",
|
"@types/node": "12.0.10",
|
||||||
"codelyzer": "^4.3.0",
|
"codelyzer": "^5.1.0",
|
||||||
"jasmine-core": "^3.1.0",
|
"jasmine-core": "^3.4.0",
|
||||||
"jasmine-spec-reporter": "4.2.1",
|
"jasmine-spec-reporter": "4.2.1",
|
||||||
"karma": "^2.0.2",
|
"karma": "^4.1.0",
|
||||||
"karma-chrome-launcher": "2.2.0",
|
"karma-chrome-launcher": "2.2.0",
|
||||||
"karma-cli": "1.0.1",
|
"karma-cli": "2.0.0",
|
||||||
"karma-coverage-istanbul-reporter": "^2.0.1",
|
"karma-coverage-istanbul-reporter": "^2.0.5",
|
||||||
"karma-jasmine": "^1.1.2",
|
"karma-jasmine": "^2.0.1",
|
||||||
"karma-jasmine-html-reporter": "^1.1.0",
|
"karma-jasmine-html-reporter": "^1.4.2",
|
||||||
"protractor": "^5.3.2",
|
"protractor": "^5.4.2",
|
||||||
"ts-node": "^6.1.0",
|
"ts-node": "^8.3.0",
|
||||||
"tslint": "^5.10.0",
|
"tslint": "^5.18.0",
|
||||||
"typescript": "2.7.2"
|
"typescript": "~3.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||||
|
@ -27,6 +28,7 @@ import { CustGraphsService } from './providers/cust-graphs.service';
|
||||||
import { OrgSnippetsService } from './providers/org-snippets.service';
|
import { OrgSnippetsService } from './providers/org-snippets.service';
|
||||||
import { CustSnippetsService } from './providers/cust-snippets.service';
|
import { CustSnippetsService } from './providers/cust-snippets.service';
|
||||||
import { CustPiesService } from './providers/cust-pies.service';
|
import { CustPiesService } from './providers/cust-pies.service';
|
||||||
|
import { OrgPiesService } from './providers/org-pies.service';
|
||||||
|
|
||||||
// Layouts
|
// Layouts
|
||||||
import { FullLayoutComponent } from './layouts/full-layout.component';
|
import { FullLayoutComponent } from './layouts/full-layout.component';
|
||||||
|
@ -39,23 +41,30 @@ import { P500Component } from './pages/500.component';
|
||||||
// Submodules
|
// Submodules
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { DashboardModule } from './dashboard/dashboard.module';
|
import { DashboardModule } from './dashboard/dashboard.module';
|
||||||
|
import { ChartsModule } from 'ng2-charts';
|
||||||
|
// import { StackedBarChartComponent } from './panels/stacked-bar.component';
|
||||||
|
import { FilterPipeModule } from 'ngx-filter-pipe';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
FormsModule,
|
||||||
|
FilterPipeModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
NgxPaginationModule,
|
NgxPaginationModule,
|
||||||
BsDropdownModule.forRoot(),
|
BsDropdownModule.forRoot(),
|
||||||
TabsModule.forRoot(),
|
TabsModule.forRoot(),
|
||||||
AuthModule,
|
AuthModule,
|
||||||
|
ChartsModule,
|
||||||
DashboardModule,
|
DashboardModule,
|
||||||
// Loaded last to allow for 404 catchall
|
// Loaded last to allow for 404 catchall
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
// StackedBarChartComponent,
|
||||||
FullLayoutComponent,
|
FullLayoutComponent,
|
||||||
SimpleLayoutComponent,
|
SimpleLayoutComponent,
|
||||||
NAV_DROPDOWN_DIRECTIVES,
|
NAV_DROPDOWN_DIRECTIVES,
|
||||||
|
@ -75,6 +84,7 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
||||||
CustGraphsService,
|
CustGraphsService,
|
||||||
CustSnippetsService,
|
CustSnippetsService,
|
||||||
CustPiesService,
|
CustPiesService,
|
||||||
|
OrgPiesService,
|
||||||
{
|
{
|
||||||
provide: LocationStrategy,
|
provide: LocationStrategy,
|
||||||
useClass: HashLocationStrategy
|
useClass: HashLocationStrategy
|
||||||
|
|
|
@ -40,15 +40,11 @@ export class LoginComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
console.log(this.signin.value);
|
|
||||||
|
|
||||||
this.api
|
this.api
|
||||||
.login(this.signin.value)
|
.login(this.signin.value)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
result => {
|
result => {
|
||||||
console.log('logged in!');
|
|
||||||
this.loginStatus = 'success';
|
this.loginStatus = 'success';
|
||||||
console.log(this.loginStatus);
|
|
||||||
this.router.navigate([this.returnUrl]);
|
this.router.navigate([this.returnUrl]);
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
|
|
@ -116,7 +116,6 @@ export class RegisterComponent {
|
||||||
town: organisationForm.town,
|
town: organisationForm.town,
|
||||||
postcode: organisationForm.postcode,
|
postcode: organisationForm.postcode,
|
||||||
};
|
};
|
||||||
console.log(data);
|
|
||||||
this.api
|
this.api
|
||||||
.register(data)
|
.register(data)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
|
|
|
@ -24,13 +24,14 @@
|
||||||
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input">Essential Purchase</label>
|
<label class="col-md-3 form-control-label" for="text-input">Essential Purchase</label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="checkbox" class="mr-auto" [(ngModel)]="essentialPurchase" (ngModelChange)="transactionFormValidate()">
|
<input type="checkbox" class="mr-auto" [(ngModel)]="essentialPurchase" (ngModelChange)="transactionFormValidate()">
|
||||||
|
<span class="help-block">Tick if the purchase is deemed an essential purchase for budgeting purposes.</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="help-block">Tick if the purchase is deemed an essential purchase for budgeting purposes.</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
|
@ -38,8 +39,8 @@
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="checkbox" class="mr-auto" [(ngModel)]="recurringPurchase" (ngModelChange)="transactionFormValidate()">
|
<input type="checkbox" class="mr-auto" [(ngModel)]="recurringPurchase" (ngModelChange)="transactionFormValidate()">
|
||||||
|
<span class="help-block">Tick if the purchase frequently recurs, such as monthly.</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="help-block">Tick if the purchase frequently recurs, such as monthly.</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="recurringPurchase" class="form-group row">
|
<div *ngIf="recurringPurchase" class="form-group row">
|
||||||
|
@ -156,14 +157,14 @@
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input type="number" class="form-control" formControlName="employee_amount" placeholder="0">
|
<input type="number" class="form-control" formControlName="employee_amount" placeholder="0" min="0">
|
||||||
<span class="help-block">Enter the amount of employees the organisation has for the entry month.</span>
|
<span class="help-block">Enter the amount of employees the organisation has for the entry month.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input type="number" class="form-control" formControlName="local_employee_amount" placeholder="0">
|
<input type="number" class="form-control" formControlName="local_employee_amount" placeholder="0" min="0">
|
||||||
<span class="help-block">Enter the amount of employees that live locally to the organisation for the entry month.</span>
|
<span class="help-block">Enter the amount of employees that live locally to the organisation for the entry month.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<div class=row>
|
<div class=row>
|
||||||
<div class="col-md-6">
|
<div *ngIf="weekList1" class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div class="col-md-6">
|
<div *ngIf="weekList2" class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div class="col-md-6">
|
<div *ngIf="weekList3" class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -126,7 +126,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div class="col-md-6">
|
<div *ngIf="weekList4" class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -12,29 +12,34 @@
|
||||||
</div><!--/.row-->
|
</div><!--/.row-->
|
||||||
<div class=row>
|
<div class=row>
|
||||||
<div class="col-xl-6">
|
<div class="col-xl-6">
|
||||||
<panel-pie></panel-pie>
|
<panel-pie></panel-pie><!--All Purchases -->
|
||||||
</div><!--/.col-->
|
<!-- <div class="demo-container" ng-app="stacked-bar" ng-controller="stacked-bar">
|
||||||
<div *ngIf="showCategoryDoughnutChart" class="col-xl-6">
|
<div id="stacked-bar" dx-chart="chartOptions"></div>
|
||||||
<div class="card">
|
</div> -->
|
||||||
<div class="card-block">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<h4 class="card-title mb-0">Weekly Spending by Category</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="chart-wrapper">
|
|
||||||
<canvas baseChart class="chart"
|
|
||||||
[datasets]="doughnutChartDataCategory"
|
|
||||||
[labels]="doughnutChartLabelsCategory"
|
|
||||||
[options]="doughnutChartOptionsCategory"
|
|
||||||
[legend]="chartLegend"
|
|
||||||
[chartType]="chartType"
|
|
||||||
(chartHover)="chartHovered($event)"
|
|
||||||
(chartClick)="chartClicked($event)"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
|
<!--<div *ngIf="showCategoryDoughnutChart" class="col-xl-6">
|
||||||
|
<div class="card"> -->
|
||||||
|
<!-- <body style="background-color:rgb(0,0,0);"> -->
|
||||||
|
<!-- <div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">Spending by Category</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="doughnutChartDataCategory"
|
||||||
|
[labels]="doughnutChartLabelsCategory"
|
||||||
|
[options]="doughnutChartOptionsCategory"
|
||||||
|
[colors]= "doughnutChartColoursCategory"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<!-- </body> -->
|
||||||
|
<!-- </div> --><!--/.col-->
|
||||||
<div *ngIf="showEssentialBarChart" class="col-xl-6">
|
<div *ngIf="showEssentialBarChart" class="col-xl-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
|
@ -55,19 +60,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div *ngIf="showCategoryBarChart" class="col-xl-6">
|
<div class="col-xl-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title mb-0">Monthly Spending by Category</h4>
|
<h4 class="card-title float-left mb-0">Your Purchases by Category</h4>
|
||||||
</div>
|
</div><!--/.col-->
|
||||||
</div>
|
</div><!--/.row-->
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart
|
<canvas baseChart class="chart"
|
||||||
[datasets]="barChartDataCategory"
|
[datasets]="barChartDataCategory"
|
||||||
[labels]="barChartLabelsCategory"
|
[labels]="barChartLabelsCategory"
|
||||||
[options]="barChartOptionsCategory"
|
[options]="barChartOptionsCategory"
|
||||||
|
[colors]="barChartColoursCategory"
|
||||||
[legend]="barChartLegendCategory"
|
[legend]="barChartLegendCategory"
|
||||||
[chartType]="barChartTypeCategory"
|
[chartType]="barChartTypeCategory"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
|
@ -81,88 +87,29 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0">Weekly Purchase No.</h4>
|
<h4 class="card-title float-left mb-0"> Global Puchases by Category</h4>
|
||||||
</div><!--/.col-->
|
</div>
|
||||||
</div><!--/.row-->
|
|
||||||
<div class="chart-wrapper">
|
|
||||||
<ul class="horizontal-bars type-2">
|
|
||||||
<li>
|
|
||||||
<span class="title">This Week</span>
|
|
||||||
<span class="value">{{ (weekPurchaseList.first || 0 ) }} <span class="text-muted small">
|
|
||||||
({{ (weekPurchaseList.first || 0 ) / weekPurchaseList.max | percent:'1.0-0' }})</span></span>
|
|
||||||
<div class="bars">
|
|
||||||
<div class="progress" style="height: 6px;">
|
|
||||||
<div class="progress-bar bg-success" role="progressbar"
|
|
||||||
[style.width]="(weekPurchaseList.first || 0 ) / weekPurchaseList.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="title">Last Week</span>
|
|
||||||
<span class="value">{{ weekPurchaseList.second || 0 }} <span class="text-muted small">
|
|
||||||
({{ (weekPurchaseList.second || 0 ) / weekPurchaseList.max | percent:'1.0-0' }})</span></span>
|
|
||||||
<div class="bars">
|
|
||||||
<div class="progress" style="height: 6px;">
|
|
||||||
<div class="progress-bar bg-success" role="progressbar"
|
|
||||||
[style.width]="(weekPurchaseList.second || 0 ) / weekPurchaseList.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="title">Week Maximum</span>
|
|
||||||
<span class="value">{{ weekPurchaseList.max || 0 }} <span class="text-muted small">
|
|
||||||
(100%)</span></span>
|
|
||||||
<div class="bars">
|
|
||||||
<div class="progress" style="height: 6px;">
|
|
||||||
<div class="progress-bar bg-success" role="progressbar"
|
|
||||||
style="width: 100%" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="title">Weekly Average</span>
|
|
||||||
<span class="value">{{ (weekPurchaseList.sum / weekPurchaseList.count) || 0 | number:'1.0-0'}} <span class="text-muted small">
|
|
||||||
({{ ((weekPurchaseList.sum / weekPurchaseList.count) || 0) / weekPurchaseList.max | percent:'1.0-0' }})</span></span>
|
|
||||||
<div class="bars">
|
|
||||||
<div class="progress" style="height: 6px;">
|
|
||||||
<div class="progress-bar bg-success" role="progressbar"
|
|
||||||
[style.width]="((weekPurchaseList.sum / weekPurchaseList.count) || 0) / weekPurchaseList.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div><!--/.col-->
|
|
||||||
<div class="col-xl-6">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-block">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0">All Purchases by Category</h4>
|
<div *ngIf="showTotalCategoryList" class="chart-wrapper">
|
||||||
</div><!--/.col-->
|
<ul class="icons-list">
|
||||||
</div><!--/.row-->
|
<!-- New loop -->
|
||||||
<div class="chart-wrapper">
|
<li *ngFor="let category of totalCategoryList | slice:0:totalCategoryLimit; let i=index">
|
||||||
<ul class="icons-list">
|
<i [ngClass]="['icon-' + category.icon, getBootstrapColour(i)]"></i>
|
||||||
<!-- New loop -->
|
<div class="desc">
|
||||||
<li *ngFor="let category of totalCategoryList | slice:0:totalCategoryLimit; let i=index">
|
<div class="title">{{ category.category || 'N/A' }}</div>
|
||||||
<i [ngClass]="['icon-' + category.icon, getBootstrapColour(i)]"></i>
|
</div>
|
||||||
<div class="desc">
|
<div class="value">
|
||||||
<div class="title">{{ category.category || 'N/A' }}</div>
|
<div class="small text-muted">Bought</div>
|
||||||
</div>
|
<strong>{{ category.value || 'N/A' }}</strong>
|
||||||
<div class="value">
|
</div>
|
||||||
<div class="small text-muted">Bought</div>
|
</li>
|
||||||
<strong>{{ category.value || 'N/A' }}</strong>
|
<li *ngIf="totalCategoryList.length > totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
|
||||||
</div>
|
<button type="button" class="btn btn-sm btn-link text-muted" (click)="categoryLoadMore()"><i class="icon-options"></i></button>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="totalCategoryList.length > totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
|
</ul>
|
||||||
<button type="button" class="btn btn-sm btn-link text-muted" (click)="categoryLoadMore()"><i class="icon-options"></i></button>
|
</div>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div><!--/.row-->
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div>
|
||||||
</div><!--/.row-->
|
</div>
|
||||||
</div>
|
|
||||||
|
|
|
@ -2,12 +2,19 @@ import { Directive, Component, OnInit } from '@angular/core';
|
||||||
import { CurrencyPipe } from '@angular/common';
|
import { CurrencyPipe } from '@angular/common';
|
||||||
import { ApiService } from '../providers/api-service';
|
import { ApiService } from '../providers/api-service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
||||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
|
import { Color, Label } from 'ng2-charts';
|
||||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||||
import { PiePanel } from '../panels/pie-panel.component';
|
import { PiePanel } from '../panels/pie-panel.component';
|
||||||
import { DataType } from '../shared/data-types.enum';
|
import { DataType } from '../shared/data-types.enum';
|
||||||
import * as moment from 'moment';
|
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({
|
@Component({
|
||||||
templateUrl: 'dashboard-customer.component.html'
|
templateUrl: 'dashboard-customer.component.html'
|
||||||
|
@ -32,6 +39,22 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataCategory: any[] = [];
|
public doughnutChartDataCategory: any[] = [];
|
||||||
public doughnutChartLabelsCategory: string[] = [];
|
public doughnutChartLabelsCategory: string[] = [];
|
||||||
|
public doughnutChartColoursCategory: any[] = [
|
||||||
|
{
|
||||||
|
backgroundColor:[
|
||||||
|
'#ffa1b5',
|
||||||
|
'#3cde52',
|
||||||
|
'#52afed',
|
||||||
|
'#c133e3',
|
||||||
|
'#f7fa08',
|
||||||
|
'#75152d',
|
||||||
|
'#ee12ee',
|
||||||
|
'#15eaea',
|
||||||
|
'#eaa015',
|
||||||
|
'#ea1515',
|
||||||
|
'#2d4fcc'
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
public doughnutChartOptionsCategory:any = {
|
public doughnutChartOptionsCategory:any = {
|
||||||
tooltips: {
|
tooltips: {
|
||||||
|
@ -62,11 +85,12 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
scales:{
|
scales:{
|
||||||
xAxes:[{
|
xAxes:[{
|
||||||
stacked:true
|
scaleLabel: {
|
||||||
|
display:true,
|
||||||
|
},
|
||||||
|
stacked:true,
|
||||||
|
|
||||||
}],
|
}],
|
||||||
yAxes:[{
|
|
||||||
stacked:true
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public barChartTypeEssential:string = 'horizontalBar';
|
public barChartTypeEssential:string = 'horizontalBar';
|
||||||
|
@ -94,6 +118,23 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
public barChartLegendCategory:boolean = false;
|
public barChartLegendCategory:boolean = false;
|
||||||
public barChartDataCategory:any[]=[];
|
public barChartDataCategory:any[]=[];
|
||||||
public barChartLabelsCategory:string[] = [];
|
public barChartLabelsCategory:string[] = [];
|
||||||
|
public barChartColoursCategory: any[] = [
|
||||||
|
{
|
||||||
|
backgroundColor:[
|
||||||
|
'#ffa1b5',
|
||||||
|
'#3cde52',
|
||||||
|
'#52afed',
|
||||||
|
'#c133e3',
|
||||||
|
'#f7fa08',
|
||||||
|
'#75152d',
|
||||||
|
'#ee12ee',
|
||||||
|
'#15eaea',
|
||||||
|
'#eaa015',
|
||||||
|
'#ea1515',
|
||||||
|
'#2d4fcc'
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
weekPurchaseList = {
|
weekPurchaseList = {
|
||||||
first: 0,
|
first: 0,
|
||||||
|
@ -107,6 +148,7 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
totalCategoryLimit: number = 10;
|
totalCategoryLimit: number = 10;
|
||||||
totalCategoryList: any[]=[];
|
totalCategoryList: any[]=[];
|
||||||
|
|
||||||
|
|
||||||
// Graph widgets
|
// Graph widgets
|
||||||
public widgetList = [
|
public widgetList = [
|
||||||
{
|
{
|
||||||
|
@ -148,7 +190,9 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
this.setWeekData(result);
|
this.setWeekData(result);
|
||||||
this.setChartData(result.data.cat_total);
|
this.setChartData(result.data.cat_total);
|
||||||
this.totalCategoryList = result.data.cat_list;
|
this.totalCategoryList = result.data.cat_list;
|
||||||
this.showTotalCategoryList = true;
|
if (this.totalCategoryList) {
|
||||||
|
this.showTotalCategoryList = true;
|
||||||
|
}
|
||||||
this.purchaseEssential = result.data.essentials.purchase_no_essential_total;
|
this.purchaseEssential = result.data.essentials.purchase_no_essential_total;
|
||||||
this.purchaseNotEssential = result.data.essentials.purchase_no_total - this.purchaseEssential;
|
this.purchaseNotEssential = result.data.essentials.purchase_no_total - this.purchaseEssential;
|
||||||
this.barChartDataEssential = [
|
this.barChartDataEssential = [
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<snippet-bar-org></snippet-bar-org>
|
<snippet-bar-org></snippet-bar-org>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -11,4 +12,102 @@
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
</div><!--/.row-->
|
</div><!--/.row-->
|
||||||
<panel-graph></panel-graph>
|
<panel-graph></panel-graph>
|
||||||
</div>
|
<div class=row>
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">Number of Essential Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="showEssentialBarChart" class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="barChartDataEssential"
|
||||||
|
[labels]="barChartLabelsEssential"
|
||||||
|
[options]="barChartOptionsEssential"
|
||||||
|
[chartType]="barChartTypeEssential"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!--/.col-->
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title float-left mb-0">All Organisation Purchases by Category</h4>
|
||||||
|
</div><!--/.col-->
|
||||||
|
</div><!--/.row-->
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="barChartDataCategory"
|
||||||
|
[labels]="barChartLabelsCategory"
|
||||||
|
[options]="barChartOptionsCategory"
|
||||||
|
[colors]="barChartColoursCategory"
|
||||||
|
[legend]="barChartLegendCategory"
|
||||||
|
[chartType]="barChartTypeCategory"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!--/.col-->
|
||||||
|
<div *ngIf="showCategoryDoughnutChart" class="col-xl-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">This weeks' spending by Category</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="doughnutChartDataCategory"
|
||||||
|
[labels]="doughnutChartLabelsCategory"
|
||||||
|
[options]="doughnutChartOptionsCategory"
|
||||||
|
[colors]="doughnutChartColoursCategory"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<org-pie-panel></org-pie-panel>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title float-left mb-0"> Global Puchases by Category</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div *ngIf="showTotalCategoryList" class="chart-wrapper">
|
||||||
|
<ul class="icons-list">
|
||||||
|
<!-- New loop -->
|
||||||
|
<li *ngFor="let category of totalCategoryList | slice:0:totalCategoryLimit; let i=index">
|
||||||
|
<i [ngClass]="['icon-' + category.icon, getBootstrapColour(i)]"></i>
|
||||||
|
<div class="desc">
|
||||||
|
<div class="title">{{ category.category || 'N/A' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="value">
|
||||||
|
<div class="small text-muted">Bought</div>
|
||||||
|
<strong>{{ category.value || 'N/A' }}</strong>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li *ngIf="totalCategoryList.length > totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
|
||||||
|
<button type="button" class="btn btn-sm btn-link text-muted" (click)="categoryLoadMore()"><i class="icon-options"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!--/.row-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {Router, NavigationEnd} 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 { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||||
import { GraphPanel } from '../panels/graph-panel.component';
|
import { GraphPanel } from '../panels/graph-panel.component';
|
||||||
|
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
||||||
import { DataType } from '../shared/data-types.enum';
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: 'dashboard.component.html'
|
templateUrl: 'dashboard.component.html'
|
||||||
|
@ -38,6 +44,13 @@ export class DashboardComponent {
|
||||||
title: 'Sales Last 30 Days',
|
title: 'Sales Last 30 Days',
|
||||||
dataType: DataType.currency,
|
dataType: DataType.currency,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'graph',
|
||||||
|
name: 'sales_last_quart',
|
||||||
|
icon: 'icon-diamond',
|
||||||
|
title: 'Sales Last Quart',
|
||||||
|
dataType: DataType.currency,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'graph',
|
type: 'graph',
|
||||||
name: 'purchases_last_7_days',
|
name: 'purchases_last_7_days',
|
||||||
|
@ -50,8 +63,194 @@ export class DashboardComponent {
|
||||||
title: 'Purchases Last 30 Days',
|
title: 'Purchases Last 30 Days',
|
||||||
dataType: DataType.currency,
|
dataType: DataType.currency,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'graph',
|
||||||
|
name: 'purchases_last_quart;',
|
||||||
|
title: 'Purchases Last Quart',
|
||||||
|
dataType: DataType.currency,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
constructor(private router: Router) {
|
|
||||||
|
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) {
|
if (environment.enableAnalytics) {
|
||||||
this.router.events.subscribe(event => {
|
this.router.events.subscribe(event => {
|
||||||
if (event instanceof NavigationEnd) {
|
if (event instanceof NavigationEnd) {
|
||||||
|
@ -60,5 +259,111 @@ export class DashboardComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
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<T, K extends keyof T>(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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
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 { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||||
import { NgxPaginationModule } from 'ngx-pagination';
|
import { NgxPaginationModule } from 'ngx-pagination';
|
||||||
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
||||||
|
@ -18,6 +18,8 @@ import { FeedbackComponent } from './feedback.component';
|
||||||
import { TransactionLogComponent } from './transaction-log.component';
|
import { TransactionLogComponent } from './transaction-log.component';
|
||||||
import { CategoryMonthComponent } from './category-month.component';
|
import { CategoryMonthComponent } from './category-month.component';
|
||||||
import { PayrollLogComponent } from './payroll-log.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 { LeaderboardComponent } from './leaderboard.component';
|
||||||
import { MapComponent } from './map.component';
|
import { MapComponent } from './map.component';
|
||||||
import { TrailMapComponent } from './trail-map.component';
|
import { TrailMapComponent } from './trail-map.component';
|
||||||
|
@ -26,7 +28,9 @@ import { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||||
import { GraphPanel } from '../panels/graph-panel.component';
|
import { GraphPanel } from '../panels/graph-panel.component';
|
||||||
|
import { BubbleChartComponent } from '../panels/bubble-panel.component';
|
||||||
import { PiePanel } from '../panels/pie-panel.component';
|
import { PiePanel } from '../panels/pie-panel.component';
|
||||||
|
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
||||||
|
|
||||||
import { DashboardRoutingModule } from './dashboard.routing';
|
import { DashboardRoutingModule } from './dashboard.routing';
|
||||||
import { OrgResultComponent } from '../shared/org-result.component';
|
import { OrgResultComponent } from '../shared/org-result.component';
|
||||||
|
@ -34,6 +38,9 @@ import { OrgTableComponent } from '../shared/org-table.component';
|
||||||
import { RecurResultComponent } from '../shared/recur-result.component';
|
import { RecurResultComponent } from '../shared/recur-result.component';
|
||||||
import { RecurTableComponent } from '../shared/recur-table.component';
|
import { RecurTableComponent } from '../shared/recur-table.component';
|
||||||
import { TransactionResultComponent } from '../shared/transaction-result.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 { PayrollResultComponent } from '../shared/payroll-result.component';
|
||||||
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
||||||
|
|
||||||
|
@ -68,6 +75,9 @@ import { environment } from '../../environments/environment';
|
||||||
TransactionLogComponent,
|
TransactionLogComponent,
|
||||||
CategoryMonthComponent,
|
CategoryMonthComponent,
|
||||||
TransactionResultComponent,
|
TransactionResultComponent,
|
||||||
|
SupplierResultComponent,
|
||||||
|
WardResultComponent,
|
||||||
|
MetaTypeResultComponent,
|
||||||
PayrollLogComponent,
|
PayrollLogComponent,
|
||||||
PayrollResultComponent,
|
PayrollResultComponent,
|
||||||
LeaderboardComponent,
|
LeaderboardComponent,
|
||||||
|
@ -80,6 +90,10 @@ import { environment } from '../../environments/environment';
|
||||||
CustBarSnippetComponent,
|
CustBarSnippetComponent,
|
||||||
GraphPanel,
|
GraphPanel,
|
||||||
PiePanel,
|
PiePanel,
|
||||||
|
OrgPiePanel,
|
||||||
|
BubbleChartComponent,
|
||||||
|
SuppliersComponent,
|
||||||
|
MoreStuffComponent,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CurrencyPipe,
|
CurrencyPipe,
|
||||||
|
|
|
@ -17,6 +17,8 @@ import { PayrollLogComponent } from './payroll-log.component';
|
||||||
import { LeaderboardComponent } from './leaderboard.component';
|
import { LeaderboardComponent } from './leaderboard.component';
|
||||||
import { MapComponent } from './map.component';
|
import { MapComponent } from './map.component';
|
||||||
import { TrailMapComponent } from './trail-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
|
// Using child path to allow for FullLayout theming
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
@ -84,6 +86,16 @@ const routes: Routes = [
|
||||||
path: 'feedback',
|
path: 'feedback',
|
||||||
component: FeedbackComponent,
|
component: FeedbackComponent,
|
||||||
data: { title: 'Give Feedback' },
|
data: { title: 'Give Feedback' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'suppliers',
|
||||||
|
component: SuppliersComponent,
|
||||||
|
data: { title: 'Suppliers' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'more-graphs-and-tables',
|
||||||
|
component: MoreStuffComponent,
|
||||||
|
data: { title: 'Infographics'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Position</th>
|
<th>Position</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Amount</th>
|
<th class="js-sort-number">Gross amount</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class LeaderboardComponent implements OnInit {
|
||||||
|
|
||||||
public paginateConfig: PaginationInstance = {
|
public paginateConfig: PaginationInstance = {
|
||||||
id: 'leadpaginate',
|
id: 'leadpaginate',
|
||||||
itemsPerPage: 10,
|
itemsPerPage: 20,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
totalItems: 0
|
totalItems: 0
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ export class LeaderboardComponent implements OnInit {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}org
|
||||||
|
|
||||||
// // dynamically changes the row style based on player's position
|
// // dynamically changes the row style based on player's position
|
||||||
// // for instance, top three player and the player him/herself should
|
// // for instance, top three player and the player him/herself should
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||||
templateUrl: 'map.component.html',
|
templateUrl: 'map.component.html',
|
||||||
})
|
})
|
||||||
export class MapComponent implements OnInit, AfterViewInit {
|
export class MapComponent implements OnInit, AfterViewInit {
|
||||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
@ViewChild('statusModal', { static: true }) myStatusModal: ModalDirective;
|
||||||
lat: number = 54.0466;
|
lat: number = 54.0466;
|
||||||
lng: number = -2.8007;
|
lng: number = -2.8007;
|
||||||
zoom: number = 12;
|
zoom: number = 12;
|
||||||
|
|
136
src/app/dashboard/more-graphs-and-tables.component.html
Normal file
136
src/app/dashboard/more-graphs-and-tables.component.html
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<div class="animated fadeIn">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Filter</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-block">
|
||||||
|
<form class="form-inline">
|
||||||
|
<label class="mr-2" for="filter-from">From</label>
|
||||||
|
<input id="filter-from" class="form-control" type="date" [(ngModel)]="filterFrom" name="from">
|
||||||
|
<label class="mx-2" for="filter-to">To</label>
|
||||||
|
<input class="form-control" id="filter-to" type="date" [(ngModel)]="filterTo" name="to">
|
||||||
|
<button type="submit" class="btn btn-primary ml-2" (click)="loadData()">Filter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<strong>Transaction Types</strong>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="metaTypeListAvailable" class="card-block">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Ward</th>
|
||||||
|
<th>Amount of Transactions</th>
|
||||||
|
<th>Sum of Transactions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr meta-type-result *ngFor="let type of metaTypeList" [type]="type"></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!metaTypeListAvailable" class="card-block">
|
||||||
|
No Data available.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<strong>Ward Spending</strong>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="wardListAvailable" class="card-block">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Ward</th>
|
||||||
|
<th>Amount of Transactions</th>
|
||||||
|
<th>Sum of Transactions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ward-result *ngFor="let ward of wardList" [ward]="ward"></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!wardListAvailable" class="card-block">
|
||||||
|
No Data available.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="animated fadeIn">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<h4 class="card-title mb-0">Supplier spend amount and number of purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small>vertical shows number of purchases, size of bubble shows the total spend amount, horizontal shows date</small>
|
||||||
|
<div class="col-sm-12" *ngIf="!isBubbleChartLoaded">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="isBubbleChartLoaded">
|
||||||
|
<canvas baseChart
|
||||||
|
[datasets]="supplierBubbleChartData"
|
||||||
|
[options]="supplierBubbleChartOptions"
|
||||||
|
[labels]="supplierBubbleChartLabels"
|
||||||
|
[legend]="showLegend"
|
||||||
|
[chartType]="supplierBubbleChartType">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h4 class="card-title mb-0">Spend & Number of Transactions</h4>
|
||||||
|
<small>Date against Value and Number of Transactions</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<canvas baseChart
|
||||||
|
[datasets]="yearSpendChartData"
|
||||||
|
[options]="yearSpendChartOptions"
|
||||||
|
[labels]="yearSpendChartLabels"
|
||||||
|
[legend]="showLegend"
|
||||||
|
[chartType]="yearSpendChartType">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h4 class="card-title mb-0">Supplier Spend History</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 hidden-sm-down">
|
||||||
|
<button type="button" class="btn btn-danger" (click)="previousSupplierHistoryPage()">Previous Page</button>
|
||||||
|
<button type="button" class="btn btn-info" (click)="nextSupplierHistoryPage()">Next Page</button>
|
||||||
|
<span class="ml-2">Page {{ _supplierHistoryPage }} of {{ _supplierHistoryPages }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="isSupplierChartLoaded">
|
||||||
|
<canvas baseChart #supplierChart
|
||||||
|
[datasets]="supplierMonthChartData"
|
||||||
|
[options]="supplierMonthChartOptions"
|
||||||
|
[labels]="supplierMonthChartLabels"
|
||||||
|
[legend]="showLegend"
|
||||||
|
[chartType]="supplierMonthChartType">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
335
src/app/dashboard/more-graphs-and-tables.component.ts
Normal file
335
src/app/dashboard/more-graphs-and-tables.component.ts
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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;
|
||||||
|
private _supplierHistoryPage: number = 1;
|
||||||
|
private _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';
|
||||||
|
}
|
79
src/app/dashboard/suppliers.component.html
Normal file
79
src/app/dashboard/suppliers.component.html
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<div class="animated fadeIn">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Search Suppliers</h4>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="supplierListAvailable" class="card-block">
|
||||||
|
<div class="input-group">
|
||||||
|
<input class="form-control" type="text" name="search" [(ngModel)]="searchText" autocomplete="off"
|
||||||
|
placeholder="Search by Name or Postcode" (keydown.enter)="searchSuppliers()">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-primary" (click)="searchSuppliers()">Search</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="animated fadeIn">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>List of Suppliers</h4>
|
||||||
|
<div class="small">Click on Column Headers to change Sort Order</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="supplierListAvailable" class="card-block">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th (click)="sortName()">Name <span class="fa-stack">
|
||||||
|
<i *ngIf="sortBy !== 'name' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
||||||
|
<i *ngIf="sortBy !== 'name' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
||||||
|
</span></th>
|
||||||
|
<th (click)="sortPostcode()">Postcode <span class="fa-stack">
|
||||||
|
<i *ngIf="sortBy !== 'postcode' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
||||||
|
<i *ngIf="sortBy !== 'postcode' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
||||||
|
</span></th>
|
||||||
|
<th (click)="sortSpend()">Spend <span class="fa-stack">
|
||||||
|
<i *ngIf="sortBy !== 'spend' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
||||||
|
<i *ngIf="sortBy !== 'spend' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
||||||
|
</span></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr supplier-result *ngFor="let supplier of supplierList | paginate: paginateConfig"
|
||||||
|
[supplier]="supplier"></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<pagination-template #p="paginationApi"
|
||||||
|
[id]="paginateConfig.id"
|
||||||
|
(pageChange)="loadSuppliers($event)">
|
||||||
|
<ul class="pagination">
|
||||||
|
<li class="page-item" [class.disabled]="p.isFirstPage()">
|
||||||
|
<a class="page-link clickable" *ngIf="!p.isFirstPage()" (click)="p.previous()">Prev</a>
|
||||||
|
</li>
|
||||||
|
<li *ngFor="let page of p.pages" class="page-item" [class.active]="p.getCurrent() === page.value">
|
||||||
|
<a class="page-link clickable" (click)="p.setCurrent(page.value)" *ngIf="p.getCurrent() !== page.value">
|
||||||
|
<span>{{ page.label }}</span>
|
||||||
|
</a>
|
||||||
|
<div class="page-link" *ngIf="p.getCurrent() === page.value">
|
||||||
|
<span>{{ page.label }}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="page-item" [class.disabled]="p.isLastPage()">
|
||||||
|
<a class="page-link clickable" *ngIf="!p.isLastPage()" (click)="p.next()">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</pagination-template>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!supplierListAvailable" class="card-block">
|
||||||
|
No Suppliers available.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
74
src/app/dashboard/suppliers.component.ts
Normal file
74
src/app/dashboard/suppliers.component.ts
Normal file
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||||
templateUrl: 'trail-map.component.html',
|
templateUrl: 'trail-map.component.html',
|
||||||
})
|
})
|
||||||
export class TrailMapComponent implements OnInit, AfterViewInit {
|
export class TrailMapComponent implements OnInit, AfterViewInit {
|
||||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
@ViewChild('statusModal', { static: true }) myStatusModal: ModalDirective;
|
||||||
lat: number = 54.0466;
|
lat: number = 54.0466;
|
||||||
lng: number = -2.8007;
|
lng: number = -2.8007;
|
||||||
zoom: number = 12;
|
zoom: number = 12;
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer d-flex justify-content-between">
|
<div class="modal-footer d-flex justify-content-between">
|
||||||
<button type="submit" (click)="deleteRecurringTransaction()" class="btn btn-sm btn-danger"><i class="fa fa-times"></i> Delete</button>
|
<button type="submit" (click)="deleteRecurringTransaction()" class="btn btn-sm btn-danger"><i class="fa fa-times"></i> Delete</button>
|
||||||
<button type="submit" (click)="editRecurringTransaction()" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Edit</button>
|
<button type="submit" (click)="editRecurringTransaction()" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Save</button>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,18 +101,24 @@
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<strong>Log of Outgoing Transactions</strong>
|
<strong>Log of Outgoing Transactions</strong>
|
||||||
<small>This lists all purchases that have been submitted.</small>
|
<small>This lists all purchases that have been submitted.</small>
|
||||||
|
<button class="btn pull-right btn-sm" (click)="toggleShowMeta()">
|
||||||
|
<span *ngIf="!showMeta">Show</span><span *ngIf="showMeta">Hide</span> Details
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!noTransactionList" class="card-block">
|
<div *ngIf="!noTransactionList" class="card-block">
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Seller</th>
|
<th>Seller</th>
|
||||||
<th>Value</th>
|
<th *ngIf="!showMeta">Value</th>
|
||||||
|
<th *ngIf="showMeta">Net Value</th>
|
||||||
|
<th *ngIf="showMeta">Sales Tax Value</th>
|
||||||
|
<th *ngIf="showMeta">Gross Value</th>
|
||||||
<th>Purchase Time</th>
|
<th>Purchase Time</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr transaction-result *ngFor="let transaction of transactionList | paginate: paginateConfig" [transaction]="transaction"></tr>
|
<tr transaction-result *ngFor="let transaction of transactionList | paginate: paginateConfig" [transaction]="transaction" [showMeta]="showMeta"></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<pagination-template #p="paginationApi"
|
<pagination-template #p="paginationApi"
|
||||||
|
|
|
@ -29,13 +29,14 @@ export class TransactionLogComponent implements OnInit {
|
||||||
transactionFormStatusSuccess: string;
|
transactionFormStatusSuccess: string;
|
||||||
transactionFormStatusError = 'Error received, please try again.';
|
transactionFormStatusError = 'Error received, please try again.';
|
||||||
updatedTime: string;
|
updatedTime: string;
|
||||||
|
showMeta = false;
|
||||||
|
|
||||||
public paginateConfig: PaginationInstance = {
|
public paginateConfig: PaginationInstance = {
|
||||||
id: 'transpaginate',
|
id: 'transpaginate',
|
||||||
itemsPerPage: 10,
|
itemsPerPage: 10,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
totalItems: 0
|
totalItems: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
|
@ -87,6 +88,7 @@ export class TransactionLogComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
recurringTransactionDetails(clicked, template: TemplateRef<any>) {
|
recurringTransactionDetails(clicked, template: TemplateRef<any>) {
|
||||||
this.clickedRecur = clicked;
|
this.clickedRecur = clicked;
|
||||||
this.updatedTime = moment(this.clickedRecur.display_time, 'llll').format('YYYY-MM-DD[T]HH:mm');
|
this.updatedTime = moment(this.clickedRecur.display_time, 'llll').format('YYYY-MM-DD[T]HH:mm');
|
||||||
|
@ -161,4 +163,7 @@ export class TransactionLogComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleShowMeta() {
|
||||||
|
this.showMeta = !this.showMeta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/more-graphs-and-tables']">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col-2"><i class="icon-map"></i></div>
|
||||||
|
<div class="col-10">Infographics</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
|
@ -94,14 +102,22 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/payroll-log']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/suppliers']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
<div class="col-2"><i class="icon-basket"></i></div>
|
<div class="col-2"><i class="icon-speedometer"></i></div>
|
||||||
<div class="col-10">Payroll Log</div>
|
<div class="col-10">Suppliers</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
||||||
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/payroll-log']">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col-2"><i class="icon-basket"></i></div>
|
||||||
|
<div class="col-10">Payroll Log</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
13
src/app/panels/bubble-panel.component.html
Normal file
13
src/app/panels/bubble-panel.component.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div style="display: block">
|
||||||
|
<canvas baseChart
|
||||||
|
[datasets]="bubbleChartData"
|
||||||
|
[options]="bubbleChartOptions"
|
||||||
|
[colors]="bubbleChartColors"
|
||||||
|
[legend]="bubbleChartLegend"
|
||||||
|
[chartType]="bubbleChartType">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
97
src/app/panels/bubble-panel.component.ts
Normal file
97
src/app/panels/bubble-panel.component.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
||||||
|
import { Color } from 'ng2-charts';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-bubble-chart',
|
||||||
|
templateUrl: './bubble-panel.component.html',
|
||||||
|
})
|
||||||
|
export class BubbleChartComponent implements OnInit {
|
||||||
|
public bubbleChartOptions: ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
ticks: {
|
||||||
|
min: 0,
|
||||||
|
max: 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
ticks: {
|
||||||
|
min: 0,
|
||||||
|
max: 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public bubbleChartType: ChartType = 'bubble';
|
||||||
|
public bubbleChartLegend = true;
|
||||||
|
|
||||||
|
public bubbleChartData: ChartDataSets[] = [
|
||||||
|
{
|
||||||
|
data: [
|
||||||
|
{ x: 10, y: 10, r: 10 },
|
||||||
|
{ x: 15, y: 5, r: 15 },
|
||||||
|
{ x: 26, y: 12, r: 23 },
|
||||||
|
{ x: 7, y: 8, r: 8 },
|
||||||
|
],
|
||||||
|
label: 'Series A',
|
||||||
|
backgroundColor: 'green',
|
||||||
|
borderColor: 'blue',
|
||||||
|
hoverBackgroundColor: 'purple',
|
||||||
|
hoverBorderColor: 'red',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
public bubbleChartColors: Color[] = [
|
||||||
|
{
|
||||||
|
backgroundColor: [
|
||||||
|
'red',
|
||||||
|
'green',
|
||||||
|
'blue',
|
||||||
|
'purple',
|
||||||
|
'yellow',
|
||||||
|
'brown',
|
||||||
|
'magenta',
|
||||||
|
'cyan',
|
||||||
|
'orange',
|
||||||
|
'pink'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// events
|
||||||
|
public chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
private rand(max: number) {
|
||||||
|
return Math.trunc(Math.random() * max);
|
||||||
|
}
|
||||||
|
|
||||||
|
private randomPoint(maxCoordinate: number) {
|
||||||
|
const x = this.rand(maxCoordinate);
|
||||||
|
const y = this.rand(maxCoordinate);
|
||||||
|
const r = this.rand(30) + 5;
|
||||||
|
return { x, y, r };
|
||||||
|
}
|
||||||
|
|
||||||
|
public randomize(): void {
|
||||||
|
const numberOfPoints = this.rand(5) + 5;
|
||||||
|
const data = Array.apply(null, { length: numberOfPoints }).map(r => this.randomPoint(30));
|
||||||
|
this.bubbleChartData[0].data = data;
|
||||||
|
}
|
||||||
|
}
|
19
src/app/panels/candlestick.component.html
Normal file
19
src/app/panels/candlestick.component.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[data]="doughnutChartDataLocal"
|
||||||
|
[labels]="doughnutChartLabelsLocal"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
84
src/app/panels/candlestick.component.ts
Normal file
84
src/app/panels/candlestick.component.ts
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import 'dist/chartjs-chart-financial/chartjs-chart-financial';
|
||||||
|
import * as luxon from 'luxon';
|
||||||
|
import 'chartjs-adapter-luxon';
|
||||||
|
import { ChartOptions } from 'chart.js';
|
||||||
|
import { Color, BaseChartDirective } from 'ng2-charts';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-financial-chart',
|
||||||
|
templateUrl: './financial-chart.component.html',
|
||||||
|
styleUrls: ['./financial-chart.component.css']
|
||||||
|
})
|
||||||
|
export class FinancialChartComponent implements OnInit {
|
||||||
|
barCount = 60;
|
||||||
|
initialDateStr = '01 Apr 2017 00:00 Z';
|
||||||
|
|
||||||
|
public financialChartData = [
|
||||||
|
{
|
||||||
|
label: 'CHRT - Chart.js Corporation',
|
||||||
|
data: this.getRandomData(this.initialDateStr, this.barCount)
|
||||||
|
},
|
||||||
|
];
|
||||||
|
public financialChartOptions: ChartOptions = {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
};
|
||||||
|
public financialChartColors: Color[] = [
|
||||||
|
{
|
||||||
|
borderColor: 'black',
|
||||||
|
backgroundColor: 'rgba(255,0,0,0.3)',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
public financialChartLegend : Boolean;
|
||||||
|
public chartLegend : Boolean;
|
||||||
|
public financialChartType = 'candlestick';
|
||||||
|
public chartType : string;
|
||||||
|
public financialChartPlugins = [];
|
||||||
|
|
||||||
|
@ViewChild(BaseChartDirective, { static: true }) chart: BaseChartDirective;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.financialChartType = 'candlestick';
|
||||||
|
this.chartType=this.financialChartType;
|
||||||
|
|
||||||
|
this.financialChartLegend = this.chartLegend;
|
||||||
|
}
|
||||||
|
|
||||||
|
randomNumber(min: number, max: number) {
|
||||||
|
return Math.random() * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
randomBar(date: luxon.DateTime, lastClose: number) {
|
||||||
|
const open = this.randomNumber(lastClose * 0.95, lastClose * 1.05);
|
||||||
|
const close = this.randomNumber(open * 0.95, open * 1.05);
|
||||||
|
const high = this.randomNumber(Math.max(open, close), Math.max(open, close) * 1.1);
|
||||||
|
const low = this.randomNumber(Math.min(open, close) * 0.9, Math.min(open, close));
|
||||||
|
return {
|
||||||
|
t: date.valueOf(),
|
||||||
|
o: open,
|
||||||
|
h: high,
|
||||||
|
l: low,
|
||||||
|
c: close
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getRandomData(dateStr: string, count: number) {
|
||||||
|
let date = luxon.DateTime.fromRFC2822(dateStr);
|
||||||
|
const data = [this.randomBar(date, 30)];
|
||||||
|
while (data.length < count) {
|
||||||
|
date = date.plus({ days: 1 });
|
||||||
|
if (date.weekday <= 5) {
|
||||||
|
data.push(this.randomBar(date, data[data.length - 1].c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
// candlestick vs ohlc
|
||||||
|
this.financialChartType = this.financialChartType === 'candlestick' ? 'ohlc' : 'candlestick';
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,9 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-5">
|
<div class="col-sm-12">
|
||||||
<h4 class="card-title mb-0">Customers</h4>
|
<h4 class="card-title mb-0">Customers</h4>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div class="col-sm-7 hidden-sm-down">
|
|
||||||
<div class="btn-toolbar float-right" role="toolbar" aria-label="Toolbar with button groups">
|
|
||||||
<div class="btn-group mr-3" data-toggle="buttons" aria-label="First group">
|
|
||||||
<label class="btn btn-outline-secondary active">
|
|
||||||
<input type="radio" name="options" id="option2" checked> Week
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div><!--/.col-->
|
|
||||||
</div><!--/.row-->
|
</div><!--/.row-->
|
||||||
<div class="chart-wrapper" style="height:300px;margin-top:40px;">
|
<div class="chart-wrapper" style="height:300px;margin-top:40px;">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
|
|
|
@ -82,12 +82,12 @@ export class GraphPanel implements OnInit {
|
||||||
pointHoverBackgroundColor: '#fff'
|
pointHoverBackgroundColor: '#fff'
|
||||||
},
|
},
|
||||||
{ // brandSuccess
|
{ // brandSuccess
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: this.convertHex(this.brandInfo, 10),
|
||||||
borderColor: this.brandSuccess,
|
borderColor: this.brandSuccess,
|
||||||
pointHoverBackgroundColor: '#fff'
|
pointHoverBackgroundColor: '#fff'
|
||||||
},
|
},
|
||||||
{ // brandDanger
|
{ // brandDanger
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: this.convertHex(this.brandDanger, 10),
|
||||||
borderColor: this.brandDanger,
|
borderColor: this.brandDanger,
|
||||||
pointHoverBackgroundColor: '#fff',
|
pointHoverBackgroundColor: '#fff',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
|
19
src/app/panels/org-pie-panel.component.html
Normal file
19
src/app/panels/org-pie-panel.component.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">Global Purchases by Type</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[data]="doughnutChartDataLocal"
|
||||||
|
[labels]="doughnutChartLabelsLocal"
|
||||||
|
[colors]="doughnutChartColors"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
86
src/app/panels/org-pie-panel.component.ts
Normal file
86
src/app/panels/org-pie-panel.component.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
|
import { OrgPiesService } from '../providers/org-pies.service';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'org-pie-panel',
|
||||||
|
templateUrl: 'org-pie-panel.component.html',
|
||||||
|
})
|
||||||
|
|
||||||
|
export class OrgPiePanel implements OnInit {
|
||||||
|
|
||||||
|
public chartType = 'pie';
|
||||||
|
public chartLegend = true;
|
||||||
|
public doughnutChartDataLocal: number[] = [];
|
||||||
|
public doughnutChartColors: any[] = [
|
||||||
|
{
|
||||||
|
backgroundColor:[
|
||||||
|
'#ffa1b5',
|
||||||
|
'#3cde52',
|
||||||
|
'#52afed',
|
||||||
|
'#c133e3',
|
||||||
|
'#f7fa08',
|
||||||
|
'#75152d',
|
||||||
|
'#ee12ee',
|
||||||
|
'#15eaea',
|
||||||
|
'#eaa015',
|
||||||
|
'#ea1515',
|
||||||
|
'#2d4fcc'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
borderColor: [
|
||||||
|
'red',
|
||||||
|
'green',
|
||||||
|
'blue',
|
||||||
|
'purple',
|
||||||
|
'yellow',
|
||||||
|
'brown',
|
||||||
|
'magenta',
|
||||||
|
'cyan',
|
||||||
|
'orange',
|
||||||
|
'pink'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ borderWidth: [100]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
public doughnutChartLabelsLocal: string[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private pieService: OrgPiesService,
|
||||||
|
) {
|
||||||
|
this.pieService.getOrgPie().subscribe(
|
||||||
|
result => {
|
||||||
|
this.setChartData(result.local_all);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('Retrieval Error');
|
||||||
|
console.log( error._body );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private setChartData(dataLocal: any) {
|
||||||
|
this.doughnutChartDataLocal = Object.keys(dataLocal).map(key => dataLocal[key]);
|
||||||
|
// setTimeout is currently a workaround for ng2-charts labels
|
||||||
|
setTimeout(() => this.doughnutChartLabelsLocal = Object.keys(dataLocal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// events
|
||||||
|
public chartClicked(e: any): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public chartHovered(e: any): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title mb-0">All Purchases</h4>
|
<h4 class="card-title mb-0">All Purchases by Category</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
[data]="doughnutChartDataLocal"
|
[data]="doughnutChartDataLocal"
|
||||||
[labels]="doughnutChartLabelsLocal"
|
[labels]="doughnutChartLabelsLocal"
|
||||||
|
[colors]="doughnutChartColors"
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
[chartType]="chartType"
|
[chartType]="chartType"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
|
|
|
@ -9,12 +9,44 @@ import { ChartData } from '../_interfaces/chart-data';
|
||||||
selector: 'panel-pie',
|
selector: 'panel-pie',
|
||||||
templateUrl: 'pie-panel.component.html',
|
templateUrl: 'pie-panel.component.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class PiePanel implements OnInit {
|
export class PiePanel implements OnInit {
|
||||||
|
|
||||||
public chartType = 'doughnut';
|
public chartType = 'pie';
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataLocal: number[] = [];
|
public doughnutChartDataLocal: number[] = [];
|
||||||
public doughnutChartLabelsLocal: string[] = [];
|
public doughnutChartLabelsLocal: string[] = [];
|
||||||
|
public doughnutChartColors: any[] = [
|
||||||
|
{ backgroundColor: [
|
||||||
|
'#ffa1b5',
|
||||||
|
'#3cde52',
|
||||||
|
'#52afed',
|
||||||
|
'#c133e3',
|
||||||
|
'#f7fa08',
|
||||||
|
'#75152d',
|
||||||
|
'#ee12ee',
|
||||||
|
'#15eaea',
|
||||||
|
'#eaa015',
|
||||||
|
'#ea1515',
|
||||||
|
'#2d4fcc'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ borderColor:[
|
||||||
|
'red',
|
||||||
|
'green',
|
||||||
|
'blue',
|
||||||
|
'purple',
|
||||||
|
'yellow',
|
||||||
|
'brown',
|
||||||
|
'magenta',
|
||||||
|
'cyan',
|
||||||
|
'orange',
|
||||||
|
'pink'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ borderWidth: [10]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
|
|
19
src/app/panels/polar-panel.component.html
Normal file
19
src/app/panels/polar-panel.component.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[data]="doughnutChartDataLocal"
|
||||||
|
[labels]="doughnutChartLabelsLocal"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
72
src/app/panels/polar-panel.component.ts
Normal file
72
src/app/panels/polar-panel.component.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { SingleDataSet, Label } from 'ng2-charts';
|
||||||
|
import { ChartType } from 'chart.js';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
|
import { CustPiesService } from '../providers/cust-pies.service';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'polar-area',
|
||||||
|
templateUrl: 'polar-panel.component.html',
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PolarAreaChartComponent implements OnInit {
|
||||||
|
// PolarArea
|
||||||
|
|
||||||
|
public chartType : 'polar-area';
|
||||||
|
public polarAreaChartLabels: Label[];
|
||||||
|
public polarAreaChartData: SingleDataSet;
|
||||||
|
public chartLegend : Boolean;
|
||||||
|
public polarAreaLegend : Boolean;
|
||||||
|
|
||||||
|
public polarChartLabelsLocal: string[] = [];
|
||||||
|
public polarChartDataLocal: number[] = [];
|
||||||
|
|
||||||
|
public polarAreaChartType: ChartType = 'polarArea';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private pieService: CustPiesService,
|
||||||
|
) {
|
||||||
|
this.pieService.getPie().subscribe(
|
||||||
|
result => {
|
||||||
|
this.setChartData(result.local_all);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('Retrieval Error');
|
||||||
|
console.log( error._body );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.polarAreaLegend = this.chartLegend;
|
||||||
|
this.polarAreaLegend = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private setChartData(dataLocal: any) {
|
||||||
|
this.polarChartDataLocal = Object.keys(dataLocal).map(key => dataLocal[key]);
|
||||||
|
// setTimeout is currently a workaround for ng2-charts labels
|
||||||
|
setTimeout(() => this.polarChartLabelsLocal = Object.keys(dataLocal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// events
|
||||||
|
public chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
}
|
19
src/app/panels/stacked-bar.component.html.broken
Normal file
19
src/app/panels/stacked-bar.component.html.broken
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
attr.[data]="doughnutChartDataLocal"
|
||||||
|
attr.[labels]="doughnutChartLabelsLocal"
|
||||||
|
attr.[legend]="chartLegend"
|
||||||
|
attr.[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
68
src/app/panels/stacked-bar.component.ts.broken
Normal file
68
src/app/panels/stacked-bar.component.ts.broken
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { NgModule, enableProdMode } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
|
import { CustPiesService } from '../providers/cust-pies.service';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { DxChartModule } from 'devextreme-angular';
|
||||||
|
|
||||||
|
if(!/localhost/.test(document.location.host)) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'stacked-bar',
|
||||||
|
templateUrl: 'stacked-bar.component.html',
|
||||||
|
})
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
DxChartModule
|
||||||
|
],
|
||||||
|
declarations: [StackedBarChartComponent],
|
||||||
|
bootstrap: [StackedBarChartComponent]
|
||||||
|
})
|
||||||
|
export class StackedBarChartComponent {
|
||||||
|
|
||||||
|
public chartType: 'stacked-bar';
|
||||||
|
public chartLegend = true;
|
||||||
|
public stackedBarChartDataLocal : number[] = [];
|
||||||
|
public stackedBarChartLabelsLocal : string[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private pieService: CustPiesService,
|
||||||
|
) {
|
||||||
|
this.pieService.getPie().subscribe(
|
||||||
|
result => {
|
||||||
|
this.setChartData(result.local_all);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('Retrieval Error');
|
||||||
|
console.log( error._body );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
console.log("stacked bar graph tried to initialise");
|
||||||
|
}
|
||||||
|
|
||||||
|
private setChartData(dataLocal: any) {
|
||||||
|
this.stackedBarChartDataLocal = Object.keys(dataLocal).map(key => dataLocal[key]);
|
||||||
|
// setTimeout is currently a workaround for ng2-charts labels
|
||||||
|
setTimeout(() => this.stackedBarChartLabelsLocal = Object.keys(dataLocal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
customizeTooltip(arg: any) {
|
||||||
|
return {
|
||||||
|
text: arg.percentText + ' - ' + arg.valueText
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(StackedBarChartComponent);
|
|
@ -133,6 +133,43 @@ export class ApiService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LCC data
|
||||||
|
public externalTransactions() {
|
||||||
|
const key = this.sessionKey;
|
||||||
|
return this.http.post<any>(
|
||||||
|
this.apiUrl + '/v1/organisation/external/transactions',
|
||||||
|
{
|
||||||
|
session_key : key,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadMiscUrl(extra_url, extraArgs = {}) {
|
||||||
|
const key = this.sessionKey;
|
||||||
|
return this.http.post<any>(
|
||||||
|
this.apiUrl + '/v1/' + extra_url,
|
||||||
|
{
|
||||||
|
session_key : key,
|
||||||
|
...extraArgs,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public externalSuppliers(page, sortBy, sortDir, perPage, search) {
|
||||||
|
const key = this.sessionKey;
|
||||||
|
return this.http.post<any>(
|
||||||
|
this.apiUrl + '/v1/organisation/external/suppliers',
|
||||||
|
{
|
||||||
|
session_key : key,
|
||||||
|
page : page,
|
||||||
|
sort_by : sortBy,
|
||||||
|
sort_dir : sortDir,
|
||||||
|
per_page : perPage,
|
||||||
|
search : search,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Searches organisations used for transaction submission
|
// Searches organisations used for transaction submission
|
||||||
|
|
||||||
public search(data) {
|
public search(data) {
|
||||||
|
@ -324,4 +361,15 @@ export class ApiService {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Basic Customer User stats API
|
||||||
|
public orgStats() {
|
||||||
|
const key = this.sessionKey;
|
||||||
|
return this.http.post<any>(
|
||||||
|
this.apiUrl + '/stats/organisation',
|
||||||
|
{
|
||||||
|
session_key : key,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ApiService } from './api-service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OrgGraphsService {
|
export class OrgGraphsService {
|
||||||
private orgGraphUrl = '/v1/customer/graphs';
|
private orgGraphUrl = '/v1/organisation/graphs';
|
||||||
|
|
||||||
constructor(private api: ApiService) { }
|
constructor(private api: ApiService) { }
|
||||||
|
|
||||||
|
|
14
src/app/providers/org-pies.service.ts
Normal file
14
src/app/providers/org-pies.service.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ApiService } from './api-service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OrgPiesService {
|
||||||
|
private orgPieUrl = '/v1/organisation/pies';
|
||||||
|
|
||||||
|
constructor(private api: ApiService) { }
|
||||||
|
|
||||||
|
public getOrgPie(): Observable<any> {
|
||||||
|
return this.api.post(this.orgPieUrl);
|
||||||
|
}
|
||||||
|
}
|
3
src/app/shared/meta-type-result.component.html
Normal file
3
src/app/shared/meta-type-result.component.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<td>{{type.type}}</td>
|
||||||
|
<td>{{type.count}}</td>
|
||||||
|
<td>{{type.sum | currency:'GBP':'symbol':'1.2-2' }}</td>
|
19
src/app/shared/meta-type-result.component.ts
Normal file
19
src/app/shared/meta-type-result.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
interface MetaTypeData {
|
||||||
|
type: string;
|
||||||
|
sum: number;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// tslint:disable-next-line
|
||||||
|
selector: '[meta-type-result]',
|
||||||
|
templateUrl: 'meta-type-result.component.html',
|
||||||
|
})
|
||||||
|
export class MetaTypeResultComponent implements OnInit {
|
||||||
|
@Input() public type: MetaTypeData;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
}
|
3
src/app/shared/supplier-result.component.html
Normal file
3
src/app/shared/supplier-result.component.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<td>{{supplier.name}}</td>
|
||||||
|
<td>{{supplier.postcode}}</td>
|
||||||
|
<td>{{supplier.spend | currency:'GBP':'symbol':'1.2-2' }}</td>
|
19
src/app/shared/supplier-result.component.ts
Normal file
19
src/app/shared/supplier-result.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
interface SupplierData {
|
||||||
|
name: string;
|
||||||
|
postcode: string;
|
||||||
|
spend: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// tslint:disable-next-line
|
||||||
|
selector: '[supplier-result]',
|
||||||
|
templateUrl: 'supplier-result.component.html',
|
||||||
|
})
|
||||||
|
export class SupplierResultComponent implements OnInit {
|
||||||
|
@Input() public supplier: SupplierData;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
<td>{{transaction.seller}}</td>
|
<td>{{transaction.seller}}</td>
|
||||||
<td>{{transaction.value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
<td *ngIf="!showMeta">{{transaction.value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||||
|
<td *ngIf="showMeta">{{transaction.net_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||||
|
<td *ngIf="showMeta">{{transaction.sales_tax_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||||
|
<td *ngIf="showMeta">{{transaction.gross_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||||
<td>{{transactionDate}}</td>
|
<td>{{transactionDate}}</td>
|
||||||
|
|
|
@ -14,6 +14,7 @@ interface TransactionData {
|
||||||
})
|
})
|
||||||
export class TransactionResultComponent implements OnInit {
|
export class TransactionResultComponent implements OnInit {
|
||||||
@Input() public transaction: TransactionData;
|
@Input() public transaction: TransactionData;
|
||||||
|
@Input() public showMeta: boolean;
|
||||||
public transactionDate: string;
|
public transactionDate: string;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
3
src/app/shared/ward-result.component.html
Normal file
3
src/app/shared/ward-result.component.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<td>{{ward.ward}}</td>
|
||||||
|
<td>{{ward.count}}</td>
|
||||||
|
<td>{{ward.sum | currency:'GBP':'symbol':'1.2-2' }}</td>
|
19
src/app/shared/ward-result.component.ts
Normal file
19
src/app/shared/ward-result.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
interface WardData {
|
||||||
|
ward: string;
|
||||||
|
sum: number;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
// tslint:disable-next-line
|
||||||
|
selector: '[ward-result]',
|
||||||
|
templateUrl: 'ward-result.component.html',
|
||||||
|
})
|
||||||
|
export class WardResultComponent implements OnInit {
|
||||||
|
@Input() public ward: WardData;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,15 @@
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="hidden-sm-down">
|
<li class="hidden-sm-down">
|
||||||
<div class="text-muted">Customers This Month</div>
|
<div class="text-muted">Sales Total</div>
|
||||||
|
<strong>{{ allSalesCount }}</strong>
|
||||||
|
</li>
|
||||||
|
<li class="hidden-sm-down">
|
||||||
|
<div class="text-muted">Money Spent Total</div>
|
||||||
|
<strong>{{ allPurchasesTotal | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
||||||
|
</li>
|
||||||
|
<li class="hidden-sm-down">
|
||||||
|
<div class="text-muted">Sales This Month</div>
|
||||||
<strong>{{ thisMonthSalesCount }}</strong>
|
<strong>{{ thisMonthSalesCount }}</strong>
|
||||||
</li>
|
</li>
|
||||||
<li class="hidden-sm-down">
|
<li class="hidden-sm-down">
|
||||||
|
@ -10,7 +18,7 @@
|
||||||
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
||||||
</li>
|
</li>
|
||||||
<li class="hidden-sm-down">
|
<li class="hidden-sm-down">
|
||||||
<div class="text-muted">Customers Today</div>
|
<div class="text-muted">Sales Today</div>
|
||||||
<strong>{{ todaySalesCount }}</strong>
|
<strong>{{ todaySalesCount }}</strong>
|
||||||
</li>
|
</li>
|
||||||
<li class="hidden-sm-down">
|
<li class="hidden-sm-down">
|
||||||
|
|
|
@ -7,6 +7,8 @@ import { OrgSnippetsService } from '../providers/org-snippets.service';
|
||||||
})
|
})
|
||||||
export class OrgBarSnippetComponent implements OnInit {
|
export class OrgBarSnippetComponent implements OnInit {
|
||||||
|
|
||||||
|
public allSalesCount = 0;
|
||||||
|
public allSalesTotal = 0;
|
||||||
public thisMonthSalesCount = 0;
|
public thisMonthSalesCount = 0;
|
||||||
public thisMonthSalesTotal = 0;
|
public thisMonthSalesTotal = 0;
|
||||||
public thisWeekSalesCount = 0;
|
public thisWeekSalesCount = 0;
|
||||||
|
@ -14,6 +16,8 @@ export class OrgBarSnippetComponent implements OnInit {
|
||||||
public todaySalesCount = 0;
|
public todaySalesCount = 0;
|
||||||
public todaySalesTotal = 0;
|
public todaySalesTotal = 0;
|
||||||
|
|
||||||
|
public allPurchasesCount = 0;
|
||||||
|
public allPurchasesTotal = 0;
|
||||||
public thisMonthPurchasesCount = 0;
|
public thisMonthPurchasesCount = 0;
|
||||||
public thisMonthPurchasesTotal = 0;
|
public thisMonthPurchasesTotal = 0;
|
||||||
public thisWeekPurchasesCount = 0;
|
public thisWeekPurchasesCount = 0;
|
||||||
|
@ -29,6 +33,8 @@ export class OrgBarSnippetComponent implements OnInit {
|
||||||
this.snippetsService.getData()
|
this.snippetsService.getData()
|
||||||
.subscribe(
|
.subscribe(
|
||||||
result => {
|
result => {
|
||||||
|
this.allSalesCount = result.snippets.all_sales_count;
|
||||||
|
this.allSalesTotal = result.snippets.all_sales_total;
|
||||||
this.thisMonthSalesCount = result.snippets.this_month_sales_count;
|
this.thisMonthSalesCount = result.snippets.this_month_sales_count;
|
||||||
this.thisMonthSalesTotal = result.snippets.this_month_sales_total;
|
this.thisMonthSalesTotal = result.snippets.this_month_sales_total;
|
||||||
this.thisWeekSalesCount = result.snippets.this_week_sales_count;
|
this.thisWeekSalesCount = result.snippets.this_week_sales_count;
|
||||||
|
@ -36,6 +42,8 @@ export class OrgBarSnippetComponent implements OnInit {
|
||||||
this.todaySalesCount = result.snippets.today_sales_count;
|
this.todaySalesCount = result.snippets.today_sales_count;
|
||||||
this.todaySalesTotal = result.snippets.today_sales_total;
|
this.todaySalesTotal = result.snippets.today_sales_total;
|
||||||
|
|
||||||
|
this.allPurchasesCount = result.snippets.all_purchases_count;
|
||||||
|
this.allPurchasesTotal = result.snippets.all_purchases_total;
|
||||||
this.thisMonthPurchasesCount = result.snippets.this_week_purchases_count;
|
this.thisMonthPurchasesCount = result.snippets.this_week_purchases_count;
|
||||||
this.thisMonthPurchasesTotal = result.snippets.this_week_purchases_total;
|
this.thisMonthPurchasesTotal = result.snippets.this_week_purchases_total;
|
||||||
this.thisWeekPurchasesCount = result.snippets.this_month_purchases_count;
|
this.thisWeekPurchasesCount = result.snippets.this_month_purchases_count;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="chart-wrapper px-3" style="height:70px;">
|
<div class="chart-wrapper px-3" style="height:70px;">
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
class="chart"
|
class="chart"
|
||||||
[datasets]="lineChartData"
|
[datasets]="lineGraphChartData"
|
||||||
[labels]="lineChartLabels"
|
[labels]="lineChartLabels"
|
||||||
[options]="lineChartOptions"
|
[options]="lineChartOptions"
|
||||||
[colors]="lineChartColours"
|
[colors]="lineChartColours"
|
||||||
|
|
|
@ -12,6 +12,7 @@ interface ChartData {
|
||||||
selector: 'widget-graph',
|
selector: 'widget-graph',
|
||||||
templateUrl: 'graph-widget.component.html',
|
templateUrl: 'graph-widget.component.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class GraphWidget implements OnInit {
|
export class GraphWidget implements OnInit {
|
||||||
@Input() public graphName: string;
|
@Input() public graphName: string;
|
||||||
@Input() public graphTitle = 'Graph';
|
@Input() public graphTitle = 'Graph';
|
||||||
|
@ -24,7 +25,7 @@ export class GraphWidget implements OnInit {
|
||||||
public graphSum: Number = 0;
|
public graphSum: Number = 0;
|
||||||
public availableDataTypes = DataType;
|
public availableDataTypes = DataType;
|
||||||
|
|
||||||
public lineChartData: Array<ChartData> = [
|
public lineGraphChartData: Array<ChartData> = [
|
||||||
{
|
{
|
||||||
data: [],
|
data: [],
|
||||||
label: 'Series A'
|
label: 'Series A'
|
||||||
|
@ -63,7 +64,7 @@ export class GraphWidget implements OnInit {
|
||||||
},
|
},
|
||||||
elements: {
|
elements: {
|
||||||
line: {
|
line: {
|
||||||
borderWidth: 1
|
borderWidth: 2
|
||||||
},
|
},
|
||||||
point: {
|
point: {
|
||||||
radius: 4,
|
radius: 4,
|
||||||
|
@ -124,7 +125,7 @@ export class GraphWidget implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private setChartData(data: Array<number>) {
|
private setChartData(data: Array<number>) {
|
||||||
this.lineChartData[0].data = data;
|
this.lineGraphChartData[0].data = data;
|
||||||
this.graphSum = data.reduce((a, b) => a + b, 0);
|
this.graphSum = data.reduce((a, b) => a + b, 0);
|
||||||
// Set point size based on data
|
// Set point size based on data
|
||||||
if ( data.length < 15 ) {
|
if ( data.length < 15 ) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
apiUrl: 'https://dev.peartrade.org/api',
|
apiUrl: 'https://dev.localspend.co.uk/api',
|
||||||
mapApiKey: 'CHANGEME',
|
mapApiKey: 'CHANGEME',
|
||||||
enableAnalytics: false,
|
enableAnalytics: false,
|
||||||
analyticsKey: 'CHANGEME',
|
analyticsKey: 'CHANGEME',
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||||
*
|
*
|
||||||
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
* Learn more in https://angular.io/guide/browser-support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* BROWSER POLYFILLS
|
* BROWSER POLYFILLS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||||
|
@ -31,23 +31,37 @@ import 'core-js/es6/date';
|
||||||
import 'core-js/es6/array';
|
import 'core-js/es6/array';
|
||||||
import 'core-js/es6/regexp';
|
import 'core-js/es6/regexp';
|
||||||
import 'core-js/es6/map';
|
import 'core-js/es6/map';
|
||||||
|
import 'core-js/es6/weak-map';
|
||||||
import 'core-js/es6/set';
|
import 'core-js/es6/set';
|
||||||
import 'core-js/es6/reflect';
|
import 'core-js/es7/array';
|
||||||
|
import 'core-js/es7/object';
|
||||||
|
|
||||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||||
|
|
||||||
/** IE10 and IE11 requires the following to support `@angular/animation`. */
|
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
|
||||||
|
|
||||||
|
|
||||||
/** Evergreen browsers require these. **/
|
|
||||||
import 'core-js/es6/reflect';
|
import 'core-js/es6/reflect';
|
||||||
import 'core-js/es7/reflect';
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required to support Web Animations `@angular/platform-browser/animations`.
|
||||||
|
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
||||||
|
**/
|
||||||
|
import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
/** ALL Firefox browsers require the following to support `@angular/animation`. **/
|
/**
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||||
|
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
(window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||||
|
(window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||||
|
(window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||||
|
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||||
|
*/
|
||||||
|
(window as any).__Zone_enable_cross_context_check = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,8 @@ agm-map {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.small {
|
||||||
|
}
|
||||||
&.legend {
|
&.legend {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
|
28
src/scss/bootstrap/_spinner.scss
Normal file
28
src/scss/bootstrap/_spinner.scss
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
.spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: #333;
|
||||||
|
|
||||||
|
margin: 100px auto;
|
||||||
|
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
|
||||||
|
animation: sk-rotateplane 1.2s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes sk-rotateplane {
|
||||||
|
0% { -webkit-transform: perspective(120px) }
|
||||||
|
50% { -webkit-transform: perspective(120px) rotateY(180deg) }
|
||||||
|
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sk-rotateplane {
|
||||||
|
0% {
|
||||||
|
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
|
||||||
|
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
|
||||||
|
} 50% {
|
||||||
|
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
|
||||||
|
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
|
||||||
|
} 100% {
|
||||||
|
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||||
|
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,3 +76,4 @@
|
||||||
|
|
||||||
// Custom styles
|
// Custom styles
|
||||||
@import "custom";
|
@import "custom";
|
||||||
|
@import "bootstrap/spinner";
|
|
@ -2,7 +2,6 @@
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/app",
|
"outDir": "../out-tsc/app",
|
||||||
"module": "es2015",
|
|
||||||
"baseUrl": "",
|
"baseUrl": "",
|
||||||
"types": []
|
"types": []
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/spec",
|
"outDir": "../out-tsc/spec",
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es5",
|
|
||||||
"baseUrl": "",
|
"baseUrl": "",
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
"jasmine",
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"module": "esnext",
|
||||||
"outDir": "./dist/out-tsc",
|
"outDir": "./dist/out-tsc",
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
@ -8,7 +11,7 @@
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"target": "es5",
|
"target": "es2015",
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"node_modules/@types"
|
"node_modules/@types"
|
||||||
],
|
],
|
||||||
|
|
|
@ -100,12 +100,12 @@
|
||||||
|
|
||||||
"directive-selector": [true, "attribute", "app", "camelCase"],
|
"directive-selector": [true, "attribute", "app", "camelCase"],
|
||||||
"component-selector": [true, "element", ["app", "widget", "snippet", "panel"], "kebab-case"],
|
"component-selector": [true, "element", ["app", "widget", "snippet", "panel"], "kebab-case"],
|
||||||
"use-input-property-decorator": true,
|
"no-inputs-metadata-property": true,
|
||||||
"use-output-property-decorator": true,
|
"no-outputs-metadata-property": true,
|
||||||
"use-host-property-decorator": true,
|
"no-host-metadata-property": true,
|
||||||
"no-input-rename": true,
|
"no-input-rename": true,
|
||||||
"no-output-rename": true,
|
"no-output-rename": true,
|
||||||
"use-life-cycle-interface": true,
|
"use-lifecycle-interface": true,
|
||||||
"use-pipe-transform-interface": true,
|
"use-pipe-transform-interface": true,
|
||||||
"component-class-suffix": [true, "Component", "Widget", "Panel"],
|
"component-class-suffix": [true, "Component", "Widget", "Panel"],
|
||||||
"directive-class-suffix": true,
|
"directive-class-suffix": true,
|
||||||
|
|
Reference in a new issue