Compare commits
2 commits
developmen
...
tom/minorf
Author | SHA1 | Date | |
---|---|---|---|
|
7740d9ec2d | ||
|
e7441bf47a |
72 changed files with 4251 additions and 9351 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,6 +22,7 @@ $RECYCLE.BIN/
|
||||||
/bower_components
|
/bower_components
|
||||||
|
|
||||||
# IDEs and editors
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
*.launch
|
*.launch
|
||||||
|
|
3
.idea/.gitignore
vendored
3
.idea/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
# Default ignored files
|
|
||||||
/workspace.xml
|
|
|
@ -1,14 +0,0 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<TypeScriptCodeStyleSettings version="0">
|
|
||||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
|
||||||
<option name="BLANK_LINES_AROUND_FUNCTION" value="0" />
|
|
||||||
</TypeScriptCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="TypeScript">
|
|
||||||
<option name="BLANK_LINES_AROUND_METHOD" value="0" />
|
|
||||||
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
|
|
||||||
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
|
|
||||||
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectRootManager">
|
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
.travis.yml
10
.travis.yml
|
@ -1,12 +1,16 @@
|
||||||
|
# Force sudo due to issue in travis
|
||||||
|
sudo: required
|
||||||
addons:
|
addons:
|
||||||
chrome: stable
|
chrome: stable
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- node
|
- 8
|
||||||
before_install:
|
before_install:
|
||||||
- openssl aes-256-cbc -K $encrypted_17157b34afc7_key -iv $encrypted_17157b34afc7_iv -in src/environments/environments.tar.enc -out src/environments/environments.tar -d
|
- openssl aes-256-cbc -K $encrypted_9d2af3734b6c_key -iv $encrypted_9d2af3734b6c_iv -in src/environments/environments.tar.enc -out src/environments/environments.tar -d
|
||||||
- tar xf src/environments/environments.tar -C src/environments
|
- tar xf src/environments/environments.tar -C src/environments
|
||||||
before_script:
|
before_script:
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
- npm config set spin false
|
- npm config set spin false
|
||||||
install:
|
install:
|
||||||
- npm install
|
- npm install
|
||||||
|
@ -17,7 +21,7 @@ before_deploy:
|
||||||
deploy:
|
deploy:
|
||||||
provider: releases
|
provider: releases
|
||||||
api_key:
|
api_key:
|
||||||
secure: "Ke27Qm16uRgfX+ZVAq92Suu0ZpLOG9TGXDD8ndKNQZ4zl80DOmePoKvVpk/5Ip3H57Me2seqtCwgjeUCfW0dX3KayPoNmGVxWXCsZCH3MZWuaMnGk/Zc1Ef8P3L1sTEG4LD6+59RaOiMwIrMtLPjSlzvV2gc+002O7MHoudx/qZl47L+T01B0Ovh1AueSVN224Q79NrBnbgTtMqaS3x2avLkJmdZpneafqeO5OusOFcvsHvBr7ca0qKv5yIpn4eotK2bo6TFuaC9e9i7gUgPKHb1/GXAK1DcteUDF3AzK/b7T+dqTS+1vowuNKjMZ+ecyB8VDXQlWnBcv/IGn/C3nBmtp2oN97BFQtHguCY42Qk9LZxIu9o0mpOt6aMRiIsfbWstgONKaLzgt4Ce3DFlJ7YR5BFRaoKDdGHoCW+tcucQ/o9vFCbBVZ8sol2aYJOiNHYxlC8A7NLs6YEjyckVAa3q1l6CddnSjrFA5oe9fsLdzUDGhJ57Nv7kF9v6jjsTlZtucrzf8ix9+vNKNfWLQ6K86UIeBT40pPYHLBmWEsiGai+s4IWrYjTscT4zQDHcfQCMuQbbb3NTEfy9Fwv0VQdIR/cKsQgUCZwwlv3RBImryuDFqY2pNOqvnGIcr/OJ/MmY9bbCYEp55dxrZ50dNBbtR4O8IyUDte/ycU4OKbE="
|
secure: IZKEl1/LnzCN4/uMPKqUktURoNFjDmrybGKwrKbTPS27iXLrC9x4NwrQnOgipLF5h6Jeee4Qf1LhFCEpL/VTBTGMljQU2uOUFqn7TTGV5Ok7wxn2Z4CYeLDHMqDeGEECidAs8pB7I8lQvk5iUqmQT0NbuB0tDgavM9XCAecGUrFHh2tQaqPRGgZ1Q+1QB5d68EItSncMFKgRKja3Jq3u6ArF3uR3qY0dx9UKgcSUkKMnYbkBoEmiuCthdtwsH6WiIp4+K5GnVkGWxFa6KwdUJseHvUCuwS0Jp6lz47fP75xr4pHP45BxL7s549P60Iyr5AMRUge2+LPQV5QdbRH4guQV6qWI2L6Vw64fdC3lK00MhNFNO4M9p1T9eeldXhvUJwBDjzjoHlsrZysUMBy5G9CpQIVJtaPSVMWm/9yfPbu/B3k85cCHLb3fTos3altCWREIUScWIdDAHczJmmITUE9d5KljT8t2gLzCiCqB3BQ6ZzN8Ur68EIJ2ePuCO4644S+1shg5AXYDzXuUd30J57UGnuELQSMQkuZvMUQy8PmNO/iInIqpnuAwOwT4YD0MHgXrjD38a9+KszDjY+9HrIWcQE8P7AuN0iVf2voB5uLTOckkd4mXF9sskwoREVYJM+jz49HViggYyn1MHLsnlY5//vhMo5HNaf2DtT8fhk4=
|
||||||
file_glob: true
|
file_glob: true
|
||||||
file: "../WebApp-Releases/*"
|
file: "../WebApp-Releases/*"
|
||||||
skip_cleanup: true
|
skip_cleanup: true
|
||||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -2,17 +2,6 @@
|
||||||
|
|
||||||
# Next Release
|
# Next Release
|
||||||
|
|
||||||
# 0.1.13
|
|
||||||
|
|
||||||
* Added new graphs for organisation view, for better breakdown of spending
|
|
||||||
* Added Suppliers spend search page
|
|
||||||
* Updated and fixes numerous graphs on dashboard
|
|
||||||
|
|
||||||
## Minor
|
|
||||||
|
|
||||||
* *Dev Fixes* Updated Travis config
|
|
||||||
|
|
||||||
|
|
||||||
# 0.1.12
|
# 0.1.12
|
||||||
|
|
||||||
* Fixed accidentally added app-root
|
* Fixed accidentally added app-root
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?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>
|
|
123
README.md
123
README.md
|
@ -1,43 +1,30 @@
|
||||||
# LocalSpend - Web Application
|
# LocalLoop Web Interface
|
||||||
|
|
||||||
This repository contains the Web application for the LocalSpend system.
|
This is the repository for the LocalLoop web interface, for traders and
|
||||||
|
customers to see and submit data to the service.
|
||||||
## Current Status
|
|
||||||
|
|
||||||
| Branch | Status |
|
| Branch | Status |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `master` | [![Build Status](https://travis-ci.org/Pear-Trading/FoodLoop-Web.svg?branch=master)](https://travis-ci.org/Pear-Trading/FoodLoop-Web) |
|
| *Master:* | [![Build Status](https://travis-ci.org/Pear-Trading/FoodLoop-Web.svg?branch=master)](https://travis-ci.org/Pear-Trading/FoodLoop-Web) |
|
||||||
| `development` | [![Build Status](https://travis-ci.org/Pear-Trading/FoodLoop-Web.svg?branch=development)](https://travis-ci.org/Pear-Trading/FoodLoop-Web) |
|
| *Development:* | [![Build Status](https://travis-ci.org/Pear-Trading/FoodLoop-Web.svg?branch=development)](https://travis-ci.org/Pear-Trading/FoodLoop-Web) |
|
||||||
|
|
||||||
## Contents
|
|
||||||
|
|
||||||
1. [Getting Started](#getting-started)
|
|
||||||
1. [Environments](#environments)
|
|
||||||
1. [Testing](#testing)
|
|
||||||
1. [Troubleshooting](#troubleshooting)
|
|
||||||
1. [Licences](#licenses)
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
To get started with development, you will need an up-to-date version of
|
To get started with development, you will need an up to date version of
|
||||||
Node.js, git, and access to either the backend dev. server or a local
|
node.js, git, and access to either the backend dev server, or a local running
|
||||||
copy of it from the [LocalSpend Server][LocalLoop-Server] repo.
|
copy of the backend server from [LocalLoop Server][LocalLoop-Server].
|
||||||
|
|
||||||
For your local Node.js, we recommend using:
|
For your local node.js, We reccomend using [n][tj/n] on \*nix and Mac, for
|
||||||
- [n][tj/n] for \*nix and Mac; and
|
Windows take a look at [nodist][marcelklehr/nodist] - although other options
|
||||||
- [nodist][marcelklehr/nodist] for Windows.
|
exist. We reccomend Node.js version 8.0.0+ and npm version 5.3.0+.
|
||||||
|
|
||||||
We reccomend Node.js version 8.0.0+ and npm version 5.3.0+.
|
To get this repository set up, first clone it and then run the following
|
||||||
|
commands:
|
||||||
|
|
||||||
To get this repository set up:
|
```
|
||||||
|
npm install -g @angular/cli
|
||||||
1. Clone it
|
npm install
|
||||||
2. Install the dependencies:
|
```
|
||||||
- `npm install -g @angular/cli`
|
|
||||||
- `npm install`
|
|
||||||
3. Start the application:
|
|
||||||
- `npm start`
|
|
||||||
- The app. will automatically reload after source file changes
|
|
||||||
|
|
||||||
[LocalLoop-Server]:https://github.com/Pear-Trading/Foodloop-Server
|
[LocalLoop-Server]:https://github.com/Pear-Trading/Foodloop-Server
|
||||||
[tj/n]:https://github.com/tj/n
|
[tj/n]:https://github.com/tj/n
|
||||||
|
@ -45,52 +32,46 @@ To get this repository set up:
|
||||||
|
|
||||||
## Environments
|
## Environments
|
||||||
|
|
||||||
The app defaults to using the development server. For other options, see
|
The app defaults to using the development server. For other options, see
|
||||||
`src/environments/environments.ts`.
|
`src/environments/environments.ts`
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build` to build the project; the resulting files will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
There are two types of test in this codebase:
|
|
||||||
- unit tests (using Karma); and
|
|
||||||
- E2E tests (using Protractor).
|
|
||||||
|
|
||||||
### Karma Unit Tests
|
|
||||||
|
|
||||||
To run these, you just need to run `npm run test` - this should work without any further configuration. These run the `*.spec.ts` files next to the normal source files, and are for basic tests for each function on their own.
|
|
||||||
|
|
||||||
These tests are a long-running process, and will automatically run on file changes. Just run the command above, and then check back to the browser window that appears to see any errors as you work!
|
|
||||||
|
|
||||||
### Protractor E2E Tests
|
|
||||||
|
|
||||||
To run these, you will need to run the following command:
|
|
||||||
|
|
||||||
- `webdriver-manager update`
|
|
||||||
|
|
||||||
This will download the correct webdriver for you (we use chromedriver), and
|
|
||||||
any other dependencies it needs.
|
|
||||||
After that, you can run the tests with `npm run e2e`.
|
|
||||||
Note these run once, and will need to be re-run every time you want to run an
|
|
||||||
e2e test.
|
|
||||||
|
|
||||||
These tests are best run regularly, and should show if any issues have emerged
|
|
||||||
in other parts of the application that you are not aware of, or if some part
|
|
||||||
of the flow through the app has changed significantly.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### ‘Error: EACCES: permission denied, access '/usr/local/lib'’ when installing dependencies
|
|
||||||
|
|
||||||
Change npm's default directory by following [these steps](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally#manually-change-npms-default-directory).
|
|
||||||
|
|
||||||
## Licences
|
## Licences
|
||||||
|
|
||||||
### CoreUI
|
### CoreUI
|
||||||
|
|
||||||
The interface itself is based off of [CoreUI][core-ui] which is MIT Licenced.
|
The interface itself is based off of [CoreUI][core-ui] which is MIT Licenced.
|
||||||
For information, see `LICENCE.MIT` included in this repo.
|
For information, see [MIT Licence](./LICENCE.MIT) included in this repo.
|
||||||
|
|
||||||
[core-ui]: http://coreui.io
|
[core-ui]: http://coreui.io
|
||||||
|
|
||||||
|
# Old README
|
||||||
|
|
||||||
|
This is the old README with some minor tips on getting started, and more reading.
|
||||||
|
|
||||||
|
## Angular2DevelopmentCLI
|
||||||
|
|
||||||
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0-beta.32.3.
|
||||||
|
|
||||||
|
### Development server
|
||||||
|
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||||
|
|
||||||
|
### Code scaffolding
|
||||||
|
|
||||||
|
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||||
|
|
||||||
|
### Running unit tests
|
||||||
|
|
||||||
|
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||||
|
|
||||||
|
### Running end-to-end tests
|
||||||
|
|
||||||
|
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||||
|
Before running the tests make sure you are serving the app via `ng serve`.
|
||||||
|
|
||||||
|
### Further help
|
||||||
|
|
||||||
|
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||||
|
|
10
angular.json
10
angular.json
|
@ -17,12 +17,7 @@
|
||||||
"tsConfig": "src/tsconfig.app.json",
|
"tsConfig": "src/tsconfig.app.json",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/assets",
|
"src/assets"
|
||||||
{"input":
|
|
||||||
"./node_modules/@google/markerclustererplus/images",
|
|
||||||
"glob": "*",
|
|
||||||
"output": "/images"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/scss/style.scss"
|
"src/scss/style.scss"
|
||||||
|
@ -117,6 +112,9 @@
|
||||||
"karmaConfig": "./karma.conf.js",
|
"karmaConfig": "./karma.conf.js",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "src/tsconfig.spec.json",
|
"tsConfig": "src/tsconfig.spec.json",
|
||||||
|
"scripts": [
|
||||||
|
"node_modules/moment/min/moment.min.js"
|
||||||
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/scss/style.scss"
|
"src/scss/style.scss"
|
||||||
],
|
],
|
||||||
|
|
|
@ -12,13 +12,13 @@ echo "Building releases for $VERSION"
|
||||||
|
|
||||||
echo "Building Prod Release..."
|
echo "Building Prod Release..."
|
||||||
|
|
||||||
npm run build:prod
|
ng build --prod
|
||||||
|
|
||||||
tar -czf ../WebApp-Releases/LocalLoop-Web-prod-$VERSION.tar.gz dist
|
tar -czf ../WebApp-Releases/LocalLoop-Web-prod-$VERSION.tar.gz dist
|
||||||
|
|
||||||
echo "Building Dev Release..."
|
echo "Building Dev Release..."
|
||||||
|
|
||||||
npm run build:dev
|
ng build --dev
|
||||||
|
|
||||||
tar -czf ../WebApp-Releases/LocalLoop-Web-dev-$VERSION.tar.gz dist
|
tar -czf ../WebApp-Releases/LocalLoop-Web-dev-$VERSION.tar.gz dist
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { LoginPageObject } from './login.po';
|
import { LoginPageObject } from './login.po';
|
||||||
import { browser } from "protractor";
|
|
||||||
|
|
||||||
describe('Login Page', () => {
|
describe('Login Page', () => {
|
||||||
let page: LoginPageObject;
|
let page: LoginPageObject;
|
||||||
|
@ -14,46 +13,12 @@ describe('Login Page', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a username box of type email', () => {
|
it('should have a username box of type email', () => {
|
||||||
expect(page.isEmailFieldPresent()).toBeTruthy();
|
expect(page.isUsernameFieldPresent()).toBeTruthy();
|
||||||
expect(page.getEmailFieldType()).toEqual('email');
|
expect(page.getUsernameFieldType()).toEqual('email');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a password box of type password', () => {
|
it('should have a password box of type password', () => {
|
||||||
expect(page.isPasswordFieldPresent()).toBeTruthy();
|
expect(page.isPasswordFieldPresent()).toBeTruthy();
|
||||||
expect(page.getPasswordFieldType()).toBe('password');
|
expect(page.getPasswordFieldType()).toBe('password');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a login button of type submit', () => {
|
|
||||||
expect(page.isLoginButtonPresent()).toBeTruthy();
|
|
||||||
expect(page.getLoginButtonType()).toBe('submit');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a disabled login button when empty', () => {
|
|
||||||
expect(page.isLoginButtonEnabled()).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a disabled login button when only email', () => {
|
|
||||||
page.fillEmailFieldWith('test@example.com');
|
|
||||||
expect(page.isLoginButtonEnabled()).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a disabled login button when only password', () => {
|
|
||||||
page.fillPasswordFieldWith('abc123');
|
|
||||||
expect(page.isLoginButtonEnabled()).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have an enabled login button when both inputs filled', () => {
|
|
||||||
page.fillEmailFieldWith('test@example.com');
|
|
||||||
page.fillPasswordFieldWith('abc123');
|
|
||||||
expect(page.isLoginButtonEnabled()).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should submit the filled data when login pressed', () => {
|
|
||||||
page.fillEmailFieldWith('test@example.com');
|
|
||||||
page.fillPasswordFieldWith('abc123');
|
|
||||||
expect(page.isLoginButtonEnabled()).toBeTruthy();
|
|
||||||
page.getLoginButton().click();
|
|
||||||
browser.waitForAngular();
|
|
||||||
expect(browser.getCurrentUrl()).toContain('dashboard');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,23 +9,12 @@ export class LoginPageObject {
|
||||||
return element(by.css('app-root h1')).getText();
|
return element(by.css('app-root h1')).getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
getEmailField() { return element(by.id('username')); }
|
getUsernameField() { return element(by.id('username')); }
|
||||||
getPasswordField() { return element(by.id('password')); }
|
getPasswordField() { return element(by.id('password')); }
|
||||||
getLoginButton() { return element(by.id('login')); }
|
|
||||||
|
|
||||||
isEmailFieldPresent() { return this.getEmailField().isPresent(); }
|
isUsernameFieldPresent() { return this.getUsernameField().isPresent(); }
|
||||||
isPasswordFieldPresent() { return this.getPasswordField().isPresent(); }
|
isPasswordFieldPresent() { return this.getPasswordField().isPresent(); }
|
||||||
isLoginButtonPresent() { return this.getLoginButton().isPresent(); }
|
|
||||||
|
|
||||||
getEmailFieldType() { return this.getEmailField().getAttribute('type'); }
|
getUsernameFieldType() { return this.getUsernameField().getAttribute('type'); }
|
||||||
getPasswordFieldType() { return this.getPasswordField().getAttribute('type'); }
|
getPasswordFieldType() { return this.getPasswordField().getAttribute('type'); }
|
||||||
getLoginButtonType() { return this.getLoginButton().getAttribute('type'); }
|
|
||||||
|
|
||||||
isLoginButtonEnabled() { return this.getLoginButton().isEnabled(); }
|
|
||||||
|
|
||||||
clearEmailField() { return this.getEmailField().clear() };
|
|
||||||
clearPasswordField() { return this.getPasswordField().clear() };
|
|
||||||
|
|
||||||
fillEmailFieldWith(text) { return this.getEmailField().sendKeys(text) };
|
|
||||||
fillPasswordFieldWith(text) { return this.getPasswordField().sendKeys(text) };
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ module.exports = function (config) {
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
plugins: [
|
plugins: [
|
||||||
require('karma-jasmine'),
|
require('karma-jasmine'),
|
||||||
|
require("readable-stream");
|
||||||
require('karma-chrome-launcher'),
|
require('karma-chrome-launcher'),
|
||||||
require('karma-jasmine-html-reporter'),
|
require('karma-jasmine-html-reporter'),
|
||||||
require('karma-coverage-istanbul-reporter'),
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
|
11290
package-lock.json
generated
11290
package-lock.json
generated
File diff suppressed because it is too large
Load diff
60
package.json
60
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "localloop-web",
|
"name": "localloop-web",
|
||||||
"version": "0.1.13",
|
"version": "0.1.11",
|
||||||
"description": "LocalLoop Web - Web interface for LocalLoop app",
|
"description": "LocalLoop Web - Web interface for LocalLoop app",
|
||||||
"author": "",
|
"author": "",
|
||||||
"url": "http://www.peartrade.org",
|
"url": "http://www.peartrade.org",
|
||||||
|
@ -8,13 +8,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"start:dev": "ng serve --optimization=false --configuration=dev",
|
"build": "ng build",
|
||||||
"start:prod": "ng serve --optimization=false --configuration=production",
|
|
||||||
"start:local": "ng serve --optimization=false --configuration=local",
|
|
||||||
"build:dev": "ng build --configuration=dev",
|
|
||||||
"build:prod": "ng build --configuration=production",
|
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"test:ci": "ng test --watch=false --browsers=ChromeHeadless",
|
"test:ci": "ng test --watch=false",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"e2e": "ng e2e",
|
"e2e": "ng e2e",
|
||||||
"e2e:ci": "ng e2e --configuration=ci",
|
"e2e:ci": "ng e2e --configuration=ci",
|
||||||
|
@ -22,67 +18,63 @@
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agm/core": "^3.0.0-beta.0",
|
"@agm/core": "1.0.0-beta.6",
|
||||||
"@agm/markerclusterer": "^3.0.0-beta.0",
|
"@agm/js-marker-clusterer": "1.0.0-beta.6",
|
||||||
"@angular/common": "10.0.6",
|
"@angular/common": "8.1.0",
|
||||||
"@angular/compiler": "10.0.6",
|
"@angular/compiler": "8.1.0",
|
||||||
"@angular/core": "10.0.6",
|
"@angular/core": "8.1.0",
|
||||||
"@angular/forms": "10.0.6",
|
"@angular/forms": "8.1.0",
|
||||||
"@angular/platform-browser": "10.0.6",
|
"@angular/platform-browser": "8.1.0",
|
||||||
"@angular/platform-browser-dynamic": "10.0.6",
|
"@angular/platform-browser-dynamic": "8.1.0",
|
||||||
"@angular/router": "10.0.6",
|
"@angular/router": "8.1.0",
|
||||||
"@angular/upgrade": "10.0.6",
|
"@angular/upgrade": "8.1.0",
|
||||||
"@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1",
|
"@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1",
|
||||||
"@coreui/icons": "0.3.0",
|
"@coreui/icons": "0.3.0",
|
||||||
"@google/markerclustererplus": "^5.0.4",
|
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
"ajv-keywords": "^3.4.0",
|
"ajv-keywords": "^3.4.0",
|
||||||
"angular2-datetimepicker": "^1.1.1",
|
|
||||||
"chart.js": "^2.8.0",
|
"chart.js": "^2.8.0",
|
||||||
"chartjs-adapter-luxon": "^0.2.0",
|
"chartjs-adapter-luxon": "^0.2.0",
|
||||||
"core-js": "^2.6.9",
|
"core-js": "^2.6.9",
|
||||||
"devextreme": "^19.1.4",
|
"devextreme": "^19.1.4",
|
||||||
"devextreme-angular": "^19.1.4",
|
"devextreme-angular": "^19.1.4",
|
||||||
"jasmine": "^3.4.0",
|
"jasmine": "^3.4.0",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.3.1",
|
||||||
|
"js-marker-clusterer": "1.0.0",
|
||||||
"jszip": "^3.2.2",
|
"jszip": "^3.2.2",
|
||||||
"luxon": "^1.16.1",
|
"luxon": "^1.16.1",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"ng2-charts": "^2.3.2",
|
"ng2-charts": "^2.3.0",
|
||||||
"ng2-validation-manager": "0.5.3",
|
"ng2-validation-manager": "0.5.3",
|
||||||
"ngx-bootstrap": "^5.0.0",
|
"ngx-bootstrap": "^5.0.0",
|
||||||
"ngx-filter-pipe": "^2.1.2",
|
|
||||||
"ngx-pagination": "^4.0.0",
|
"ngx-pagination": "^4.0.0",
|
||||||
"popper.js": "^1.15.0",
|
"popper.js": "^1.15.0",
|
||||||
"rxjs": "6.6.0",
|
"rxjs": "6.5.2",
|
||||||
"stream": "0.0.2",
|
"stream": "0.0.2",
|
||||||
"ts-helpers": "1.1.2",
|
"ts-helpers": "1.1.2",
|
||||||
"tslib": "^1.10.0",
|
"tslib": "^1.10.0",
|
||||||
"web-animations-js": "^2.3.2",
|
"web-animations-js": "^2.3.2",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.7.2",
|
||||||
"zone.js": "~0.10.3"
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^0.1000.4",
|
"@angular-devkit/build-angular": "~0.801.0",
|
||||||
"@angular/cli": "^10.0.4",
|
"@angular/cli": "^8.1.0",
|
||||||
"@angular/compiler-cli": "10.0.6",
|
"@angular/compiler-cli": "8.1.0",
|
||||||
"@types/googlemaps": "^3.39.8",
|
|
||||||
"@types/jasmine": "3.3.13",
|
"@types/jasmine": "3.3.13",
|
||||||
"@types/jasminewd2": "2.0.6",
|
"@types/jasminewd2": "2.0.6",
|
||||||
"@types/node": "12.0.10",
|
"@types/node": "12.0.10",
|
||||||
"codelyzer": "^6.0.0",
|
"codelyzer": "^5.1.0",
|
||||||
"jasmine-core": "^3.4.0",
|
"jasmine-core": "^3.4.0",
|
||||||
"jasmine-spec-reporter": "4.2.1",
|
"jasmine-spec-reporter": "4.2.1",
|
||||||
"karma": "^5.1.1",
|
"karma": "^4.1.0",
|
||||||
"karma-chrome-launcher": "2.2.0",
|
"karma-chrome-launcher": "2.2.0",
|
||||||
"karma-cli": "2.0.0",
|
"karma-cli": "2.0.0",
|
||||||
"karma-coverage-istanbul-reporter": "^2.0.5",
|
"karma-coverage-istanbul-reporter": "^2.0.5",
|
||||||
"karma-jasmine": "^2.0.1",
|
"karma-jasmine": "^2.0.1",
|
||||||
"karma-jasmine-html-reporter": "^1.4.2",
|
"karma-jasmine-html-reporter": "^1.4.2",
|
||||||
"protractor": "^7.0.0",
|
"protractor": "^5.4.2",
|
||||||
"readable-stream": "latest",
|
|
||||||
"ts-node": "^8.3.0",
|
"ts-node": "^8.3.0",
|
||||||
"tslint": "^5.18.0",
|
"tslint": "^5.18.0",
|
||||||
"typescript": "~3.9.7"
|
"typescript": "~3.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,7 @@ exports.config = {
|
||||||
'./e2e/**/*.e2e-spec.ts'
|
'./e2e/**/*.e2e-spec.ts'
|
||||||
],
|
],
|
||||||
capabilities: {
|
capabilities: {
|
||||||
'browserName': 'chrome',
|
'browserName': 'chrome'
|
||||||
chromeOptions: {
|
|
||||||
args: [ "--headless" ]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
directConnect: true,
|
directConnect: true,
|
||||||
baseUrl: 'http://localhost:4200/',
|
baseUrl: 'http://localhost:4200/',
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||||
|
@ -41,18 +40,17 @@ import { P500Component } from './pages/500.component';
|
||||||
// Submodules
|
// Submodules
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { DashboardModule } from './dashboard/dashboard.module';
|
import { DashboardModule } from './dashboard/dashboard.module';
|
||||||
|
|
||||||
import { ChartsModule } from 'ng2-charts';
|
import { ChartsModule } from 'ng2-charts';
|
||||||
// import { StackedBarChartComponent } from './panels/stacked-bar.component';
|
// import { StackedBarChartComponent } from './panels/stacked-bar.component';
|
||||||
import { FilterPipeModule } from 'ngx-filter-pipe';
|
import { SuppliersComponent } from './dashboard/suppliers.component';
|
||||||
|
import { MoreStuffComponent } from './dashboard/more-graphs-and-tables.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
FormsModule,
|
|
||||||
FilterPipeModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
NgxPaginationModule,
|
NgxPaginationModule,
|
||||||
BsDropdownModule.forRoot(),
|
BsDropdownModule.forRoot(),
|
||||||
TabsModule.forRoot(),
|
TabsModule.forRoot(),
|
||||||
|
@ -71,8 +69,11 @@ import { FilterPipeModule } from 'ngx-filter-pipe';
|
||||||
BreadcrumbsComponent,
|
BreadcrumbsComponent,
|
||||||
SIDEBAR_TOGGLE_DIRECTIVES,
|
SIDEBAR_TOGGLE_DIRECTIVES,
|
||||||
AsideToggleDirective,
|
AsideToggleDirective,
|
||||||
|
SuppliersComponent,
|
||||||
|
MoreStuffComponent,
|
||||||
P404Component,
|
P404Component,
|
||||||
P500Component,
|
P500Component,
|
||||||
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AuthGuard,
|
AuthGuard,
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<button id="login" type="submit" [disabled]="!signin.valid" class="btn btn-primary px-4">Login</button>
|
<button type="submit" [disabled]="!signin.valid" class="btn btn-primary px-4">Login</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-right">
|
<div class="col-6 text-right">
|
||||||
<button type="button" class="btn btn-link px-0" disabled>Forgot password?</button>
|
<button type="button" class="btn btn-link px-0" disabled>Forgot password?</button>
|
||||||
|
|
|
@ -40,11 +40,15 @@ export class LoginComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
console.log(this.signin.value);
|
||||||
|
|
||||||
this.api
|
this.api
|
||||||
.login(this.signin.value)
|
.login(this.signin.value)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
result => {
|
result => {
|
||||||
|
console.log('logged in!');
|
||||||
this.loginStatus = 'success';
|
this.loginStatus = 'success';
|
||||||
|
console.log(this.loginStatus);
|
||||||
this.router.navigate([this.returnUrl]);
|
this.router.navigate([this.returnUrl]);
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class RegisterComponent {
|
||||||
password: signupForm.password,
|
password: signupForm.password,
|
||||||
display_name: customerForm.display_name,
|
display_name: customerForm.display_name,
|
||||||
full_name: customerForm.full_name,
|
full_name: customerForm.full_name,
|
||||||
postcode: customerForm.postcode.toUpperCase(),
|
postcode: customerForm.postcode,
|
||||||
year_of_birth: customerForm.year_of_birth,
|
year_of_birth: customerForm.year_of_birth,
|
||||||
};
|
};
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
@ -114,8 +114,9 @@ export class RegisterComponent {
|
||||||
sector: organisationForm.sector,
|
sector: organisationForm.sector,
|
||||||
street_name: organisationForm.street_name,
|
street_name: organisationForm.street_name,
|
||||||
town: organisationForm.town,
|
town: organisationForm.town,
|
||||||
postcode: organisationForm.postcode.toUpperCase(),
|
postcode: organisationForm.postcode,
|
||||||
};
|
};
|
||||||
|
console.log(data);
|
||||||
this.api
|
this.api
|
||||||
.register(data)
|
.register(data)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
|
|
|
@ -89,7 +89,7 @@ export class AccountEditComponent implements OnInit {
|
||||||
|
|
||||||
const submitData = {
|
const submitData = {
|
||||||
email: settingForm.email,
|
email: settingForm.email,
|
||||||
postcode: settingForm.postcode.toUpperCase(),
|
postcode: settingForm.postcode,
|
||||||
password: settingForm.password,
|
password: settingForm.password,
|
||||||
new_password: settingForm.new_password,
|
new_password: settingForm.new_password,
|
||||||
name: settingOrganisationForm.name,
|
name: settingOrganisationForm.name,
|
||||||
|
@ -142,7 +142,7 @@ export class AccountEditComponent implements OnInit {
|
||||||
|
|
||||||
const submitData = {
|
const submitData = {
|
||||||
email: settingForm.email,
|
email: settingForm.email,
|
||||||
postcode: settingForm.postcode.toUpperCase(),
|
postcode: settingForm.postcode,
|
||||||
password: settingForm.password,
|
password: settingForm.password,
|
||||||
new_password: settingForm.new_password,
|
new_password: settingForm.new_password,
|
||||||
full_name: settingCustomerForm.full_name,
|
full_name: settingCustomerForm.full_name,
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
<span class="help-block">Enter the amount spent, such as 5.35 for £5.35.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input">Essential Purchase</label>
|
<label class="col-md-3 form-control-label" for="text-input">Essential Purchase</label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
|
@ -157,14 +156,14 @@
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of Employees</strong></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input type="number" class="form-control" formControlName="employee_amount" placeholder="0" min="0">
|
<input type="number" class="form-control" formControlName="employee_amount" placeholder="0">
|
||||||
<span class="help-block">Enter the amount of employees the organisation has for the entry month.</span>
|
<span class="help-block">Enter the amount of employees the organisation has for the entry month.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
<label class="col-md-3 form-control-label" for="text-input"><strong>Total amount of local Employees</strong></label>
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<input type="number" class="form-control" formControlName="local_employee_amount" placeholder="0" min="0">
|
<input type="number" class="form-control" formControlName="local_employee_amount" placeholder="0">
|
||||||
<span class="help-block">Enter the amount of employees that live locally to the organisation for the entry month.</span>
|
<span class="help-block">Enter the amount of employees that live locally to the organisation for the entry month.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<div class=row>
|
<div class=row>
|
||||||
<div *ngIf="weekList1" class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div *ngIf="weekList2" class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div *ngIf="weekList3" class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -126,7 +126,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div *ngIf="weekList4" class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
<div id="stacked-bar" dx-chart="chartOptions"></div>
|
<div id="stacked-bar" dx-chart="chartOptions"></div>
|
||||||
</div> -->
|
</div> -->
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<!--<div *ngIf="showCategoryDoughnutChart" class="col-xl-6">
|
<div *ngIf="showCategoryDoughnutChart" class="col-xl-6">
|
||||||
<div class="card"> -->
|
<div class="card">
|
||||||
<!-- <body style="background-color:rgb(0,0,0);"> -->
|
<!-- <body style="background-color:rgb(0,0,0);"> -->
|
||||||
<!-- <div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title mb-0">Spending by Category</h4>
|
<h4 class="card-title mb-0">Weekly Spending by Category</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
|
@ -31,15 +31,15 @@
|
||||||
[datasets]="doughnutChartDataCategory"
|
[datasets]="doughnutChartDataCategory"
|
||||||
[labels]="doughnutChartLabelsCategory"
|
[labels]="doughnutChartLabelsCategory"
|
||||||
[options]="doughnutChartOptionsCategory"
|
[options]="doughnutChartOptionsCategory"
|
||||||
[colors]= "doughnutChartColoursCategory"
|
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
[chartType]="chartType"
|
[chartType]="chartType"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
(chartClick)="chartClicked($event)"></canvas>
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
<!-- </body> -->
|
<!-- </body> -->
|
||||||
<!-- </div> --><!--/.col-->
|
</div>
|
||||||
|
</div><!--/.col-->
|
||||||
<div *ngIf="showEssentialBarChart" class="col-xl-6">
|
<div *ngIf="showEssentialBarChart" class="col-xl-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
|
@ -60,20 +60,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
<div class="col-xl-6">
|
<div *ngIf="showCategoryBarChart" class="col-xl-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0">Your Purchases by Category</h4>
|
<h4 class="card-title mb-0">Monthly Spending by Category</h4>
|
||||||
</div><!--/.col-->
|
</div>
|
||||||
</div><!--/.row-->
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart
|
||||||
[datasets]="barChartDataCategory"
|
[datasets]="barChartDataCategory"
|
||||||
[labels]="barChartLabelsCategory"
|
[labels]="barChartLabelsCategory"
|
||||||
[options]="barChartOptionsCategory"
|
[options]="barChartOptionsCategory"
|
||||||
[colors]="barChartColoursCategory"
|
|
||||||
[legend]="barChartLegendCategory"
|
[legend]="barChartLegendCategory"
|
||||||
[chartType]="barChartTypeCategory"
|
[chartType]="barChartTypeCategory"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
|
@ -87,29 +86,137 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0"> Global Puchases by Category</h4>
|
<h4 class="card-title float-left mb-0">Weekly Purchase No.</h4>
|
||||||
</div>
|
</div><!--/.col-->
|
||||||
<div class="col-12">
|
</div><!--/.row-->
|
||||||
<div *ngIf="showTotalCategoryList" class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<ul class="icons-list">
|
<ul class="horizontal-bars type-2">
|
||||||
<!-- New loop -->
|
<li>
|
||||||
<li *ngFor="let category of totalCategoryList | slice:0:totalCategoryLimit; let i=index">
|
<span class="title">This Week</span>
|
||||||
<i [ngClass]="['icon-' + category.icon, getBootstrapColour(i)]"></i>
|
<span class="value">{{ (weekPurchaseList.first || 0 ) }} <span class="text-muted small">
|
||||||
<div class="desc">
|
({{ (weekPurchaseList.first || 0 ) / weekPurchaseList.max | percent:'1.0-0' }})</span></span>
|
||||||
<div class="title">{{ category.category || 'N/A' }}</div>
|
<div class="bars">
|
||||||
</div>
|
<div class="progress" style="height: 6px;">
|
||||||
<div class="value">
|
<div class="progress-bar bg-success" role="progressbar"
|
||||||
<div class="small text-muted">Bought</div>
|
[style.width]="(weekPurchaseList.first || 0 ) / weekPurchaseList.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
<strong>{{ category.value || 'N/A' }}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
<li *ngIf="totalCategoryList.length > totalCategoryLimit && disableCategoryButton == false" class="divider text-center">
|
</li>
|
||||||
<button type="button" class="btn btn-sm btn-link text-muted" (click)="categoryLoadMore()"><i class="icon-options"></i></button>
|
<li>
|
||||||
</li>
|
<span class="title">Last Week</span>
|
||||||
</ul>
|
<span class="value">{{ weekPurchaseList.second || 0 }} <span class="text-muted small">
|
||||||
</div>
|
({{ (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><!--/.row-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div><!--/.col-->
|
||||||
</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">All Purchases by Category</h4>
|
||||||
|
</div><!--/.col-->
|
||||||
|
</div><!--/.row-->
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="barChartDataCategoryAll"
|
||||||
|
[labels]="barChartLabelsCategory"
|
||||||
|
[options]="barChartOptionsCategory"
|
||||||
|
[legend]="barChartLegendCategory"
|
||||||
|
[chartType]="barChartTypeCategory"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
<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><!--/.col-->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title float-left mb-0">Spend by company and Industrial sector</h4>
|
||||||
|
</div><!--/.col-->
|
||||||
|
</div><!--/.row-->
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="lineChartData"
|
||||||
|
[labels]="lineChartLabels"
|
||||||
|
[options]="lineChartOptions"
|
||||||
|
[legend]="lineChartLegend"
|
||||||
|
[chartType]="lineChartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
<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><!--/.col-->
|
||||||
|
</div><!--/.row-->
|
||||||
|
</div>
|
||||||
|
|
|
@ -2,17 +2,16 @@ import { Directive, Component, OnInit } from '@angular/core';
|
||||||
import { CurrencyPipe } from '@angular/common';
|
import { CurrencyPipe } from '@angular/common';
|
||||||
import { ApiService } from '../providers/api-service';
|
import { ApiService } from '../providers/api-service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
|
||||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
import { Color, Label } from 'ng2-charts';
|
|
||||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||||
import { PiePanel } from '../panels/pie-panel.component';
|
import { PiePanel } from '../panels/pie-panel.component';
|
||||||
import { DataType } from '../shared/data-types.enum';
|
import { DataType } from '../shared/data-types.enum';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
import { SuppliersComponent } from '../dashboard/suppliers.component';
|
||||||
import { MoreStuffComponent } from '../dashboard/more-graphs-and-tables.component';
|
import { MoreStuffComponent } from '../dashboard/more-graphs-and-tables.component';
|
||||||
// import { StackedBarChartComponent } from '../panels/stacked-bar.component';
|
// import { StackedBarChartComponent } from '../panels/stacked-bar.component';
|
||||||
|
|
||||||
interface SuppliersComponent {
|
interface RecurSupplierData {
|
||||||
name : string;
|
name : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,22 +38,6 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataCategory: any[] = [];
|
public doughnutChartDataCategory: any[] = [];
|
||||||
public doughnutChartLabelsCategory: string[] = [];
|
public doughnutChartLabelsCategory: string[] = [];
|
||||||
public doughnutChartColoursCategory: any[] = [
|
|
||||||
{
|
|
||||||
backgroundColor:[
|
|
||||||
'#ffa1b5',
|
|
||||||
'#3cde52',
|
|
||||||
'#52afed',
|
|
||||||
'#c133e3',
|
|
||||||
'#f7fa08',
|
|
||||||
'#75152d',
|
|
||||||
'#ee12ee',
|
|
||||||
'#15eaea',
|
|
||||||
'#eaa015',
|
|
||||||
'#ea1515',
|
|
||||||
'#2d4fcc'
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
|
|
||||||
public doughnutChartOptionsCategory:any = {
|
public doughnutChartOptionsCategory:any = {
|
||||||
tooltips: {
|
tooltips: {
|
||||||
|
@ -85,12 +68,11 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
scales:{
|
scales:{
|
||||||
xAxes:[{
|
xAxes:[{
|
||||||
scaleLabel: {
|
stacked:true
|
||||||
display:true,
|
|
||||||
},
|
|
||||||
stacked:true,
|
|
||||||
|
|
||||||
}],
|
}],
|
||||||
|
yAxes:[{
|
||||||
|
stacked:true
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public barChartTypeEssential:string = 'horizontalBar';
|
public barChartTypeEssential:string = 'horizontalBar';
|
||||||
|
@ -118,22 +100,8 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
public barChartLegendCategory:boolean = false;
|
public barChartLegendCategory:boolean = false;
|
||||||
public barChartDataCategory:any[]=[];
|
public barChartDataCategory:any[]=[];
|
||||||
public barChartLabelsCategory:string[] = [];
|
public barChartLabelsCategory:string[] = [];
|
||||||
public barChartColoursCategory: any[] = [
|
public barChartDataCategoryAll:any[]=[];
|
||||||
{
|
|
||||||
backgroundColor:[
|
|
||||||
'#ffa1b5',
|
|
||||||
'#3cde52',
|
|
||||||
'#52afed',
|
|
||||||
'#c133e3',
|
|
||||||
'#f7fa08',
|
|
||||||
'#75152d',
|
|
||||||
'#ee12ee',
|
|
||||||
'#15eaea',
|
|
||||||
'#eaa015',
|
|
||||||
'#ea1515',
|
|
||||||
'#2d4fcc'
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
|
|
||||||
|
|
||||||
weekPurchaseList = {
|
weekPurchaseList = {
|
||||||
|
@ -148,6 +116,81 @@ export class DashboardCustomerComponent implements OnInit {
|
||||||
totalCategoryLimit: number = 10;
|
totalCategoryLimit: number = 10;
|
||||||
totalCategoryList: any[]=[];
|
totalCategoryList: any[]=[];
|
||||||
|
|
||||||
|
public lineChartData: ChartDataSets[] = [
|
||||||
|
{ data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A' },
|
||||||
|
{ data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B' },
|
||||||
|
{ data: [180, 480, 770, 90, 1000, 270, 400], label: 'Series C', yAxisID: 'y-axis-1' }
|
||||||
|
];
|
||||||
|
public lineChartLabels: Label[] = ['January', 'February', 'March', 'April', 'May', 'June', 'July','August','September','October','November','December'];
|
||||||
|
public lineChartOptions: (ChartOptions & { annotation: any }) = {
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
// We use this empty structure as a placeholder for dynamic theming.
|
||||||
|
xAxes: [{}],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
id: 'y-axis-0',
|
||||||
|
position: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'y-axis-1',
|
||||||
|
position: 'right',
|
||||||
|
gridLines: {
|
||||||
|
color: 'rgba(255,0,0,0.3)',
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
fontColor: 'red',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
annotation: {
|
||||||
|
annotations: [
|
||||||
|
{
|
||||||
|
type: 'line',
|
||||||
|
mode: 'vertical',
|
||||||
|
scaleID: 'x-axis-0',
|
||||||
|
value: 'March',
|
||||||
|
borderColor: 'orange',
|
||||||
|
borderWidth: 2,
|
||||||
|
label: {
|
||||||
|
enabled: true,
|
||||||
|
fontColor: 'orange',
|
||||||
|
content: 'LineAnno'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
public lineChartColors: 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 lineChartLegend = true;
|
||||||
|
public lineChartType = 'line';
|
||||||
|
|
||||||
|
|
||||||
// Graph widgets
|
// Graph widgets
|
||||||
public widgetList = [
|
public widgetList = [
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<snippet-bar-org></snippet-bar-org>
|
<snippet-bar-org></snippet-bar-org>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -12,71 +11,67 @@
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
</div><!--/.row-->
|
</div><!--/.row-->
|
||||||
<panel-graph></panel-graph>
|
<panel-graph></panel-graph>
|
||||||
<div class=row>
|
<div class="card">
|
||||||
<div class="col-xl-6">
|
<div class="card-block">
|
||||||
<div class="card">
|
<div class="row">
|
||||||
<div class="card-block">
|
<div class="col-12">
|
||||||
<div class="row">
|
<h4 class="card-title float-left mb-0">Spend by company and Industrial sector</h4>
|
||||||
<div class="col-12">
|
</div><!--/.col-->
|
||||||
<h4 class="card-title mb-0">Number of Essential Purchases</h4>
|
</div><!--/.row-->
|
||||||
</div>
|
<div class="chart-wrapper">
|
||||||
</div>
|
<canvas baseChart class="chart"
|
||||||
<div *ngIf="showEssentialBarChart" class="chart-wrapper">
|
[datasets]="lineChartDataSector"
|
||||||
<canvas baseChart class="chart"
|
[labels]="lineChartLabelsSector"
|
||||||
[datasets]="barChartDataEssential"
|
[options]="lineChartOptionsSector"
|
||||||
[labels]="barChartLabelsEssential"
|
[legend]="lineChartLegendSector"
|
||||||
[options]="barChartOptionsEssential"
|
[chartType]="lineChartTypeSector"
|
||||||
[chartType]="barChartTypeEssential"
|
(chartHover)="chartHovered($event)"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
(chartClick)="chartClicked($event)"></canvas>
|
</div>
|
||||||
|
</div>
|
||||||
|
</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">No. of Essential Purchases</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div 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>
|
||||||
<div class="col-xl-6">
|
</div><!--/.col-->
|
||||||
<div class="card">
|
<div class="col-xl-6">
|
||||||
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0">All Organisation Purchases by Category</h4>
|
<h4 class="card-title mb-0">Weekly Spending by Category</h4>
|
||||||
</div><!--/.col-->
|
</div>
|
||||||
</div><!--/.row-->
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
[datasets]="barChartDataCategory"
|
[datasets]="doughnutChartDataCategory"
|
||||||
[labels]="barChartLabelsCategory"
|
[labels]="doughnutChartLabelsCategory"
|
||||||
[options]="barChartOptionsCategory"
|
[options]="doughnutChartOptionsCategory"
|
||||||
[colors]="barChartColoursCategory"
|
[legend]="chartLegend"
|
||||||
[legend]="barChartLegendCategory"
|
[chartType]="chartType"
|
||||||
[chartType]="barChartTypeCategory"
|
(chartHover)="chartHovered($event)"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
(chartClick)="chartClicked($event)"></canvas>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.col-->
|
</div>
|
||||||
<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">
|
<div class="col-xl-6">
|
||||||
<org-pie-panel></org-pie-panel>
|
<org-pie-panel></org-pie-panel>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,29 +80,100 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title float-left mb-0"> Global Puchases by Category</h4>
|
<h4 class="card-title mb-0">Monthly Spending by Category</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
</div>
|
||||||
<div *ngIf="showTotalCategoryList" class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<ul class="icons-list">
|
<canvas baseChart
|
||||||
<!-- New loop -->
|
[datasets]="barChartDataCategory"
|
||||||
<li *ngFor="let category of totalCategoryList | slice:0:totalCategoryLimit; let i=index">
|
[labels]="barChartLabelsCategory"
|
||||||
<i [ngClass]="['icon-' + category.icon, getBootstrapColour(i)]"></i>
|
[options]="barChartOptionsCategory"
|
||||||
<div class="desc">
|
[legend]="barChartLegendCategory"
|
||||||
<div class="title">{{ category.category || 'N/A' }}</div>
|
[chartType]="barChartTypeCategory"
|
||||||
</div>
|
(chartHover)="chartHovered($event)"
|
||||||
<div class="value">
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
<div class="small text-muted">Bought</div>
|
</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>
|
</div>
|
||||||
</div>
|
</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">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>
|
||||||
|
<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 Purchases by Category</h4>
|
||||||
|
</div><!--/.col-->
|
||||||
|
</div><!--/.row-->
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[datasets]="barChartDataCategoryAll"
|
||||||
|
[labels]="barChartLabelsCategoryAll"
|
||||||
|
[options]="barChartOptionsCategoryAll"
|
||||||
|
[legend]="barChartLegendCategoryAll"
|
||||||
|
[chartType]="barChartTypeCategoryAll"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router, NavigationEnd } from "@angular/router";
|
import { Router, NavigationEnd } from "@angular/router";
|
||||||
import { CurrencyPipe } from '@angular/common';
|
import { CurrencyPipe } from '@angular/common';
|
||||||
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
|
||||||
import { Color, Label } from 'ng2-charts';
|
|
||||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||||
import { GraphPanel } from '../panels/graph-panel.component';
|
import { GraphPanel } from '../panels/graph-panel.component';
|
||||||
|
@ -44,13 +42,6 @@ export class DashboardComponent {
|
||||||
title: 'Sales Last 30 Days',
|
title: 'Sales Last 30 Days',
|
||||||
dataType: DataType.currency,
|
dataType: DataType.currency,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'graph',
|
|
||||||
name: 'sales_last_quart',
|
|
||||||
icon: 'icon-diamond',
|
|
||||||
title: 'Sales Last Quart',
|
|
||||||
dataType: DataType.currency,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'graph',
|
type: 'graph',
|
||||||
name: 'purchases_last_7_days',
|
name: 'purchases_last_7_days',
|
||||||
|
@ -63,12 +54,6 @@ export class DashboardComponent {
|
||||||
title: 'Purchases Last 30 Days',
|
title: 'Purchases Last 30 Days',
|
||||||
dataType: DataType.currency,
|
dataType: DataType.currency,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'graph',
|
|
||||||
name: 'purchases_last_quart;',
|
|
||||||
title: 'Purchases Last Quart',
|
|
||||||
dataType: DataType.currency,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
disableCategoryButton: boolean = false;
|
disableCategoryButton: boolean = false;
|
||||||
|
@ -80,22 +65,6 @@ export class DashboardComponent {
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataCategory: any[] = [];
|
public doughnutChartDataCategory: any[] = [];
|
||||||
public doughnutChartLabelsCategory: string[] = [];
|
public doughnutChartLabelsCategory: string[] = [];
|
||||||
public doughnutChartColoursCategory: any[] = [
|
|
||||||
{
|
|
||||||
backgroundColor:[
|
|
||||||
'#ffa1b5',
|
|
||||||
'#3cde52',
|
|
||||||
'#52afed',
|
|
||||||
'#c133e3',
|
|
||||||
'#f7fa08',
|
|
||||||
'#75152d',
|
|
||||||
'#ee12ee',
|
|
||||||
'#15eaea',
|
|
||||||
'#eaa015',
|
|
||||||
'#ea1515',
|
|
||||||
'#2d4fcc'
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
|
|
||||||
|
|
||||||
public doughnutChartOptionsCategory:any = {
|
public doughnutChartOptionsCategory:any = {
|
||||||
|
@ -114,13 +83,13 @@ export class DashboardComponent {
|
||||||
|
|
||||||
public purchaseNotEssential: number;
|
public purchaseNotEssential: number;
|
||||||
public purchaseEssential: number;
|
public purchaseEssential: number;
|
||||||
public showEssentialBarChart:boolean = false;
|
public showEssentialBarChart = false;
|
||||||
public showCategoryBarChart = false;
|
public showCategoryBarChart = false;
|
||||||
public showCategoryDoughnutChart = false;
|
public showCategoryDoughnutChart = false;
|
||||||
|
|
||||||
public barChartDataEssential: ChartDataSets[] = [
|
public barChartDataEssential:any[]=[
|
||||||
{data: [0], label: 'Essential', stack: '1'},
|
{data: 0, label: 'Essential', stack: '1'},
|
||||||
{data: [0], label: 'Non-Essential', stack: '1'},
|
{data: 0, label: 'Non-Essential', stack: '1'},
|
||||||
];
|
];
|
||||||
public barChartLabelsEssential:string[] = ['All Purchases'];
|
public barChartLabelsEssential:string[] = ['All Purchases'];
|
||||||
public barChartOptionsEssential:any = {
|
public barChartOptionsEssential:any = {
|
||||||
|
@ -135,22 +104,6 @@ export class DashboardComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public barChartTypeEssential:string = 'horizontalBar';
|
public barChartTypeEssential:string = 'horizontalBar';
|
||||||
public barChartColoursCategory: any[] = [
|
|
||||||
{
|
|
||||||
backgroundColor:[
|
|
||||||
'#ffa1b5',
|
|
||||||
'#3cde52',
|
|
||||||
'#52afed',
|
|
||||||
'#c133e3',
|
|
||||||
'#f7fa08',
|
|
||||||
'#75152d',
|
|
||||||
'#ee12ee',
|
|
||||||
'#15eaea',
|
|
||||||
'#eaa015',
|
|
||||||
'#ea1515',
|
|
||||||
'#2d4fcc'
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
|
|
||||||
public barChartOptionsCategory:any = {
|
public barChartOptionsCategory:any = {
|
||||||
scaleShowVerticalLines: false,
|
scaleShowVerticalLines: false,
|
||||||
|
@ -176,6 +129,12 @@ export class DashboardComponent {
|
||||||
public barChartDataCategory:any[]=[];
|
public barChartDataCategory:any[]=[];
|
||||||
public barChartLabelsCategory:string[] = [];
|
public barChartLabelsCategory:string[] = [];
|
||||||
|
|
||||||
|
public barChartDataCategoryAll:string = 'bar'
|
||||||
|
public barChartLegendCategoryAll:boolean = false;
|
||||||
|
public barChartDataCategoryAll:any[]=[];
|
||||||
|
public barChartLabelsCategoryAll:string[] = [];
|
||||||
|
|
||||||
|
|
||||||
public lineChartDataSector: ChartDataSets[] = [
|
public lineChartDataSector: ChartDataSets[] = [
|
||||||
{ data: [], label: '' },
|
{ data: [], label: '' },
|
||||||
];
|
];
|
||||||
|
@ -265,11 +224,17 @@ export class DashboardComponent {
|
||||||
this.setWeekPurchaseList(result.weeks);
|
this.setWeekPurchaseList(result.weeks);
|
||||||
this.setWeekData(result);
|
this.setWeekData(result);
|
||||||
this.setChartDataCat(result.data.cat_total);
|
this.setChartDataCat(result.data.cat_total);
|
||||||
this.setChartDataEssential(result.data.essentials);
|
|
||||||
this.totalCategoryList = result.data.cat_list;
|
this.totalCategoryList = result.data.cat_list;
|
||||||
if (this.totalCategoryList) {
|
if (this.totalCategoryList) {
|
||||||
this.showTotalCategoryList = true;
|
this.showTotalCategoryList = true;
|
||||||
}
|
}
|
||||||
|
this.purchaseEssential = result.data.essentials.purchase_no_essential_total;
|
||||||
|
this.purchaseNotEssential = result.data.essentials.purchase_no_total - this.purchaseEssential;
|
||||||
|
this.barChartDataEssential = [
|
||||||
|
{data: [this.purchaseEssential], label: 'Essential', stack: '1'},
|
||||||
|
{data: [this.purchaseNotEssential], label: 'Non-Essential', stack: '1'},
|
||||||
|
];
|
||||||
|
this.showEssentialBarChart = true;
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
console.log('Retrieval Error');
|
console.log('Retrieval Error');
|
||||||
|
@ -278,17 +243,23 @@ export class DashboardComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setChartDataEssential (dataEs: any) {
|
private setChartDataCat(dataCat: any) {
|
||||||
this.purchaseEssential = dataEs.purchase_no_essential_total;
|
this.barChartLabelsCategoryAll = Object.keys(dataCat);
|
||||||
this.purchaseNotEssential = dataEs.purchase_no_total - this.purchaseEssential;
|
let barChartDataCategoryInitial = Object.keys(dataCat).map(key => dataCat[key]);
|
||||||
this.barChartDataEssential = [
|
this.barChartDataCategoryAll = [
|
||||||
{data: [this.purchaseEssential], label: 'Essential', stack: '1'},
|
{data: barChartDataCategoryInitial, label: 'Series A'},
|
||||||
{data: [this.purchaseNotEssential], label: 'Non-Essential', stack: '1'},
|
];
|
||||||
];
|
this.showCategoryBarChart = true;
|
||||||
this.showEssentialBarChart = true;
|
if (this.weekList1) {
|
||||||
console.log(this.barChartDataEssential);
|
let n = 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 setChartDataCat(dataCat: any) {
|
private setChartDataCat(dataCat: any) {
|
||||||
this.barChartLabelsCategory = Object.keys(dataCat);
|
this.barChartLabelsCategory = Object.keys(dataCat);
|
||||||
let barChartDataCategoryInitial = Object.keys(dataCat).map(key => dataCat[key]);
|
let barChartDataCategoryInitial = Object.keys(dataCat).map(key => dataCat[key]);
|
||||||
|
@ -296,6 +267,24 @@ export class DashboardComponent {
|
||||||
{data: barChartDataCategoryInitial, label: 'Series A'},
|
{data: barChartDataCategoryInitial, label: 'Series A'},
|
||||||
];
|
];
|
||||||
this.showCategoryBarChart = true;
|
this.showCategoryBarChart = true;
|
||||||
|
if (this.weekList1) {
|
||||||
|
let n = 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) {
|
||||||
|
this.barChartLabelsCategory = Object.keys(dataSec);
|
||||||
|
let lineChartDataSectorInitial = Object.keys(dataSec).map(key => dataSec[key]);
|
||||||
|
this.lineChartDataSector = [
|
||||||
|
{data: barChartDataCategoryInitial, label: 'Series A'},
|
||||||
|
];
|
||||||
|
this.showCategoryBarChart = true;
|
||||||
if (this.weekList1) {
|
if (this.weekList1) {
|
||||||
let doughnutChartDataCategoryInitial = this.weekList1.map(function(a) {return a.value;});
|
let doughnutChartDataCategoryInitial = this.weekList1.map(function(a) {return a.value;});
|
||||||
this.doughnutChartDataCategory = [
|
this.doughnutChartDataCategory = [
|
||||||
|
@ -307,10 +296,6 @@ export class DashboardComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setChartDataSector(dataSec: any) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private setDate () {
|
private setDate () {
|
||||||
this.myWeek1 = moment().startOf('isoWeek').format('YYYY-MM-DD');
|
this.myWeek1 = moment().startOf('isoWeek').format('YYYY-MM-DD');
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { ChartsModule } from 'ng2-charts';
|
||||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||||
import { NgxPaginationModule } from 'ngx-pagination';
|
import { NgxPaginationModule } from 'ngx-pagination';
|
||||||
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
||||||
import { AgmMarkerClustererModule } from '@agm/markerclusterer';
|
import { AgmJsMarkerClustererModule } from '@agm/js-marker-clusterer';
|
||||||
import { ModalModule } from 'ngx-bootstrap/modal';
|
import { ModalModule } from 'ngx-bootstrap/modal';
|
||||||
|
|
||||||
import { CurrencyPipe } from '@angular/common';
|
import { CurrencyPipe } from '@angular/common';
|
||||||
|
@ -18,8 +18,6 @@ import { FeedbackComponent } from './feedback.component';
|
||||||
import { TransactionLogComponent } from './transaction-log.component';
|
import { TransactionLogComponent } from './transaction-log.component';
|
||||||
import { CategoryMonthComponent } from './category-month.component';
|
import { CategoryMonthComponent } from './category-month.component';
|
||||||
import { PayrollLogComponent } from './payroll-log.component';
|
import { PayrollLogComponent } from './payroll-log.component';
|
||||||
import { SuppliersComponent } from './suppliers.component';
|
|
||||||
import { MoreStuffComponent } from './more-graphs-and-tables.component';
|
|
||||||
import { LeaderboardComponent } from './leaderboard.component';
|
import { LeaderboardComponent } from './leaderboard.component';
|
||||||
import { MapComponent } from './map.component';
|
import { MapComponent } from './map.component';
|
||||||
import { TrailMapComponent } from './trail-map.component';
|
import { TrailMapComponent } from './trail-map.component';
|
||||||
|
@ -28,7 +26,6 @@ import { GraphWidget } from '../widgets/graph-widget.component';
|
||||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||||
import { GraphPanel } from '../panels/graph-panel.component';
|
import { GraphPanel } from '../panels/graph-panel.component';
|
||||||
import { BubbleChartComponent } from '../panels/bubble-panel.component';
|
|
||||||
import { PiePanel } from '../panels/pie-panel.component';
|
import { PiePanel } from '../panels/pie-panel.component';
|
||||||
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
import { OrgPiePanel } from '../panels/org-pie-panel.component';
|
||||||
|
|
||||||
|
@ -38,9 +35,6 @@ import { OrgTableComponent } from '../shared/org-table.component';
|
||||||
import { RecurResultComponent } from '../shared/recur-result.component';
|
import { RecurResultComponent } from '../shared/recur-result.component';
|
||||||
import { RecurTableComponent } from '../shared/recur-table.component';
|
import { RecurTableComponent } from '../shared/recur-table.component';
|
||||||
import { TransactionResultComponent } from '../shared/transaction-result.component';
|
import { TransactionResultComponent } from '../shared/transaction-result.component';
|
||||||
import { SupplierResultComponent } from '../shared/supplier-result.component';
|
|
||||||
import { WardResultComponent } from '../shared/ward-result.component';
|
|
||||||
import { MetaTypeResultComponent } from '../shared/meta-type-result.component';
|
|
||||||
import { PayrollResultComponent } from '../shared/payroll-result.component';
|
import { PayrollResultComponent } from '../shared/payroll-result.component';
|
||||||
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
||||||
|
|
||||||
|
@ -57,7 +51,7 @@ import { environment } from '../../environments/environment';
|
||||||
AgmCoreModule.forRoot({
|
AgmCoreModule.forRoot({
|
||||||
apiKey: environment.mapApiKey
|
apiKey: environment.mapApiKey
|
||||||
}),
|
}),
|
||||||
AgmMarkerClustererModule,
|
AgmJsMarkerClustererModule,
|
||||||
BsDropdownModule,
|
BsDropdownModule,
|
||||||
NgxPaginationModule,
|
NgxPaginationModule,
|
||||||
DashboardRoutingModule,
|
DashboardRoutingModule,
|
||||||
|
@ -75,9 +69,6 @@ import { environment } from '../../environments/environment';
|
||||||
TransactionLogComponent,
|
TransactionLogComponent,
|
||||||
CategoryMonthComponent,
|
CategoryMonthComponent,
|
||||||
TransactionResultComponent,
|
TransactionResultComponent,
|
||||||
SupplierResultComponent,
|
|
||||||
WardResultComponent,
|
|
||||||
MetaTypeResultComponent,
|
|
||||||
PayrollLogComponent,
|
PayrollLogComponent,
|
||||||
PayrollResultComponent,
|
PayrollResultComponent,
|
||||||
LeaderboardComponent,
|
LeaderboardComponent,
|
||||||
|
@ -91,9 +82,6 @@ import { environment } from '../../environments/environment';
|
||||||
GraphPanel,
|
GraphPanel,
|
||||||
PiePanel,
|
PiePanel,
|
||||||
OrgPiePanel,
|
OrgPiePanel,
|
||||||
BubbleChartComponent,
|
|
||||||
SuppliersComponent,
|
|
||||||
MoreStuffComponent,
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CurrencyPipe,
|
CurrencyPipe,
|
||||||
|
|
|
@ -95,7 +95,7 @@ const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'more-graphs-and-tables',
|
path: 'more-graphs-and-tables',
|
||||||
component: MoreStuffComponent,
|
component: MoreStuffComponent,
|
||||||
data: { title: 'Infographics'}
|
data: { title: 'More Stuff'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class LeaderboardComponent implements OnInit {
|
||||||
|
|
||||||
public paginateConfig: PaginationInstance = {
|
public paginateConfig: PaginationInstance = {
|
||||||
id: 'leadpaginate',
|
id: 'leadpaginate',
|
||||||
itemsPerPage: 20,
|
itemsPerPage: 10,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
totalItems: 0
|
totalItems: 0
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ export class LeaderboardComponent implements OnInit {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}org
|
}
|
||||||
|
|
||||||
// // dynamically changes the row style based on player's position
|
// // dynamically changes the row style based on player's position
|
||||||
// // for instance, top three player and the player him/herself should
|
// // for instance, top three player and the player him/herself should
|
||||||
|
|
|
@ -39,8 +39,9 @@
|
||||||
[latitude]="lat"
|
[latitude]="lat"
|
||||||
[longitude]="lng"
|
[longitude]="lng"
|
||||||
[zoom]="zoom"
|
[zoom]="zoom"
|
||||||
|
[scaleControl]="true"
|
||||||
(idle)="viewBoundsChanged()">
|
(idle)="viewBoundsChanged()">
|
||||||
<agm-marker-cluster maxZoom="13">
|
<agm-marker-cluster maxZoom="13" imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
|
||||||
<agm-marker
|
<agm-marker
|
||||||
*ngFor="let m of markers"
|
*ngFor="let m of markers"
|
||||||
[latitude]="m.latitude"
|
[latitude]="m.latitude"
|
||||||
|
|
|
@ -1,136 +1,28 @@
|
||||||
|
<script src="node_modules/chart.js/src/chart.js"></script>
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<div class="row">
|
<!-- <div class="form-group row"> -->
|
||||||
<div class="col-lg-12">
|
<div class="card">
|
||||||
<div class="card">
|
<div class="card-block">
|
||||||
<div class="card-header">
|
<div class="row">
|
||||||
<h4>Filter</h4>
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">Spend by Company Type</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: block">
|
||||||
|
<canvas baseChart
|
||||||
|
[datasets]="bubbleChartDataCategory"
|
||||||
|
[options]="bubbleChartOptionsCategory"
|
||||||
|
[colors]="sampleBubbleChartColors"
|
||||||
|
[labels]="bubbleChartLabelsCategory"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)">
|
||||||
|
|
||||||
|
<!--bootstrapColours-->
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</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>
|
<!-- </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>
|
</div>
|
||||||
|
|
|
@ -1,335 +1,140 @@
|
||||||
import {Component, OnInit, Input, Output, EventEmitter, ViewChild} from '@angular/core';
|
import { Component, OnInit, AfterViewInit, Input, Output, EventEmitter, ViewChild, TemplateRef } from '@angular/core';
|
||||||
import {ApiService} from '../providers/api-service';
|
import { ApiService } from '../providers/api-service';
|
||||||
import {BaseChartDirective} from 'ng2-charts';
|
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
|
||||||
import {CurrencyPipe} from '@angular/common';
|
import { Color } from 'ng2-charts';
|
||||||
import {ChartType} from "chart.js";
|
import { CurrencyPipe } from '@angular/common';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
import { BubbleChartComponent } from '../panels/bubble-panel';
|
||||||
|
import { AgmCoreModule } from '@agm/core';
|
||||||
|
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
|
||||||
|
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||||
|
|
||||||
|
// interface RecurSupplierData {
|
||||||
|
// name : string;
|
||||||
|
// }
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: 'more-graphs-and-tables.component.html',
|
templateUrl: 'more-graphs-and-tables.component.html',
|
||||||
})
|
})
|
||||||
export class MoreStuffComponent implements OnInit {
|
export class MoreStuffComponent implements OnInit {
|
||||||
|
// @Input() public recurList: Array<RecurSupplierData>;
|
||||||
@Output() public onClick = new EventEmitter();
|
@Output() public onClick = new EventEmitter();
|
||||||
@Input() public categories: any;
|
@Input() public categories: any;
|
||||||
|
|
||||||
// Global Filter Setup
|
public recurClick(event: any): void {
|
||||||
filterFrom: any;
|
this.onClick.emit( event );
|
||||||
filterTo: any;
|
}
|
||||||
|
|
||||||
isBubbleChartLoaded: boolean = false;
|
|
||||||
isSupplierChartLoaded: boolean = false;
|
|
||||||
wardList: any;
|
|
||||||
wardListAvailable = false;
|
|
||||||
metaTypeList: any;
|
|
||||||
metaTypeListAvailable = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
private currencyPipe: CurrencyPipe,
|
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 {
|
ngOnInit(): void {
|
||||||
this.loadData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadData() {
|
// main vars
|
||||||
this.tableSummary();
|
|
||||||
this.loadYearSpend();
|
|
||||||
this.loadSupplierBubble();
|
|
||||||
this.loadSupplierHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
public showLegend = true;
|
public bootstrapColours: string[] = ['bg-primary', 'bg-secondary', 'bg-success',
|
||||||
|
'bg-danger', 'bg-warning', 'bg-info'];
|
||||||
|
|
||||||
/*
|
// REAL chart data
|
||||||
* Supplier Bubble Chart Setup
|
|
||||||
*/
|
|
||||||
|
|
||||||
private formatGraphData(data: any): any[] {
|
public chartType = 'bubble';
|
||||||
let graph_data = [];
|
public chartLegend = true;
|
||||||
|
public bubbleChartDataCategory: any[] = [
|
||||||
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: [],
|
data: [
|
||||||
label: ["Spend"],
|
{ x: 10, y: 10, r: 10 },
|
||||||
borderColor: 'blue',
|
{ x: 15, y: 5, r: 15 },
|
||||||
hoverBorderColor: 'black',
|
{ x: 26, y: 12, r: 23 },
|
||||||
radius: 5,
|
{ x: 7, y: 8, r: 8 },
|
||||||
},
|
],
|
||||||
|
label: ["Series A"],
|
||||||
|
backgroundColor: 'green',
|
||||||
|
borderColor: 'blue',
|
||||||
|
hoverBackgroundColor: 'purple',
|
||||||
|
hoverBorderColor: 'red',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: [
|
||||||
|
{ x: 10, y: 2, r: 10 },
|
||||||
|
{ x: 15, y: 1, r: 15 },
|
||||||
|
{ x: 26, y: 7, r: 23 },
|
||||||
|
{ x: 5, y: 8, r: 8 },
|
||||||
|
],
|
||||||
|
label: ["Series B"],
|
||||||
|
backgroundColor: 'green',
|
||||||
|
borderColor: 'blue',
|
||||||
|
hoverBackgroundColor: 'purple',
|
||||||
|
hoverBorderColor: 'red',
|
||||||
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
public supplierBubbleChartLabels: string[] = [];
|
public bubbleChartLabelsCategory: string[] = [];
|
||||||
public supplierBubbleChartOptions: any = {
|
|
||||||
|
public bubbleChartOptionsCategory:any = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [
|
||||||
type: 'time',
|
{
|
||||||
time: {
|
ticks: {
|
||||||
unit: 'month'
|
min: 0,
|
||||||
},
|
}
|
||||||
scaleLabel: {
|
}
|
||||||
display: true,
|
],
|
||||||
labelString: 'Date'
|
yAxes: [
|
||||||
}
|
{
|
||||||
}],
|
ticks: {
|
||||||
yAxes: [{
|
min: 0,
|
||||||
scaleLabel: {
|
}
|
||||||
display: true,
|
}
|
||||||
labelString: 'Number of purchases'
|
]
|
||||||
}
|
},
|
||||||
}]
|
|
||||||
},
|
|
||||||
tooltips: {
|
tooltips: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: (tooltip, data) => {
|
label: (tooltip, data) => {
|
||||||
return this.bubbleTooltipCallback(tooltip, data);
|
return this.tooltipLabelCallback(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() {
|
private setChartData(dataCat: any) {
|
||||||
this.api.loadMiscUrl('organisation/external/lcc_tables', {
|
// now we just need some data and it will display!
|
||||||
from: this.filterFrom,
|
}
|
||||||
to: this.filterTo,
|
public chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
}).subscribe(
|
console.log(event, active);
|
||||||
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() {
|
public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
this.api.loadMiscUrl('organisation/external/year_spend', {
|
console.log(event, active);
|
||||||
from: this.filterFrom,
|
}
|
||||||
to: this.filterTo,
|
// functions
|
||||||
}).subscribe(
|
|
||||||
result => {
|
|
||||||
let value_data = [];
|
|
||||||
let count_data = [];
|
|
||||||
|
|
||||||
result.data.map(item => {
|
private tooltipLabelCallback(tooltipItem: any, data: any) {
|
||||||
value_data.push({
|
var dataset = data.datasets[tooltipItem.datasetIndex];
|
||||||
t: item.date,
|
var value = dataset.data[tooltipItem.index];
|
||||||
y: item.value,
|
return this.currencyPipe.transform(value, 'GBP', 'symbol', '1.2-2');
|
||||||
});
|
|
||||||
|
|
||||||
count_data.push({
|
|
||||||
t: item.date,
|
|
||||||
y: item.count,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.yearSpendChartData[0].data = value_data;
|
|
||||||
this.yearSpendChartData[1].data = count_data;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public yearSpendChartData: any[] = [
|
// SAMPLE chart data
|
||||||
|
|
||||||
|
public sampleBubbleChartColors: Color[] = [
|
||||||
{
|
{
|
||||||
data: [],
|
backgroundColor: [
|
||||||
label: ["Value £"],
|
'red',
|
||||||
fill: false,
|
'green',
|
||||||
borderColor: 'red',
|
'blue',
|
||||||
hoverBackgroundColor: '#ffa1b5',
|
'purple',
|
||||||
hoverBorderColor: 'red',
|
'yellow',
|
||||||
yAxisID: 'y-value',
|
'brown',
|
||||||
},
|
'magenta',
|
||||||
{
|
'cyan',
|
||||||
data: [],
|
'orange',
|
||||||
label: ["Count"],
|
'pink'
|
||||||
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 }) supplierChart: BaseChartDirective;
|
|
||||||
|
|
||||||
private loadSupplierHistory() {
|
|
||||||
this.api.loadMiscUrl('organisation/external/supplier_history').subscribe(
|
|
||||||
result => {
|
|
||||||
this._supplierHistoryData = result.data;
|
|
||||||
this._supplierHistoryPage = 1;
|
|
||||||
this._supplierHistoryPages = Math.ceil(this._supplierHistoryData.length / this._supplierHistoryPerPage);
|
|
||||||
this.updateSupplierHistoryData();
|
|
||||||
|
|
||||||
this.isSupplierChartLoaded = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateSupplierHistoryData() {
|
|
||||||
|
|
||||||
const lastResult = this._supplierHistoryPerPage * this._supplierHistoryPage;
|
|
||||||
console.log(this._supplierHistoryPage);
|
|
||||||
const firstResult = lastResult - this._supplierHistoryPerPage;
|
|
||||||
|
|
||||||
const pageData = this._supplierHistoryData.slice(firstResult, lastResult);
|
|
||||||
console.log(pageData);
|
|
||||||
|
|
||||||
let labels = [];
|
|
||||||
let year = [];
|
|
||||||
let half = [];
|
|
||||||
let quarter = [];
|
|
||||||
pageData.map(item => {
|
|
||||||
labels.push(item.name);
|
|
||||||
year.push(item.year_total);
|
|
||||||
half.push(item.half_total);
|
|
||||||
quarter.push(item.quarter_total);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.supplierMonthChartData[0].data = quarter;
|
|
||||||
this.supplierMonthChartData[1].data = half;
|
|
||||||
this.supplierMonthChartData[2].data = year;
|
|
||||||
this.supplierMonthChartLabels = labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public nextSupplierHistoryPage() {
|
|
||||||
if (this._supplierHistoryPage < this._supplierHistoryPages) {
|
|
||||||
this._supplierHistoryPage++;
|
|
||||||
}
|
}
|
||||||
this.updateSupplierHistoryData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public previousSupplierHistoryPage() {
|
|
||||||
if (this._supplierHistoryPage > 1) {
|
|
||||||
this._supplierHistoryPage--;
|
|
||||||
}
|
|
||||||
this.updateSupplierHistoryData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _supplierHistoryData: any[];
|
|
||||||
private _supplierHistoryPerPage: number = 15;
|
|
||||||
public _supplierHistoryPage: number = 1;
|
|
||||||
public _supplierHistoryPages: number = 1;
|
|
||||||
public supplierMonthChartData: any[] = [
|
|
||||||
{
|
|
||||||
data: [],
|
|
||||||
label: ["3 Month"],
|
|
||||||
fill: false,
|
|
||||||
borderColor: 'red',
|
|
||||||
hoverBorderColor: 'red',
|
|
||||||
hoverBackgroundColor: 'red',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: [],
|
|
||||||
label: ["6 Month"],
|
|
||||||
fill: false,
|
|
||||||
borderColor: 'blue',
|
|
||||||
hoverBorderColor: 'blue',
|
|
||||||
hoverBackgroundColor: 'blue',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: [],
|
|
||||||
label: ["12 Month"],
|
|
||||||
fill: false,
|
|
||||||
borderColor: 'orange',
|
|
||||||
hoverBorderColor: 'orange',
|
|
||||||
hoverBackgroundColor: 'orange',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
public supplierMonthChartOptions: any = {
|
|
||||||
//maintainAspectRatio: false,
|
|
||||||
responsive: true,
|
|
||||||
scales: {
|
|
||||||
xAxes: [{
|
|
||||||
scaleLabel: {
|
|
||||||
display: true,
|
|
||||||
labelString: 'Spend amount £'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
yAxes: [{
|
|
||||||
scaleLabel: {
|
|
||||||
display: true,
|
|
||||||
labelString: 'Supplier Names'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
public supplierMonthChartLabels: string[] = [];
|
|
||||||
public supplierMonthChartType: ChartType = 'horizontalBar';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +1,39 @@
|
||||||
|
<script type="text/javascript" charset="utf8" src=""></script>
|
||||||
<div class="animated fadeIn">
|
<div class="animated fadeIn">
|
||||||
<div class="row">
|
<div class="card">
|
||||||
<div class="col-lg-12">
|
<div class="card-header">
|
||||||
<div class="card">
|
<strong>List of Suppliers</strong>
|
||||||
<div class="card-header">
|
<small>This lists all suppliers, their postcode and spend.</small>
|
||||||
<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="card-block">
|
||||||
</div>
|
<table class="table table-striped table-hover">
|
||||||
<div class="animated fadeIn">
|
<thead>
|
||||||
<div class="row">
|
<tr>
|
||||||
<div class="col-lg-12">
|
<th>Name</th>
|
||||||
<div class="card">
|
<th>Postcode</th>
|
||||||
<div class="card-header">
|
<th>Spend</th>
|
||||||
<h4>List of Suppliers</h4>
|
</tr>
|
||||||
<div class="small">Click on Column Headers to change Sort Order</div>
|
</thead>
|
||||||
</div>
|
<tbody>
|
||||||
<div *ngIf="supplierListAvailable" class="card-block">
|
<!-- table body - name, postcode and spend data should be presented here in cost descending order -->
|
||||||
<table class="table table-striped table-hover">
|
<tr recur-result *ngFor="let recur of recurList" tr.names="name" tr.recur="recur" (onClick)="recurClick($event, template)"></tr>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td>Tom's Tippity Top Toenails Ltd.</td>
|
||||||
<th (click)="sortName()">Name <span class="fa-stack">
|
<td>LA11LY</td>
|
||||||
<i *ngIf="sortBy !== 'name' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
<td>£250,000.00</td>
|
||||||
<i *ngIf="sortBy !== 'name' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
</tr>
|
||||||
</span></th>
|
<tr>
|
||||||
<th (click)="sortPostcode()">Postcode <span class="fa-stack">
|
<td>Selena's Scratching Sticks Inc.</td>
|
||||||
<i *ngIf="sortBy !== 'postcode' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
<td>WS15PQ</td>
|
||||||
<i *ngIf="sortBy !== 'postcode' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
<td>£5.00</td>
|
||||||
</span></th>
|
</tr>
|
||||||
<th (click)="sortSpend()">Spend <span class="fa-stack">
|
<tr>
|
||||||
<i *ngIf="sortBy !== 'spend' || sortDir == 'asc'" class="fa fa-sort-up fa-stack-1x"></i>
|
<td>Big Barry and Son's Balloon Store and Clown Outfits Corp.</td>
|
||||||
<i *ngIf="sortBy !== 'spend' || sortDir == 'desc'" class="fa fa-sort-down fa-stack-1x"></i>
|
<td>PF43RD</td>
|
||||||
</span></th>
|
<td>£22.00</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</tbody>
|
||||||
<tbody>
|
</table>
|
||||||
<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>
|
</div><!--/.col-->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,69 +3,30 @@ import { ApiService } from '../providers/api-service';
|
||||||
import { AgmCoreModule } from '@agm/core';
|
import { AgmCoreModule } from '@agm/core';
|
||||||
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
|
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
|
||||||
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||||
import { PaginationInstance } from 'ngx-pagination';
|
|
||||||
import { FilterPipeModule } from 'ngx-filter-pipe';
|
interface RecurSupplierData {
|
||||||
|
name : string;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: 'suppliers.component.html',
|
templateUrl: 'suppliers.component.html',
|
||||||
})
|
})
|
||||||
export class SuppliersComponent implements OnInit, AfterViewInit {
|
export class SuppliersComponent implements OnInit, AfterViewInit {
|
||||||
|
@Input() public recurList: Array<RecurSupplierData>;
|
||||||
@Output() public onClick = new EventEmitter();
|
@Output() public onClick = new EventEmitter();
|
||||||
@Input() public categories: any;
|
@Input() public categories: any;
|
||||||
public perPage: number = 10;
|
|
||||||
|
|
||||||
searchText: string;
|
|
||||||
|
|
||||||
supplierList: any;
|
public recurClick(event: any): void {
|
||||||
supplierListAvailable = false;
|
this.onClick.emit( event );
|
||||||
sortBy = 'name';
|
}
|
||||||
sortDir = 'asc';
|
|
||||||
|
|
||||||
public paginateConfig: PaginationInstance = {
|
|
||||||
id: 'transpaginate',
|
|
||||||
itemsPerPage: this.perPage,
|
|
||||||
currentPage: 1,
|
|
||||||
totalItems: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
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() {
|
ngAfterViewInit() {
|
||||||
|
|
|
@ -72,8 +72,9 @@
|
||||||
[latitude]="lat"
|
[latitude]="lat"
|
||||||
[longitude]="lng"
|
[longitude]="lng"
|
||||||
[zoom]="zoom"
|
[zoom]="zoom"
|
||||||
|
[scaleControl]="true"
|
||||||
(idle)="viewBoundsChanged()">
|
(idle)="viewBoundsChanged()">
|
||||||
<agm-marker-cluster maxZoom="13">
|
<agm-marker-cluster maxZoom="13" imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
|
||||||
<agm-marker
|
<agm-marker
|
||||||
*ngFor="let m of markers"
|
*ngFor="let m of markers"
|
||||||
[iconUrl]="'/assets/img/association/' + assocMap + '-map-pin.png'"
|
[iconUrl]="'/assets/img/association/' + assocMap + '-map-pin.png'"
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer d-flex justify-content-between">
|
<div class="modal-footer d-flex justify-content-between">
|
||||||
<button type="submit" (click)="deleteRecurringTransaction()" class="btn btn-sm btn-danger"><i class="fa fa-times"></i> Delete</button>
|
<button type="submit" (click)="deleteRecurringTransaction()" class="btn btn-sm btn-danger"><i class="fa fa-times"></i> Delete</button>
|
||||||
<button type="submit" (click)="editRecurringTransaction()" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Save</button>
|
<button type="submit" (click)="editRecurringTransaction()" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Edit</button>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,24 +101,18 @@
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<strong>Log of Outgoing Transactions</strong>
|
<strong>Log of Outgoing Transactions</strong>
|
||||||
<small>This lists all purchases that have been submitted.</small>
|
<small>This lists all purchases that have been submitted.</small>
|
||||||
<button *ngIf="accountType == 'organisation'" class="btn pull-right btn-sm" (click)="toggleShowMeta()">
|
|
||||||
<span *ngIf="!showMeta">Show</span><span *ngIf="showMeta">Hide</span> Details
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!noTransactionList" class="card-block">
|
<div *ngIf="!noTransactionList" class="card-block">
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Seller</th>
|
<th>Seller</th>
|
||||||
<th *ngIf="!showMeta">Value</th>
|
<th>Value</th>
|
||||||
<th *ngIf="showMeta">Net Value</th>
|
|
||||||
<th *ngIf="showMeta">Sales Tax Value</th>
|
|
||||||
<th *ngIf="showMeta">Gross Value</th>
|
|
||||||
<th>Purchase Time</th>
|
<th>Purchase Time</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr transaction-result *ngFor="let transaction of transactionList | paginate: paginateConfig" [transaction]="transaction" [showMeta]="showMeta"></tr>
|
<tr transaction-result *ngFor="let transaction of transactionList | paginate: paginateConfig" [transaction]="transaction"></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<pagination-template #p="paginationApi"
|
<pagination-template #p="paginationApi"
|
||||||
|
|
|
@ -29,15 +29,13 @@ export class TransactionLogComponent implements OnInit {
|
||||||
transactionFormStatusSuccess: string;
|
transactionFormStatusSuccess: string;
|
||||||
transactionFormStatusError = 'Error received, please try again.';
|
transactionFormStatusError = 'Error received, please try again.';
|
||||||
updatedTime: string;
|
updatedTime: string;
|
||||||
accountType: any;
|
|
||||||
showMeta = false;
|
|
||||||
|
|
||||||
public paginateConfig: PaginationInstance = {
|
public paginateConfig: PaginationInstance = {
|
||||||
id: 'transpaginate',
|
id: 'transpaginate',
|
||||||
itemsPerPage: 10,
|
itemsPerPage: 10,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
totalItems: 0
|
totalItems: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
|
@ -59,7 +57,6 @@ export class TransactionLogComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadTransactions(1);
|
this.loadTransactions(1);
|
||||||
this.accountType = localStorage.getItem('usertype');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTransactions(logPage: number) {
|
loadTransactions(logPage: number) {
|
||||||
|
@ -165,7 +162,4 @@ export class TransactionLogComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleShowMeta() {
|
|
||||||
this.showMeta = !this.showMeta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,6 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/more-graphs-and-tables']">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col-2"><i class="icon-map"></i></div>
|
|
||||||
<div class="col-10">Infographics</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/add-data']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
|
@ -94,7 +86,7 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="accountType == 'customer'" class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/category-month']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/category-month']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
<div class="col-2"><i class="icon-basket"></i></div>
|
<div class="col-2"><i class="icon-basket"></i></div>
|
||||||
|
@ -102,7 +94,7 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/suppliers']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/suppliers']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
<div class="col-2"><i class="icon-speedometer"></i></div>
|
<div class="col-2"><i class="icon-speedometer"></i></div>
|
||||||
|
@ -110,6 +102,14 @@
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/more-graphs-and-tables']">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col-2"><i class="icon-map"></i></div>
|
||||||
|
<div class="col-10">Bubble Charts</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
||||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/payroll-log']">
|
<a class="nav-link" routerLinkActive="active" [routerLink]="['/payroll-log']">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="row no-gutters align-items-center">
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { Color } from 'ng2-charts';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bubble-chart',
|
selector: 'app-bubble-chart',
|
||||||
templateUrl: './bubble-panel.component.html',
|
templateUrl: './bubble-chart.component.html',
|
||||||
|
styleUrls: ['./bubble-chart.component.scss']
|
||||||
})
|
})
|
||||||
export class BubbleChartComponent implements OnInit {
|
export class BubbleChartComponent implements OnInit {
|
||||||
public bubbleChartOptions: ChartOptions = {
|
public bubbleChartOptions: ChartOptions = {
|
||||||
|
@ -94,4 +95,4 @@ export class BubbleChartComponent implements OnInit {
|
||||||
const data = Array.apply(null, { length: numberOfPoints }).map(r => this.randomPoint(30));
|
const data = Array.apply(null, { length: numberOfPoints }).map(r => this.randomPoint(30));
|
||||||
this.bubbleChartData[0].data = data;
|
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,9 +1,18 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-5">
|
||||||
<h4 class="card-title mb-0">Customers</h4>
|
<h4 class="card-title mb-0">Customers</h4>
|
||||||
</div><!--/.col-->
|
</div><!--/.col-->
|
||||||
|
<div class="col-sm-7 hidden-sm-down">
|
||||||
|
<div class="btn-toolbar float-right" role="toolbar" aria-label="Toolbar with button groups">
|
||||||
|
<div class="btn-group mr-3" data-toggle="buttons" aria-label="First group">
|
||||||
|
<label class="btn btn-outline-secondary active">
|
||||||
|
<input type="radio" name="options" id="option2" checked> Week
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!--/.col-->
|
||||||
</div><!--/.row-->
|
</div><!--/.row-->
|
||||||
<div class="chart-wrapper" style="height:300px;margin-top:40px;">
|
<div class="chart-wrapper" style="height:300px;margin-top:40px;">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
|
|
|
@ -82,12 +82,12 @@ export class GraphPanel implements OnInit {
|
||||||
pointHoverBackgroundColor: '#fff'
|
pointHoverBackgroundColor: '#fff'
|
||||||
},
|
},
|
||||||
{ // brandSuccess
|
{ // brandSuccess
|
||||||
backgroundColor: this.convertHex(this.brandInfo, 10),
|
backgroundColor: 'transparent',
|
||||||
borderColor: this.brandSuccess,
|
borderColor: this.brandSuccess,
|
||||||
pointHoverBackgroundColor: '#fff'
|
pointHoverBackgroundColor: '#fff'
|
||||||
},
|
},
|
||||||
{ // brandDanger
|
{ // brandDanger
|
||||||
backgroundColor: this.convertHex(this.brandDanger, 10),
|
backgroundColor: 'transparent',
|
||||||
borderColor: this.brandDanger,
|
borderColor: this.brandDanger,
|
||||||
pointHoverBackgroundColor: '#fff',
|
pointHoverBackgroundColor: '#fff',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title mb-0">Global Purchases by Type</h4>
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
[data]="doughnutChartDataLocal"
|
[data]="doughnutChartDataLocal"
|
||||||
[labels]="doughnutChartLabelsLocal"
|
[labels]="doughnutChartLabelsLocal"
|
||||||
[colors]="doughnutChartColors"
|
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
[chartType]="chartType"
|
[chartType]="chartType"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
|
|
|
@ -12,43 +12,9 @@ import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
|
||||||
export class OrgPiePanel implements OnInit {
|
export class OrgPiePanel implements OnInit {
|
||||||
|
|
||||||
public chartType = 'pie';
|
public chartType = 'doughnut';
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataLocal: number[] = [];
|
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[] = [];
|
public doughnutChartLabelsLocal: string[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h4 class="card-title mb-0">All Purchases by Category</h4>
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<canvas baseChart class="chart"
|
<canvas baseChart class="chart"
|
||||||
[data]="doughnutChartDataLocal"
|
[data]="doughnutChartDataLocal"
|
||||||
[labels]="doughnutChartLabelsLocal"
|
[labels]="doughnutChartLabelsLocal"
|
||||||
[colors]="doughnutChartColors"
|
|
||||||
[legend]="chartLegend"
|
[legend]="chartLegend"
|
||||||
[chartType]="chartType"
|
[chartType]="chartType"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
|
|
|
@ -12,41 +12,10 @@ import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
|
||||||
export class PiePanel implements OnInit {
|
export class PiePanel implements OnInit {
|
||||||
|
|
||||||
public chartType = 'pie';
|
public chartType = 'doughnut';
|
||||||
public chartLegend = true;
|
public chartLegend = true;
|
||||||
public doughnutChartDataLocal: number[] = [];
|
public doughnutChartDataLocal: number[] = [];
|
||||||
public doughnutChartLabelsLocal: string[] = [];
|
public doughnutChartLabelsLocal: string[] = [];
|
||||||
public doughnutChartColors: any[] = [
|
|
||||||
{ backgroundColor: [
|
|
||||||
'#ffa1b5',
|
|
||||||
'#3cde52',
|
|
||||||
'#52afed',
|
|
||||||
'#c133e3',
|
|
||||||
'#f7fa08',
|
|
||||||
'#75152d',
|
|
||||||
'#ee12ee',
|
|
||||||
'#15eaea',
|
|
||||||
'#eaa015',
|
|
||||||
'#ea1515',
|
|
||||||
'#2d4fcc'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ borderColor:[
|
|
||||||
'red',
|
|
||||||
'green',
|
|
||||||
'blue',
|
|
||||||
'purple',
|
|
||||||
'yellow',
|
|
||||||
'brown',
|
|
||||||
'magenta',
|
|
||||||
'cyan',
|
|
||||||
'orange',
|
|
||||||
'pink'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ borderWidth: [10]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
|
|
19
src/app/panels/polar-panel.component.html
Normal file
19
src/app/panels/polar-panel.component.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
[data]="doughnutChartDataLocal"
|
||||||
|
[labels]="doughnutChartLabelsLocal"
|
||||||
|
[legend]="chartLegend"
|
||||||
|
[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
72
src/app/panels/polar-panel.component.ts
Normal file
72
src/app/panels/polar-panel.component.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { SingleDataSet, Label } from 'ng2-charts';
|
||||||
|
import { ChartType } from 'chart.js';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
|
import { CustPiesService } from '../providers/cust-pies.service';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'polar-area',
|
||||||
|
templateUrl: 'polar-panel.component.html',
|
||||||
|
})
|
||||||
|
|
||||||
|
export class PolarAreaChartComponent implements OnInit {
|
||||||
|
// PolarArea
|
||||||
|
|
||||||
|
public chartType : 'polar-area';
|
||||||
|
public polarAreaChartLabels: Label[];
|
||||||
|
public polarAreaChartData: SingleDataSet;
|
||||||
|
public chartLegend : Boolean;
|
||||||
|
public polarAreaLegend : Boolean;
|
||||||
|
|
||||||
|
public polarChartLabelsLocal: string[] = [];
|
||||||
|
public polarChartDataLocal: number[] = [];
|
||||||
|
|
||||||
|
public polarAreaChartType: ChartType = 'polarArea';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private pieService: CustPiesService,
|
||||||
|
) {
|
||||||
|
this.pieService.getPie().subscribe(
|
||||||
|
result => {
|
||||||
|
this.setChartData(result.local_all);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('Retrieval Error');
|
||||||
|
console.log( error._body );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.polarAreaLegend = this.chartLegend;
|
||||||
|
this.polarAreaLegend = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private setChartData(dataLocal: any) {
|
||||||
|
this.polarChartDataLocal = Object.keys(dataLocal).map(key => dataLocal[key]);
|
||||||
|
// setTimeout is currently a workaround for ng2-charts labels
|
||||||
|
setTimeout(() => this.polarChartLabelsLocal = Object.keys(dataLocal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public convertHex(hex: string, opacity: number) {
|
||||||
|
hex = hex.replace('#', '');
|
||||||
|
const r = parseInt(hex.substring(0, 2), 16);
|
||||||
|
const g = parseInt(hex.substring(2, 4), 16);
|
||||||
|
const b = parseInt(hex.substring(4, 6), 16);
|
||||||
|
|
||||||
|
const rgba = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + opacity / 100 + ')';
|
||||||
|
return rgba;
|
||||||
|
}
|
||||||
|
|
||||||
|
// events
|
||||||
|
public chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
|
||||||
|
console.log(event, active);
|
||||||
|
}
|
||||||
|
}
|
19
src/app/panels/stacked-bar.component.html.broken
Normal file
19
src/app/panels/stacked-bar.component.html.broken
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-block">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4 class="card-title mb-0">All Purchases</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas baseChart class="chart"
|
||||||
|
attr.[data]="doughnutChartDataLocal"
|
||||||
|
attr.[labels]="doughnutChartLabelsLocal"
|
||||||
|
attr.[legend]="chartLegend"
|
||||||
|
attr.[chartType]="chartType"
|
||||||
|
(chartHover)="chartHovered($event)"
|
||||||
|
(chartClick)="chartClicked($event)"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
68
src/app/panels/stacked-bar.component.ts.broken
Normal file
68
src/app/panels/stacked-bar.component.ts.broken
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { NgModule, enableProdMode } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { ApiService } from '../providers/api-service';
|
||||||
|
import { CustPiesService } from '../providers/cust-pies.service';
|
||||||
|
import { DataType } from '../shared/data-types.enum';
|
||||||
|
import { ChartData } from '../_interfaces/chart-data';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { DxChartModule } from 'devextreme-angular';
|
||||||
|
|
||||||
|
if(!/localhost/.test(document.location.host)) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'stacked-bar',
|
||||||
|
templateUrl: 'stacked-bar.component.html',
|
||||||
|
})
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
DxChartModule
|
||||||
|
],
|
||||||
|
declarations: [StackedBarChartComponent],
|
||||||
|
bootstrap: [StackedBarChartComponent]
|
||||||
|
})
|
||||||
|
export class StackedBarChartComponent {
|
||||||
|
|
||||||
|
public chartType: 'stacked-bar';
|
||||||
|
public chartLegend = true;
|
||||||
|
public stackedBarChartDataLocal : number[] = [];
|
||||||
|
public stackedBarChartLabelsLocal : string[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private api: ApiService,
|
||||||
|
private pieService: CustPiesService,
|
||||||
|
) {
|
||||||
|
this.pieService.getPie().subscribe(
|
||||||
|
result => {
|
||||||
|
this.setChartData(result.local_all);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('Retrieval Error');
|
||||||
|
console.log( error._body );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
console.log("stacked bar graph tried to initialise");
|
||||||
|
}
|
||||||
|
|
||||||
|
private setChartData(dataLocal: any) {
|
||||||
|
this.stackedBarChartDataLocal = Object.keys(dataLocal).map(key => dataLocal[key]);
|
||||||
|
// setTimeout is currently a workaround for ng2-charts labels
|
||||||
|
setTimeout(() => this.stackedBarChartLabelsLocal = Object.keys(dataLocal), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
customizeTooltip(arg: any) {
|
||||||
|
return {
|
||||||
|
text: arg.percentText + ' - ' + arg.valueText
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(StackedBarChartComponent);
|
|
@ -144,28 +144,12 @@ export class ApiService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadMiscUrl(extra_url, extraArgs = {}) {
|
public externalSuppliers() {
|
||||||
const key = this.sessionKey;
|
const key = this.sessionKey;
|
||||||
return this.http.post<any>(
|
return this.http.post<any>(
|
||||||
this.apiUrl + '/v1/' + extra_url,
|
this.apiUrl + '/organisation/external/suppliers',
|
||||||
{
|
{
|
||||||
session_key : key,
|
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,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<td>{{type.type}}</td>
|
|
||||||
<td>{{type.count}}</td>
|
|
||||||
<td>{{type.sum | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
|
@ -1,19 +0,0 @@
|
||||||
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 {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
<td>{{supplier.name}}</td>
|
|
||||||
<td>{{supplier.postcode}}</td>
|
|
||||||
<td>{{supplier.spend | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
|
@ -1,19 +0,0 @@
|
||||||
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,6 +1,3 @@
|
||||||
<td>{{transaction.seller}}</td>
|
<td>{{transaction.seller}}</td>
|
||||||
<td *ngIf="!showMeta">{{transaction.value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
<td>{{transaction.value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||||
<td *ngIf="showMeta">{{transaction.net_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
||||||
<td *ngIf="showMeta">{{transaction.sales_tax_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
||||||
<td *ngIf="showMeta">{{transaction.gross_value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
||||||
<td>{{transactionDate}}</td>
|
<td>{{transactionDate}}</td>
|
||||||
|
|
|
@ -14,7 +14,6 @@ interface TransactionData {
|
||||||
})
|
})
|
||||||
export class TransactionResultComponent implements OnInit {
|
export class TransactionResultComponent implements OnInit {
|
||||||
@Input() public transaction: TransactionData;
|
@Input() public transaction: TransactionData;
|
||||||
@Input() public showMeta: boolean;
|
|
||||||
public transactionDate: string;
|
public transactionDate: string;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<td>{{ward.ward}}</td>
|
|
||||||
<td>{{ward.count}}</td>
|
|
||||||
<td>{{ward.sum | currency:'GBP':'symbol':'1.2-2' }}</td>
|
|
|
@ -1,19 +0,0 @@
|
||||||
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 {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
apiUrl: 'https://dev.localspend.co.uk/api',
|
apiUrl: 'https://dev.peartrade.org/api',
|
||||||
mapApiKey: 'CHANGEME',
|
mapApiKey: 'CHANGEME',
|
||||||
enableAnalytics: false,
|
enableAnalytics: false,
|
||||||
analyticsKey: 'CHANGEME',
|
analyticsKey: 'CHANGEME',
|
||||||
|
|
Binary file not shown.
|
@ -48,7 +48,7 @@ $navbar-border: (
|
||||||
);
|
);
|
||||||
$navbar-brand-width: 155px;
|
$navbar-brand-width: 155px;
|
||||||
$navbar-brand-bg: #fff;
|
$navbar-brand-bg: #fff;
|
||||||
$navbar-brand-logo: url('../../assets/img/logo.png');
|
$navbar-brand-logo: url('../assets/img/logo.png');
|
||||||
$navbar-brand-logo-size: 70px auto;
|
$navbar-brand-logo-size: 70px auto;
|
||||||
$navbar-brand-border: (
|
$navbar-brand-border: (
|
||||||
bottom: (
|
bottom: (
|
||||||
|
|
|
@ -74,6 +74,7 @@ agm-map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.small {
|
.small {
|
||||||
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
&.legend {
|
&.legend {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -66,6 +66,7 @@ small,
|
||||||
.small {
|
.small {
|
||||||
font-size: $small-font-size;
|
font-size: $small-font-size;
|
||||||
font-weight: $font-weight-normal;
|
font-weight: $font-weight-normal;
|
||||||
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark,
|
mark,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// Some special margin utils
|
// Some special margin utils
|
||||||
.m#{$infix}-auto { margin: auto !important; }
|
.m#{$infix}-auto { margin: auto !important; }
|
||||||
.mt#{$infix}-auto { margin-top: auto !important; }
|
.mt#{$infix}-auto { margin-top: auto !important; }
|
||||||
.mr#{$infix}-auto { margin-right: auto !important; }
|
.mr#{$infix}-auto { margin-right: 20px !important; }
|
||||||
.mb#{$infix}-auto { margin-bottom: auto !important; }
|
.mb#{$infix}-auto { margin-bottom: auto !important; }
|
||||||
.ml#{$infix}-auto { margin-left: auto !important; }
|
.ml#{$infix}-auto { margin-left: auto !important; }
|
||||||
.mx#{$infix}-auto {
|
.mx#{$infix}-auto {
|
||||||
|
|
|
@ -76,4 +76,3 @@
|
||||||
|
|
||||||
// Custom styles
|
// Custom styles
|
||||||
@import "custom";
|
@import "custom";
|
||||||
@import "bootstrap/spinner";
|
|
Reference in a new issue