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
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
*.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",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"scripts": [
|
||||
"node_modules/moment/min/moment.min.js"
|
||||
],
|
||||
"styles": [
|
||||
"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'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require("readable-stream");
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
|
@ -16,10 +17,10 @@ module.exports = function (config) {
|
|||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
files: [
|
||||
|
||||
|
||||
],
|
||||
preprocessors: {
|
||||
|
||||
|
||||
},
|
||||
mime: {
|
||||
'text/x-typescript': ['ts','tsx']
|
||||
|
|
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": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"start:dev": "ng serve --optimization=false --configuration=dev",
|
||||
"start:local": "ng serve --optimization=false --configuration=local",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"test:ci": "ng test --watch=false",
|
||||
|
@ -18,51 +20,65 @@
|
|||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@agm/core": "1.0.0-beta.3",
|
||||
"@agm/js-marker-clusterer": "1.0.0-beta.3",
|
||||
"@angular/common": "6.0.3",
|
||||
"@angular/compiler": "6.0.3",
|
||||
"@angular/core": "6.0.3",
|
||||
"@angular/forms": "6.0.3",
|
||||
"@angular/platform-browser": "6.0.3",
|
||||
"@angular/platform-browser-dynamic": "6.0.3",
|
||||
"@angular/router": "6.0.3",
|
||||
"@angular/upgrade": "6.0.3",
|
||||
"@types/moment": "2.13.0",
|
||||
"chart.js": "^2.7.2",
|
||||
"core-js": "^2.5.7",
|
||||
"jasmine": "^3.1.0",
|
||||
"@agm/core": "1.0.0-beta.6",
|
||||
"@agm/js-marker-clusterer": "1.0.0-beta.6",
|
||||
"@angular/common": "8.1.0",
|
||||
"@angular/compiler": "8.1.0",
|
||||
"@angular/core": "8.1.0",
|
||||
"@angular/forms": "8.1.0",
|
||||
"@angular/platform-browser": "8.1.0",
|
||||
"@angular/platform-browser-dynamic": "8.1.0",
|
||||
"@angular/router": "8.1.0",
|
||||
"@angular/upgrade": "8.1.0",
|
||||
"@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1",
|
||||
"@coreui/icons": "0.3.0",
|
||||
"ajv": "^6.10.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",
|
||||
"moment": "^2.22.2",
|
||||
"ng2-charts": "1.6.0",
|
||||
"jszip": "^3.2.2",
|
||||
"luxon": "^1.16.1",
|
||||
"moment": "^2.24.0",
|
||||
"ng2-charts": "^2.3.0",
|
||||
"ng2-validation-manager": "0.5.3",
|
||||
"ngx-bootstrap": "^2.0.5",
|
||||
"ngx-pagination": "^3.1.1",
|
||||
"rxjs": "6.2.0",
|
||||
"rxjs-compat": "^6.2.0",
|
||||
"ngx-bootstrap": "^5.0.0",
|
||||
"ngx-filter-pipe": "^2.1.2",
|
||||
"ngx-pagination": "^4.0.0",
|
||||
"popper.js": "^1.15.0",
|
||||
"rxjs": "6.5.2",
|
||||
"stream": "0.0.2",
|
||||
"ts-helpers": "1.1.2",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"zone.js": "0.8.26"
|
||||
"tslib": "^1.10.0",
|
||||
"web-animations-js": "^2.3.2",
|
||||
"webpack-dev-server": "^3.7.2",
|
||||
"zone.js": "~0.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.6.6",
|
||||
"@angular/cli": "^6.0.7",
|
||||
"@angular/compiler-cli": "6.0.3",
|
||||
"@types/jasmine": "2.8.2",
|
||||
"@types/jasminewd2": "2.0.3",
|
||||
"@types/node": "8.0.52",
|
||||
"codelyzer": "^4.3.0",
|
||||
"jasmine-core": "^3.1.0",
|
||||
"@angular-devkit/build-angular": "~0.801.0",
|
||||
"@angular/cli": "^8.1.0",
|
||||
"@angular/compiler-cli": "8.1.0",
|
||||
"@types/jasmine": "3.3.13",
|
||||
"@types/jasminewd2": "2.0.6",
|
||||
"@types/node": "12.0.10",
|
||||
"codelyzer": "^5.1.0",
|
||||
"jasmine-core": "^3.4.0",
|
||||
"jasmine-spec-reporter": "4.2.1",
|
||||
"karma": "^2.0.2",
|
||||
"karma": "^4.1.0",
|
||||
"karma-chrome-launcher": "2.2.0",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-coverage-istanbul-reporter": "^2.0.1",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-jasmine-html-reporter": "^1.1.0",
|
||||
"protractor": "^5.3.2",
|
||||
"ts-node": "^6.1.0",
|
||||
"tslint": "^5.10.0",
|
||||
"typescript": "2.7.2"
|
||||
"karma-cli": "2.0.0",
|
||||
"karma-coverage-istanbul-reporter": "^2.0.5",
|
||||
"karma-jasmine": "^2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"protractor": "^5.4.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"tslint": "^5.18.0",
|
||||
"typescript": "~3.4.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||
import { NgModule } from '@angular/core';
|
||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
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 { CustSnippetsService } from './providers/cust-snippets.service';
|
||||
import { CustPiesService } from './providers/cust-pies.service';
|
||||
import { OrgPiesService } from './providers/org-pies.service';
|
||||
|
||||
// Layouts
|
||||
import { FullLayoutComponent } from './layouts/full-layout.component';
|
||||
|
@ -39,23 +41,30 @@ import { P500Component } from './pages/500.component';
|
|||
// Submodules
|
||||
import { AuthModule } from './auth/auth.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({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
FormsModule,
|
||||
FilterPipeModule,
|
||||
ReactiveFormsModule,
|
||||
NgxPaginationModule,
|
||||
BsDropdownModule.forRoot(),
|
||||
TabsModule.forRoot(),
|
||||
AuthModule,
|
||||
ChartsModule,
|
||||
DashboardModule,
|
||||
// Loaded last to allow for 404 catchall
|
||||
AppRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
// StackedBarChartComponent,
|
||||
FullLayoutComponent,
|
||||
SimpleLayoutComponent,
|
||||
NAV_DROPDOWN_DIRECTIVES,
|
||||
|
@ -75,6 +84,7 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|||
CustGraphsService,
|
||||
CustSnippetsService,
|
||||
CustPiesService,
|
||||
OrgPiesService,
|
||||
{
|
||||
provide: LocationStrategy,
|
||||
useClass: HashLocationStrategy
|
||||
|
|
|
@ -40,15 +40,11 @@ export class LoginComponent implements OnInit {
|
|||
}
|
||||
|
||||
onSubmit() {
|
||||
console.log(this.signin.value);
|
||||
|
||||
this.api
|
||||
.login(this.signin.value)
|
||||
.subscribe(
|
||||
result => {
|
||||
console.log('logged in!');
|
||||
this.loginStatus = 'success';
|
||||
console.log(this.loginStatus);
|
||||
this.router.navigate([this.returnUrl]);
|
||||
},
|
||||
error => {
|
||||
|
|
|
@ -116,7 +116,6 @@ export class RegisterComponent {
|
|||
town: organisationForm.town,
|
||||
postcode: organisationForm.postcode,
|
||||
};
|
||||
console.log(data);
|
||||
this.api
|
||||
.register(data)
|
||||
.subscribe(
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input">Essential Purchase</label>
|
||||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<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>
|
||||
<span class="help-block">Tick if the purchase is deemed an essential purchase for budgeting purposes.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
|
@ -38,8 +39,8 @@
|
|||
<div class="col-md-9">
|
||||
<div class="input-group">
|
||||
<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>
|
||||
<span class="help-block">Tick if the purchase frequently recurs, such as monthly.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="recurringPurchase" class="form-group row">
|
||||
|
@ -156,14 +157,14 @@
|
|||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class=row>
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="weekList1" class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class="row">
|
||||
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="weekList2" class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class="row">
|
||||
|
@ -84,7 +84,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="weekList3" class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class="row">
|
||||
|
@ -126,7 +126,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="weekList4" class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class="row">
|
||||
|
|
|
@ -12,29 +12,34 @@
|
|||
</div><!--/.row-->
|
||||
<div class=row>
|
||||
<div class="col-xl-6">
|
||||
<panel-pie></panel-pie>
|
||||
</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">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>
|
||||
<panel-pie></panel-pie><!--All Purchases -->
|
||||
<!-- <div class="demo-container" ng-app="stacked-bar" ng-controller="stacked-bar">
|
||||
<div id="stacked-bar" dx-chart="chartOptions"></div>
|
||||
</div> -->
|
||||
</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 class="card">
|
||||
<div class="card-block">
|
||||
|
@ -55,19 +60,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
<div *ngIf="showCategoryBarChart" class="col-xl-6">
|
||||
<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">Monthly Spending by Category</h4>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="card-title float-left mb-0">Your Purchases by Category</h4>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
<div class="chart-wrapper">
|
||||
<canvas baseChart
|
||||
<canvas baseChart class="chart"
|
||||
[datasets]="barChartDataCategory"
|
||||
[labels]="barChartLabelsCategory"
|
||||
[options]="barChartOptionsCategory"
|
||||
[colors]="barChartColoursCategory"
|
||||
[legend]="barChartLegendCategory"
|
||||
[chartType]="barChartTypeCategory"
|
||||
(chartHover)="chartHovered($event)"
|
||||
|
@ -81,88 +87,29 @@
|
|||
<div class="card-block">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h4 class="card-title float-left mb-0">Weekly Purchase No.</h4>
|
||||
</div><!--/.col-->
|
||||
</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">
|
||||
<h4 class="card-title float-left mb-0"> Global Puchases by Category</h4>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<h4 class="card-title float-left mb-0">All Purchases by Category</h4>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
<div 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 *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>
|
||||
</div><!--/.row-->
|
||||
</div>
|
||||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,12 +2,19 @@ import { Directive, Component, OnInit } from '@angular/core';
|
|||
import { CurrencyPipe } from '@angular/common';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router } from '@angular/router';
|
||||
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { Color, Label } from 'ng2-charts';
|
||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||
import { PiePanel } from '../panels/pie-panel.component';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
import * as moment from 'moment';
|
||||
import { MoreStuffComponent } from '../dashboard/more-graphs-and-tables.component';
|
||||
// import { StackedBarChartComponent } from '../panels/stacked-bar.component';
|
||||
|
||||
interface SuppliersComponent {
|
||||
name : string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: 'dashboard-customer.component.html'
|
||||
|
@ -32,6 +39,22 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
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: {
|
||||
|
@ -62,11 +85,12 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
responsive: true,
|
||||
scales:{
|
||||
xAxes:[{
|
||||
stacked:true
|
||||
scaleLabel: {
|
||||
display:true,
|
||||
},
|
||||
stacked:true,
|
||||
|
||||
}],
|
||||
yAxes:[{
|
||||
stacked:true
|
||||
}]
|
||||
}
|
||||
};
|
||||
public barChartTypeEssential:string = 'horizontalBar';
|
||||
|
@ -94,6 +118,23 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
public barChartLegendCategory:boolean = false;
|
||||
public barChartDataCategory:any[]=[];
|
||||
public barChartLabelsCategory:string[] = [];
|
||||
public barChartColoursCategory: any[] = [
|
||||
{
|
||||
backgroundColor:[
|
||||
'#ffa1b5',
|
||||
'#3cde52',
|
||||
'#52afed',
|
||||
'#c133e3',
|
||||
'#f7fa08',
|
||||
'#75152d',
|
||||
'#ee12ee',
|
||||
'#15eaea',
|
||||
'#eaa015',
|
||||
'#ea1515',
|
||||
'#2d4fcc'
|
||||
]
|
||||
}];
|
||||
|
||||
|
||||
weekPurchaseList = {
|
||||
first: 0,
|
||||
|
@ -107,6 +148,7 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
totalCategoryLimit: number = 10;
|
||||
totalCategoryList: any[]=[];
|
||||
|
||||
|
||||
// Graph widgets
|
||||
public widgetList = [
|
||||
{
|
||||
|
@ -148,7 +190,9 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
this.setWeekData(result);
|
||||
this.setChartData(result.data.cat_total);
|
||||
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.purchaseNotEssential = result.data.essentials.purchase_no_total - this.purchaseEssential;
|
||||
this.barChartDataEssential = [
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
<div class="animated fadeIn">
|
||||
<snippet-bar-org></snippet-bar-org>
|
||||
<div class="row">
|
||||
|
@ -11,4 +12,102 @@
|
|||
</div><!--/.col-->
|
||||
</div><!--/.row-->
|
||||
<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 {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 { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { environment } from '../../environments/environment';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'dashboard.component.html'
|
||||
|
@ -38,6 +44,13 @@ export class DashboardComponent {
|
|||
title: 'Sales Last 30 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'sales_last_quart',
|
||||
icon: 'icon-diamond',
|
||||
title: 'Sales Last Quart',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'purchases_last_7_days',
|
||||
|
@ -50,8 +63,194 @@ export class DashboardComponent {
|
|||
title: 'Purchases Last 30 Days',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
{
|
||||
type: 'graph',
|
||||
name: 'purchases_last_quart;',
|
||||
title: 'Purchases Last Quart',
|
||||
dataType: DataType.currency,
|
||||
},
|
||||
];
|
||||
constructor(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) {
|
||||
this.router.events.subscribe(event => {
|
||||
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 { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ChartsModule } from 'ng2-charts/ng2-charts';
|
||||
import { ChartsModule } from 'ng2-charts';
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||
import { NgxPaginationModule } from 'ngx-pagination';
|
||||
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
||||
|
@ -18,6 +18,8 @@ import { FeedbackComponent } from './feedback.component';
|
|||
import { TransactionLogComponent } from './transaction-log.component';
|
||||
import { CategoryMonthComponent } from './category-month.component';
|
||||
import { PayrollLogComponent } from './payroll-log.component';
|
||||
import { SuppliersComponent } from './suppliers.component';
|
||||
import { MoreStuffComponent } from './more-graphs-and-tables.component';
|
||||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
|
@ -26,7 +28,9 @@ import { GraphWidget } from '../widgets/graph-widget.component';
|
|||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
import { BubbleChartComponent } from '../panels/bubble-panel.component';
|
||||
import { PiePanel } from '../panels/pie-panel.component';
|
||||
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
||||
|
||||
import { DashboardRoutingModule } from './dashboard.routing';
|
||||
import { OrgResultComponent } from '../shared/org-result.component';
|
||||
|
@ -34,6 +38,9 @@ import { OrgTableComponent } from '../shared/org-table.component';
|
|||
import { RecurResultComponent } from '../shared/recur-result.component';
|
||||
import { RecurTableComponent } from '../shared/recur-table.component';
|
||||
import { TransactionResultComponent } from '../shared/transaction-result.component';
|
||||
import { SupplierResultComponent } from '../shared/supplier-result.component';
|
||||
import { WardResultComponent } from '../shared/ward-result.component';
|
||||
import { MetaTypeResultComponent } from '../shared/meta-type-result.component';
|
||||
import { PayrollResultComponent } from '../shared/payroll-result.component';
|
||||
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
||||
|
||||
|
@ -68,6 +75,9 @@ import { environment } from '../../environments/environment';
|
|||
TransactionLogComponent,
|
||||
CategoryMonthComponent,
|
||||
TransactionResultComponent,
|
||||
SupplierResultComponent,
|
||||
WardResultComponent,
|
||||
MetaTypeResultComponent,
|
||||
PayrollLogComponent,
|
||||
PayrollResultComponent,
|
||||
LeaderboardComponent,
|
||||
|
@ -80,6 +90,10 @@ import { environment } from '../../environments/environment';
|
|||
CustBarSnippetComponent,
|
||||
GraphPanel,
|
||||
PiePanel,
|
||||
OrgPiePanel,
|
||||
BubbleChartComponent,
|
||||
SuppliersComponent,
|
||||
MoreStuffComponent,
|
||||
],
|
||||
providers: [
|
||||
CurrencyPipe,
|
||||
|
|
|
@ -17,6 +17,8 @@ import { PayrollLogComponent } from './payroll-log.component';
|
|||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
import { MoreStuffComponent } from './more-graphs-and-tables.component';
|
||||
import { SuppliersComponent } from './suppliers.component';
|
||||
|
||||
// Using child path to allow for FullLayout theming
|
||||
const routes: Routes = [
|
||||
|
@ -84,6 +86,16 @@ const routes: Routes = [
|
|||
path: 'feedback',
|
||||
component: FeedbackComponent,
|
||||
data: { title: 'Give Feedback' },
|
||||
},
|
||||
{
|
||||
path: 'suppliers',
|
||||
component: SuppliersComponent,
|
||||
data: { title: 'Suppliers' }
|
||||
},
|
||||
{
|
||||
path: 'more-graphs-and-tables',
|
||||
component: MoreStuffComponent,
|
||||
data: { title: 'Infographics'}
|
||||
}
|
||||
],
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<tr>
|
||||
<th>Position</th>
|
||||
<th>Name</th>
|
||||
<th>Amount</th>
|
||||
<th class="js-sort-number">Gross amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -22,7 +22,7 @@ export class LeaderboardComponent implements OnInit {
|
|||
|
||||
public paginateConfig: PaginationInstance = {
|
||||
id: 'leadpaginate',
|
||||
itemsPerPage: 10,
|
||||
itemsPerPage: 20,
|
||||
currentPage: 1,
|
||||
totalItems: 0
|
||||
};
|
||||
|
@ -70,7 +70,7 @@ export class LeaderboardComponent implements OnInit {
|
|||
console.log(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}org
|
||||
|
||||
// // dynamically changes the row style based on player's position
|
||||
// // for instance, top three player and the player him/herself should
|
||||
|
|
|
@ -9,7 +9,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
|||
templateUrl: 'map.component.html',
|
||||
})
|
||||
export class MapComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
||||
@ViewChild('statusModal', { static: true }) myStatusModal: ModalDirective;
|
||||
lat: number = 54.0466;
|
||||
lng: number = -2.8007;
|
||||
zoom: number = 12;
|
||||
|
|
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',
|
||||
})
|
||||
export class TrailMapComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
||||
@ViewChild('statusModal', { static: true }) myStatusModal: ModalDirective;
|
||||
lat: number = 54.0466;
|
||||
lng: number = -2.8007;
|
||||
zoom: number = 12;
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
</div>
|
||||
<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)="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>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
@ -101,18 +101,24 @@
|
|||
<div class="card-header">
|
||||
<strong>Log of Outgoing Transactions</strong>
|
||||
<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 *ngIf="!noTransactionList" class="card-block">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<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>
|
||||
</tr>
|
||||
</thead>
|
||||
<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>
|
||||
</table>
|
||||
<pagination-template #p="paginationApi"
|
||||
|
|
|
@ -29,13 +29,14 @@ export class TransactionLogComponent implements OnInit {
|
|||
transactionFormStatusSuccess: string;
|
||||
transactionFormStatusError = 'Error received, please try again.';
|
||||
updatedTime: string;
|
||||
showMeta = false;
|
||||
|
||||
public paginateConfig: PaginationInstance = {
|
||||
id: 'transpaginate',
|
||||
itemsPerPage: 10,
|
||||
currentPage: 1,
|
||||
totalItems: 0
|
||||
};
|
||||
id: 'transpaginate',
|
||||
itemsPerPage: 10,
|
||||
currentPage: 1,
|
||||
totalItems: 0
|
||||
};
|
||||
|
||||
constructor(
|
||||
private api: ApiService,
|
||||
|
@ -87,6 +88,7 @@ export class TransactionLogComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
recurringTransactionDetails(clicked, template: TemplateRef<any>) {
|
||||
this.clickedRecur = clicked;
|
||||
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>
|
||||
</a>
|
||||
</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">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
||||
<div class="row no-gutters align-items-center">
|
||||
|
@ -94,14 +102,22 @@
|
|||
</div>
|
||||
</a>
|
||||
</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>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/suppliers']">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col-2"><i class="icon-speedometer"></i></div>
|
||||
<div class="col-10">Suppliers</div>
|
||||
</div>
|
||||
</a>
|
||||
</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>
|
||||
</nav>
|
||||
</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-block">
|
||||
<div class="row">
|
||||
<div class="col-sm-5">
|
||||
<div class="col-sm-12">
|
||||
<h4 class="card-title mb-0">Customers</h4>
|
||||
</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 class="chart-wrapper" style="height:300px;margin-top:40px;">
|
||||
<canvas baseChart class="chart"
|
||||
|
|
|
@ -82,12 +82,12 @@ export class GraphPanel implements OnInit {
|
|||
pointHoverBackgroundColor: '#fff'
|
||||
},
|
||||
{ // brandSuccess
|
||||
backgroundColor: 'transparent',
|
||||
backgroundColor: this.convertHex(this.brandInfo, 10),
|
||||
borderColor: this.brandSuccess,
|
||||
pointHoverBackgroundColor: '#fff'
|
||||
},
|
||||
{ // brandDanger
|
||||
backgroundColor: 'transparent',
|
||||
backgroundColor: this.convertHex(this.brandDanger, 10),
|
||||
borderColor: this.brandDanger,
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
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="row">
|
||||
<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 class="chart-wrapper">
|
||||
<canvas baseChart class="chart"
|
||||
[data]="doughnutChartDataLocal"
|
||||
[labels]="doughnutChartLabelsLocal"
|
||||
[colors]="doughnutChartColors"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="chartType"
|
||||
(chartHover)="chartHovered($event)"
|
||||
|
|
|
@ -9,12 +9,44 @@ import { ChartData } from '../_interfaces/chart-data';
|
|||
selector: 'panel-pie',
|
||||
templateUrl: 'pie-panel.component.html',
|
||||
})
|
||||
|
||||
export class PiePanel implements OnInit {
|
||||
|
||||
public chartType = 'doughnut';
|
||||
public chartType = 'pie';
|
||||
public chartLegend = true;
|
||||
public doughnutChartDataLocal: number[] = [];
|
||||
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(
|
||||
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
|
||||
|
||||
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()
|
||||
export class OrgGraphsService {
|
||||
private orgGraphUrl = '/v1/customer/graphs';
|
||||
private orgGraphUrl = '/v1/organisation/graphs';
|
||||
|
||||
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.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>
|
||||
|
|
|
@ -14,6 +14,7 @@ interface TransactionData {
|
|||
})
|
||||
export class TransactionResultComponent implements OnInit {
|
||||
@Input() public transaction: TransactionData;
|
||||
@Input() public showMeta: boolean;
|
||||
public transactionDate: string;
|
||||
|
||||
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">
|
||||
<ul>
|
||||
<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>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
|
@ -10,7 +18,7 @@
|
|||
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Customers Today</div>
|
||||
<div class="text-muted">Sales Today</div>
|
||||
<strong>{{ todaySalesCount }}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
|
|
|
@ -7,6 +7,8 @@ import { OrgSnippetsService } from '../providers/org-snippets.service';
|
|||
})
|
||||
export class OrgBarSnippetComponent implements OnInit {
|
||||
|
||||
public allSalesCount = 0;
|
||||
public allSalesTotal = 0;
|
||||
public thisMonthSalesCount = 0;
|
||||
public thisMonthSalesTotal = 0;
|
||||
public thisWeekSalesCount = 0;
|
||||
|
@ -14,6 +16,8 @@ export class OrgBarSnippetComponent implements OnInit {
|
|||
public todaySalesCount = 0;
|
||||
public todaySalesTotal = 0;
|
||||
|
||||
public allPurchasesCount = 0;
|
||||
public allPurchasesTotal = 0;
|
||||
public thisMonthPurchasesCount = 0;
|
||||
public thisMonthPurchasesTotal = 0;
|
||||
public thisWeekPurchasesCount = 0;
|
||||
|
@ -29,6 +33,8 @@ export class OrgBarSnippetComponent implements OnInit {
|
|||
this.snippetsService.getData()
|
||||
.subscribe(
|
||||
result => {
|
||||
this.allSalesCount = result.snippets.all_sales_count;
|
||||
this.allSalesTotal = result.snippets.all_sales_total;
|
||||
this.thisMonthSalesCount = result.snippets.this_month_sales_count;
|
||||
this.thisMonthSalesTotal = result.snippets.this_month_sales_total;
|
||||
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.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.thisMonthPurchasesTotal = result.snippets.this_week_purchases_total;
|
||||
this.thisWeekPurchasesCount = result.snippets.this_month_purchases_count;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="chart-wrapper px-3" style="height:70px;">
|
||||
<canvas baseChart
|
||||
class="chart"
|
||||
[datasets]="lineChartData"
|
||||
[datasets]="lineGraphChartData"
|
||||
[labels]="lineChartLabels"
|
||||
[options]="lineChartOptions"
|
||||
[colors]="lineChartColours"
|
||||
|
|
|
@ -12,6 +12,7 @@ interface ChartData {
|
|||
selector: 'widget-graph',
|
||||
templateUrl: 'graph-widget.component.html',
|
||||
})
|
||||
|
||||
export class GraphWidget implements OnInit {
|
||||
@Input() public graphName: string;
|
||||
@Input() public graphTitle = 'Graph';
|
||||
|
@ -24,7 +25,7 @@ export class GraphWidget implements OnInit {
|
|||
public graphSum: Number = 0;
|
||||
public availableDataTypes = DataType;
|
||||
|
||||
public lineChartData: Array<ChartData> = [
|
||||
public lineGraphChartData: Array<ChartData> = [
|
||||
{
|
||||
data: [],
|
||||
label: 'Series A'
|
||||
|
@ -63,7 +64,7 @@ export class GraphWidget implements OnInit {
|
|||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 1
|
||||
borderWidth: 2
|
||||
},
|
||||
point: {
|
||||
radius: 4,
|
||||
|
@ -124,7 +125,7 @@ export class GraphWidget implements OnInit {
|
|||
}
|
||||
|
||||
private setChartData(data: Array<number>) {
|
||||
this.lineChartData[0].data = data;
|
||||
this.lineGraphChartData[0].data = data;
|
||||
this.graphSum = data.reduce((a, b) => a + b, 0);
|
||||
// Set point size based on data
|
||||
if ( data.length < 15 ) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: 'https://dev.peartrade.org/api',
|
||||
apiUrl: 'https://dev.localspend.co.uk/api',
|
||||
mapApiKey: 'CHANGEME',
|
||||
enableAnalytics: false,
|
||||
analyticsKey: 'CHANGEME',
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* 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. **/
|
||||
|
@ -31,23 +31,37 @@ import 'core-js/es6/date';
|
|||
import 'core-js/es6/array';
|
||||
import 'core-js/es6/regexp';
|
||||
import 'core-js/es6/map';
|
||||
import 'core-js/es6/weak-map';
|
||||
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 */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/** IE10 and IE11 requires the following to support `@angular/animation`. */
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
|
||||
/** Evergreen browsers require these. **/
|
||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.small {
|
||||
}
|
||||
&.legend {
|
||||
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
|
||||
@import "custom";
|
||||
@import "bootstrap/spinner";
|
|
@ -2,7 +2,6 @@
|
|||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/app",
|
||||
"module": "es2015",
|
||||
"baseUrl": "",
|
||||
"types": []
|
||||
},
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/spec",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"baseUrl": "",
|
||||
"types": [
|
||||
"jasmine",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"downlevelIteration": true,
|
||||
"importHelpers": true,
|
||||
"module": "esnext",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"baseUrl": "src",
|
||||
"sourceMap": true,
|
||||
|
@ -8,7 +11,7 @@
|
|||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "es5",
|
||||
"target": "es2015",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
|
|
|
@ -100,12 +100,12 @@
|
|||
|
||||
"directive-selector": [true, "attribute", "app", "camelCase"],
|
||||
"component-selector": [true, "element", ["app", "widget", "snippet", "panel"], "kebab-case"],
|
||||
"use-input-property-decorator": true,
|
||||
"use-output-property-decorator": true,
|
||||
"use-host-property-decorator": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-output-rename": true,
|
||||
"use-life-cycle-interface": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"component-class-suffix": [true, "Component", "Widget", "Panel"],
|
||||
"directive-class-suffix": true,
|
||||
|
|
Reference in a new issue