diff --git a/.angular-cli.json b/.angular-cli.json index 1290020..f7b4f9c 100644 --- a/.angular-cli.json +++ b/.angular-cli.json @@ -24,9 +24,10 @@ ], "environmentSource": "environments/environment.ts", "environments": { - "dev": "environments/environment.ts", + "dev": "environments/environment.dev.ts", "prod": "environments/environment.prod.ts", - "local": "environments/environment.local.ts" + "local": "environments/environment.local.ts", + "ci": "environments/environment.ci.ts" } } ], diff --git a/.gitignore b/.gitignore index f82ac9f..67d6c52 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,9 @@ testem.log # local env variable /src/environments/environment.local.ts +/src/environments/environment.prod.ts +/src/environments/environment.dev.ts +/src/environments/environment.ci.ts # ========================= # Operating System Files diff --git a/.travis.yml b/.travis.yml index f262434..22ae810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,8 @@ addons: language: node_js node_js: - 8 +before_install: + - openssl aes-256-cbc -K $encrypted_9d2af3734b6c_key -iv $encrypted_9d2af3734b6c_iv -in src/environments/environment.ci.ts.enc -out src/environments/environment.ci.ts -d before_script: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start diff --git a/CHANGELOG.md b/CHANGELOG.md index 1849098..7e6321b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ # Next Release +# v0.0.2 + +* Supplier map added to organisation view +* Fix various linter errors +* Payroll Log Data added +* Fixed register box view on login page +* Made the form reset properly if adding a new one +* Added better error messages on register and account edit + # v0.0.1 * Added Travis Testing diff --git a/bin/build-releases b/bin/build-releases new file mode 100755 index 0000000..0a840d2 --- /dev/null +++ b/bin/build-releases @@ -0,0 +1,23 @@ +#! /bin/bash + +VERSION=`git describe --tags` + +echo "Building releases for $VERSION" + +echo "Building Prod Release..." + +ng build --prod + +tar -czf ../LocalLoop-Web-prod-$VERSION.tar.gz dist + +echo "Building Dev Release..." + +ng build --dev + +tar -cvzf ../LocalLoop-Web-dev-$VERSION.tar.gz dist + +echo "Cleaning up build artefacts..." + +rm -rf dist + +echo "Done" diff --git a/package-lock.json b/package-lock.json index 2c53884..b3325ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,14 @@ { - "name": "coreui-angular", - "version": "1.0.0-alpha.5", + "name": "localloop-web", + "version": "0.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { + "@agm/core": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@agm/core/-/core-1.0.0-beta.1.tgz", + "integrity": "sha512-IVwQGmcaE42SmYY2e5QwqOC0vrSXZCW8BhATY0Vpy3NjbiydSXi9T81hVqKLvuKaB3ves1sv3W++SB1Wj+5B6A==" + }, "@angular-devkit/build-optimizer": { "version": "0.0.13", "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.0.13.tgz", diff --git a/package.json b/package.json index 9c56d35..5560151 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "localloop-web", - "version": "0.0.1", + "version": "0.0.2", "description": "LocalLoop Web - Web interface for LocalLoop app", "author": "", "url": "http://www.peartrade.org", @@ -10,13 +10,15 @@ "start": "ng serve", "build": "ng build", "test": "ng test", - "test:once": "ng test --watch=false", + "test:ci": "ng test --watch=false --env=ci", "lint": "ng lint", "e2e": "ng e2e", - "ci": "npm run test:once && npm run e2e" + "e2e:ci": "ng e2e --env=ci", + "ci": "npm run test:ci && npm run e2e:ci" }, "private": true, "dependencies": { + "@agm/core": "^1.0.0-beta.1", "@angular/common": "4.0.3", "@angular/compiler": "4.0.3", "@angular/core": "4.0.3", diff --git a/src/app/_guards/auth.guard.ts b/src/app/_guards/auth.guard.ts index 3e7a9fc..d267cf4 100644 --- a/src/app/_guards/auth.guard.ts +++ b/src/app/_guards/auth.guard.ts @@ -8,13 +8,13 @@ export class AuthGuard implements CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { if (localStorage.getItem('sessionKey')) { - console.log('session key found') + console.log('session key found'); // logged in so return true return true; } // not logged in so redirect to login page with the return url - console.log('no session key found') + console.log('no session key found'); this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }}); return false; } diff --git a/src/app/auth/login.component.html b/src/app/auth/login.component.html index 41095ff..5c02b96 100644 --- a/src/app/auth/login.component.html +++ b/src/app/auth/login.component.html @@ -37,7 +37,7 @@ -
+

Sign up

diff --git a/src/app/auth/register.component.html b/src/app/auth/register.component.html index dbe0c82..1a0c868 100644 --- a/src/app/auth/register.component.html +++ b/src/app/auth/register.component.html @@ -6,7 +6,7 @@

Register

Create your account

- + - +
- +
- +
- +
@@ -137,7 +137,7 @@ Form validation failed, please ensure the form is filled correctly.
diff --git a/src/app/auth/register.component.ts b/src/app/auth/register.component.ts index ebc69d2..d716340 100644 --- a/src/app/auth/register.component.ts +++ b/src/app/auth/register.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { Validators, FormBuilder, FormGroup } from '@angular/forms'; -import { ValidationManager } from "ng2-validation-manager"; +import { ValidationManager } from 'ng2-validation-manager'; import { Http, Response } from '@angular/http'; import { ApiService } from '../providers/api-service'; import {Router } from '@angular/router'; @@ -16,117 +16,136 @@ export class RegisterComponent { organisationForm: ValidationManager; years: Object[]; registerStatus: any; - - constructor( - private http: Http, - private formBuilder: FormBuilder, - private router: Router, - private api: ApiService, - ) { - this.years = []; - let max = new Date().getFullYear() - 10, - min = max - 140; + registerStatusError = 'Error received, please try again.'; - for (let i = max; i>=min; i--){ - this.years.push(i); - } - this.signupForm = new ValidationManager({ - token: 'required', - usertype: 'required', - email: 'required|email', - password: 'required', - confirmpassword: 'required|equalTo:password' - }); - this.customerForm = new ValidationManager({ - display_name: 'required', - full_name: 'required', - postcode: 'required', - year_of_birth:'required', - }); - this.organisationForm = new ValidationManager({ - name: 'required', - sector: 'required', - street_name: 'required', - town: 'required', - postcode: 'required', - }); + constructor( + private http: Http, + private formBuilder: FormBuilder, + private router: Router, + private api: ApiService, + ) { + this.years = []; + const max = new Date().getFullYear() - 10, + min = max - 140; + + for (let i = max; i >= min; i--) { + this.years.push(i); } - + this.signupForm = new ValidationManager({ + token: 'required', + usertype: 'required', + email: 'required|email', + password: 'required', + confirmpassword: 'required|equalTo:password' + }); + this.customerForm = new ValidationManager({ + display_name: 'required', + full_name: 'required', + postcode: 'required', + year_of_birth: 'required', + }); + this.organisationForm = new ValidationManager({ + name: 'required', + sector: 'required', + street_name: 'required', + town: 'required', + postcode: 'required', + }); + } + onSubmitCustomer() { - + console.log(this.signupForm.isValid()); - if (!this.signupForm.isValid() && !this.customerForm.isValid()) { - console.log("Not Valid!"); - this.registerStatus = "validation_failed"; + if (!this.signupForm.isValid() && !this.customerForm.isValid()) { + console.log('Not Valid!'); + this.registerStatus = 'validation_failed'; console.log(this.registerStatus); - return; - } - let signupForm = this.signupForm.getForm().value; - let customerForm = this.customerForm.getForm().value; - - let data = { - token: signupForm.token, - usertype: signupForm.usertype, - email: signupForm.email, - password: signupForm.password, - display_name: customerForm.display_name, - full_name: customerForm.full_name, - postcode: customerForm.postcode, - year_of_birth:customerForm.year_of_birth, - }; - console.log(data); - this.api + return; + } + const signupForm = this.signupForm.getForm().value; + const customerForm = this.customerForm.getForm().value; + + const data = { + token: signupForm.token, + usertype: signupForm.usertype, + email: signupForm.email, + password: signupForm.password, + display_name: customerForm.display_name, + full_name: customerForm.full_name, + postcode: customerForm.postcode, + year_of_birth: customerForm.year_of_birth, + }; + console.log(data); + this.api .register(data) .subscribe( result => { console.log('registered!'); - this.registerStatus = "success"; + this.registerStatus = 'success'; console.log(this.registerStatus); - this.router.navigate(['/dashboard']); + this.router.navigate(['/dashboard']); }, error => { - console.log( error._body ); - this.registerStatus = "send_failed"; - console.log(this.registerStatus) + console.log('Register Error'); + console.log(error); + try { + console.log(error.error); + const jsonError = error.json(); + console.log('boop'); + this.registerStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; + } catch (e) { + this.registerStatusError = 'There was a server error, please try again later.'; + } + this.registerStatus = 'send_failed'; + console.log(this.registerStatus); } ); } onSubmitOrganisation() { - + console.log(this.signupForm.isValid()); - if (!this.signupForm.isValid() || !this.organisationForm.isValid()) { - console.log("Not Valid!"); - this.registerStatus = "validation_failed"; + if (!this.signupForm.isValid() || !this.organisationForm.isValid()) { + console.log('Not Valid!'); + this.registerStatus = 'validation_failed'; console.log(this.registerStatus); - return; - } - let signupForm = this.signupForm.getForm().value; - let organisationForm = this.organisationForm.getForm().value; - - let data = { - token: signupForm.token, - usertype: signupForm.usertype, - email: signupForm.email, - password: signupForm.password, - name: organisationForm.name, + return; + } + const signupForm = this.signupForm.getForm().value; + const organisationForm = this.organisationForm.getForm().value; + + const data = { + token: signupForm.token, + usertype: signupForm.usertype, + email: signupForm.email, + password: signupForm.password, + name: organisationForm.name, sector: organisationForm.sector, - street_name: organisationForm.street_name, - town: organisationForm.town, - postcode: organisationForm.postcode, - }; - console.log(data); - this.api + street_name: organisationForm.street_name, + town: organisationForm.town, + postcode: organisationForm.postcode, + }; + console.log(data); + this.api .register(data) .subscribe( result => { console.log('registered!'); - this.registerStatus = "success"; + this.registerStatus = 'success'; console.log(this.registerStatus); this.router.navigate(['/dashboard']); }, error => { - console.log( error._body ); - this.registerStatus = "send_failed"; + console.log('Register Error'); + console.log(error); + try { + console.log(error.error); + const jsonError = error.json(); + console.log('boop'); + this.registerStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; + } catch (e) { + this.registerStatusError = 'There was a server error, please try again later.'; + } + this.registerStatus = 'send_failed'; console.log(this.registerStatus); } ); diff --git a/src/app/dashboard/account-edit.component.html b/src/app/dashboard/account-edit.component.html index f46aca7..5d4e7b4 100644 --- a/src/app/dashboard/account-edit.component.html +++ b/src/app/dashboard/account-edit.component.html @@ -122,7 +122,7 @@ Form validation failed, please ensure the form is filled correctly.
@@ -160,7 +160,7 @@ Form validation failed, please ensure the form is filled correctly. diff --git a/src/app/dashboard/account-edit.component.ts b/src/app/dashboard/account-edit.component.ts index eedd3ad..cf5b14c 100644 --- a/src/app/dashboard/account-edit.component.ts +++ b/src/app/dashboard/account-edit.component.ts @@ -14,6 +14,7 @@ export class AccountEditComponent implements OnInit { accountType: any; // @ViewChild('fileInput') fileInput; submitStatus: any; + submitStatusError = 'Error received, please try again.'; constructor( private http: Http, @@ -71,7 +72,7 @@ export class AccountEditComponent implements OnInit { console.log(this.settingForm.valid); if (!this.settingForm.valid && !this.settingOrganisationForm.valid) { console.log('Not Valid!'); - this.submitStatus = "validation_failed"; + this.submitStatus = 'validation_failed'; console.log(this.submitStatus); return; } @@ -107,12 +108,21 @@ export class AccountEditComponent implements OnInit { .subscribe( result => { console.log('data submitted!'); - this.submitStatus = "success"; + this.submitStatus = 'success'; console.log(this.submitStatus); }, error => { - console.log( error._body ); - this.submitStatus = "send_failed"; + console.log('Edit Error'); + console.log(error); + try { + console.log(error.error); + const jsonError = error.json(); + console.log('boop'); + this.submitStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; + } catch (e) { + this.submitStatusError = 'There was a server error, please try again later.'; + } + this.submitStatus = 'send_failed'; console.log(this.submitStatus); } ); @@ -122,7 +132,7 @@ export class AccountEditComponent implements OnInit { console.log(this.settingForm.valid); if (!this.settingForm.valid && !this.settingCustomerForm.valid) { console.log('Not Valid!'); - this.submitStatus = "validation_failed"; + this.submitStatus = 'validation_failed'; console.log(this.submitStatus); return; } @@ -155,12 +165,21 @@ export class AccountEditComponent implements OnInit { .subscribe( result => { console.log('data submitted!'); - this.submitStatus = "success"; + this.submitStatus = 'success'; console.log(this.submitStatus); }, error => { - console.log( error._body ); - this.submitStatus = "send_failed"; + console.log('Edit Error'); + console.log(error); + try { + console.log(error.error); + const jsonError = error.json(); + console.log('boop'); + this.submitStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; + } catch (e) { + this.submitStatusError = 'There was a server error, please try again later.'; + } + this.submitStatus = 'send_failed'; console.log(this.submitStatus); } ); diff --git a/src/app/dashboard/add-data.component.html b/src/app/dashboard/add-data.component.html index 91e8e42..3a78b96 100644 --- a/src/app/dashboard/add-data.component.html +++ b/src/app/dashboard/add-data.component.html @@ -72,7 +72,7 @@ -
+
Profile & Payroll Data Required Data marked in bold. diff --git a/src/app/dashboard/add-data.component.ts b/src/app/dashboard/add-data.component.ts index c121d0a..359c294 100644 --- a/src/app/dashboard/add-data.component.ts +++ b/src/app/dashboard/add-data.component.ts @@ -9,7 +9,7 @@ import 'rxjs/add/operator/map'; @Component({ templateUrl: 'add-data.component.html', }) -export class AddDataComponent { +export class AddDataComponent implements OnInit { payrollForm: FormGroup; singleSupplierForm: FormGroup; employeeForm: FormGroup; @@ -18,7 +18,7 @@ export class AddDataComponent { singleSupplierFormStatus: any; employeeFormStatus: any; transactionFormStatus: any; - transactionFormStatusError: string = 'Error received, please try again.'; + transactionFormStatusError = 'Error received, please try again.'; accountType: any; submitOrg = { @@ -41,20 +41,20 @@ export class AddDataComponent { constructor( private http: Http, - private formBuilder: FormBuilder, - private api: ApiService, - ) { + private formBuilder: FormBuilder, + private api: ApiService, + ) { this.payrollForm = this.formBuilder.group({ - entry_period: ['', [Validators.required]], - employee_amount: ['', [Validators.required]], - local_employee_amount: ['', [Validators.required]], - gross_payroll: ['', [Validators.required]], + entry_period: ['', [Validators.required]], + employee_amount: ['', [Validators.required]], + local_employee_amount: ['', [Validators.required]], + gross_payroll: ['', [Validators.required]], payroll_income_tax: ['', [Validators.required]], payroll_employee_ni: ['', [Validators.required]], payroll_employer_ni: ['', [Validators.required]], payroll_total_pension: ['', [Validators.required]], payroll_other_benefit: ['', [Validators.required]], - }); + }); this.employeeForm = this.formBuilder.group({ entry_period: ['', [Validators.required]], employee_no: ['', [Validators.required]], @@ -63,7 +63,7 @@ export class AddDataComponent { employee_ni: ['', [Validators.required]], employee_pension: ['', [Validators.required]], employee_other_benefit: ['', [Validators.required]], - }); + }); this.myDate = moment().format('YYYY-MM-DD[T]HH:mm'); // this.myDate = new Date().toISOString().slice(0, 16); } @@ -73,13 +73,13 @@ export class AddDataComponent { this.accountType = localStorage.getItem('usertype'); } - getMinDate(){ + getMinDate() { // gets the April 1st date of the current year - let aprilDate = moment().month(3).date(1); - let now = moment(); + const aprilDate = moment().month(3).date(1); + const now = moment(); // Checks if current time is before April 1st, if so returns true - let beforeApril = now.isBefore(aprilDate); - if ( beforeApril == true ) { + const beforeApril = now.isBefore(aprilDate); + if ( beforeApril === true ) { this.minDate = aprilDate.subtract(2, 'years').format('YYYY-MM-DD'); } else { this.minDate = aprilDate.subtract(1, 'years').format('YYYY-MM-DD'); @@ -88,16 +88,16 @@ export class AddDataComponent { initializeItems() { // Dont bother searching for an empty or undefined string - if ( this.submitOrg.name == '' ) { + if ( this.submitOrg.name === '' ) { return; } - var searchData = { + const searchData = { search_name: this.submitOrg.name, }; this.api.search(searchData).subscribe( data => { - if(data.validated.length > 0) { + if (data.validated.length > 0) { this.storeList = data.validated; this.showAddStore = false; this.transactionAdditionType = 1; @@ -107,7 +107,7 @@ export class AddDataComponent { this.transactionAdditionType = 2; } // handle the case when the storelist is empty - if(this.storeList.length < 1 ) { + if (this.storeList.length < 1) { this.storeList = null; this.showAddStore = true; this.transactionAdditionType = 3; @@ -120,7 +120,7 @@ export class AddDataComponent { } // if user select a item from the list - addStore(store){ + addStore(store) { this.submitOrg = store; this.transactionFormValidate(); this.organisationId = store.id; @@ -132,39 +132,40 @@ export class AddDataComponent { this.initializeItems(); // set val to the value of the searchbar - let val = ev.target.value; + const val = ev.target.value; // Filter the store list so search seems quicker - if (val && val.trim() != '' && this.storeList != null) { + if (val && val.trim() !== '' && this.storeList !== null) { this.storeList = this.storeList.filter( (item) => { return ( item.name.toLowerCase().indexOf( val.toLowerCase() ) > -1 ); } - ) + ); } // if nothing is found - if(!this.storeList === null){ + if (!this.storeList === null) { // display add new store button this.showAddStore = true; } } transactionFormValidate() { - if( this.submitOrg.name.length == 0 && - this.amount == 0 ) { + if (this.submitOrg.name.length === 0 || + this.submitOrg.town.length === 0 || + this.amount === 0 ) { this.transactionFormInvalid = true; - }else{ + } else { this.transactionFormInvalid = false; } } public postTransaction() { - var myParams: any; + let myParams: any; let purchaseTime: string; purchaseTime = moment(this.myDate, 'YYYY-MM-DD[T]HH:mm').local().format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'); - switch(this.transactionAdditionType){ + switch (this.transactionAdditionType) { case 1: myParams = { transaction_type : this.transactionAdditionType, @@ -199,16 +200,16 @@ export class AddDataComponent { .upload(myParams) .subscribe( result => { - if ( result.success == true ) { + if ( result.success === true ) { console.log('Successful Upload'); console.log(result); - this.transactionFormStatus = "success"; + this.transactionFormStatus = 'success'; console.log(this.transactionFormStatus); this.resetForm(); } else { console.log('Upload Error'); this.transactionFormStatusError = JSON.stringify(result.status) + 'Error, ' + JSON.stringify(result.message); - this.transactionFormStatus = "send_failed"; + this.transactionFormStatus = 'send_failed'; console.log(this.transactionFormStatus); } }, @@ -217,13 +218,13 @@ export class AddDataComponent { console.log(error); try { console.log(error.error); - let jsonError = error.json(); - console.log("boop"); + const jsonError = error.json(); + console.log('boop'); this.transactionFormStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; - } catch(e) { + } catch (e) { this.transactionFormStatusError = 'There was a server error, please try again later.'; } - this.transactionFormStatus = "send_failed"; + this.transactionFormStatus = 'send_failed'; console.log(this.transactionFormStatus); } ); @@ -239,60 +240,61 @@ export class AddDataComponent { this.storeList = null; this.amount = null; this.transactionFormInvalid = true; + this.showAddStore = false; } onSubmitPayroll() { - console.log(this.payrollForm.value); + console.log(this.payrollForm.value); - this.api + this.api .orgPayroll(this.payrollForm.value) .subscribe( result => { console.log('data submitted!'); - this.payrollFormStatus = "success"; + this.payrollFormStatus = 'success'; console.log(this.payrollFormStatus); }, error => { console.log( error._body ); - this.payrollFormStatus = "send_failed"; + this.payrollFormStatus = 'send_failed'; console.log(this.payrollFormStatus); } ); } onSubmitSingleSupplier() { - console.log(this.singleSupplierForm.value); + console.log(this.singleSupplierForm.value); - this.api + this.api .orgSupplier(this.singleSupplierForm.value) .subscribe( result => { console.log('data submitted!'); - this.singleSupplierFormStatus = "success"; + this.singleSupplierFormStatus = 'success'; console.log(this.singleSupplierFormStatus); }, error => { console.log( error._body ); - this.singleSupplierFormStatus = "send_failed"; + this.singleSupplierFormStatus = 'send_failed'; console.log(this.singleSupplierFormStatus); } ); } onSubmitEmployee() { - console.log(this.employeeForm.value); + console.log(this.employeeForm.value); - this.api + this.api .orgEmployee(this.employeeForm.value) .subscribe( result => { console.log('data submitted!'); - this.employeeFormStatus = "success"; + this.employeeFormStatus = 'success'; console.log(this.employeeFormStatus); }, error => { console.log( error._body ); - this.employeeFormStatus = "send_failed"; + this.employeeFormStatus = 'send_failed'; console.log(this.employeeFormStatus); } ); diff --git a/src/app/dashboard/dashboard-customer.component.ts b/src/app/dashboard/dashboard-customer.component.ts index dc8c9c6..09787e3 100644 --- a/src/app/dashboard/dashboard-customer.component.ts +++ b/src/app/dashboard/dashboard-customer.component.ts @@ -15,7 +15,7 @@ export class DashboardCustomerComponent implements OnInit { /* Setting up dashboard's main variables*/ name: any; - email:any; + email: any; myPearPoints: any; trends: any; myRank: any; diff --git a/src/app/dashboard/dashboard.module.ts b/src/app/dashboard/dashboard.module.ts index 55bb110..a8c59b0 100644 --- a/src/app/dashboard/dashboard.module.ts +++ b/src/app/dashboard/dashboard.module.ts @@ -4,6 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ChartsModule } from 'ng2-charts/ng2-charts'; import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; import { NgxPaginationModule } from 'ngx-pagination'; +import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core'; import { CurrencyPipe } from '@angular/common'; @@ -13,6 +14,8 @@ import { AccountEditComponent } from './account-edit.component'; import { AddDataComponent } from './add-data.component'; import { FeedbackComponent } from './feedback.component'; import { TransactionLogComponent } from './transaction-log.component'; +import { PayrollLogComponent } from './payroll-log.component'; +import { MapComponent } from './map.component'; import { GraphWidget } from '../widgets/graph-widget.component'; import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component'; @@ -22,6 +25,10 @@ import { DashboardRoutingModule } from './dashboard.routing'; import { OrgResultComponent } from '../shared/org-result.component'; import { OrgTableComponent } from '../shared/org-table.component'; import { TransactionResultComponent } from '../shared/transaction-result.component'; +import { PayrollResultComponent } from '../shared/payroll-result.component'; + +// API key env variable import +import { environment } from '../../environments/environment'; @NgModule({ imports: [ @@ -30,6 +37,9 @@ import { TransactionResultComponent } from '../shared/transaction-result.compone FormsModule, ReactiveFormsModule, ChartsModule, + AgmCoreModule.forRoot({ + apiKey: environment.mapApiKey + }), BsDropdownModule, NgxPaginationModule, DashboardRoutingModule, @@ -43,13 +53,17 @@ import { TransactionResultComponent } from '../shared/transaction-result.compone OrgTableComponent, TransactionLogComponent, TransactionResultComponent, + PayrollLogComponent, + PayrollResultComponent, + MapComponent, FeedbackComponent, GraphWidget, OrgBarSnippetComponent, GraphPanel, ], providers: [ - CurrencyPipe + CurrencyPipe, + GoogleMapsAPIWrapper, ], }) export class DashboardModule { } diff --git a/src/app/dashboard/dashboard.routing.ts b/src/app/dashboard/dashboard.routing.ts index acb81b7..f28c65e 100644 --- a/src/app/dashboard/dashboard.routing.ts +++ b/src/app/dashboard/dashboard.routing.ts @@ -12,6 +12,8 @@ import { AccountEditComponent } from './account-edit.component'; import { AddDataComponent } from './add-data.component'; import { FeedbackComponent } from './feedback.component'; import { TransactionLogComponent } from './transaction-log.component'; +import { PayrollLogComponent } from './payroll-log.component'; +import { MapComponent } from './map.component'; // Using child path to allow for FullLayout theming const routes: Routes = [ @@ -48,6 +50,18 @@ const routes: Routes = [ component: TransactionLogComponent, data: { title: 'Transaction Log' }, }, + { + path: 'map', + component: MapComponent, + data: { title: 'Supplier Map' }, + canActivate: [OrgGuard], + }, + { + path: 'payroll-log', + component: PayrollLogComponent, + data: { title: 'Payroll Log' }, + canActivate: [OrgGuard], + }, { path: 'feedback', component: FeedbackComponent, diff --git a/src/app/dashboard/feedback.component.ts b/src/app/dashboard/feedback.component.ts index 11d56d4..91ef375 100644 --- a/src/app/dashboard/feedback.component.ts +++ b/src/app/dashboard/feedback.component.ts @@ -7,18 +7,18 @@ import 'rxjs/add/operator/map'; @Component({ templateUrl: 'feedback.component.html', }) -export class FeedbackComponent { +export class FeedbackComponent implements OnInit { feedbackForm: FormGroup; loggedInEmail: string; - noEmail: boolean = false; + noEmail = false; username: any; feedbackFormStatus: any; - feedbackFormStatusError: string = 'Error received, please try again.'; + feedbackFormStatusError = 'Error received, please try again.'; constructor( private http: Http, - private formBuilder: FormBuilder, - private api: ApiService, + private formBuilder: FormBuilder, + private api: ApiService, ) { this.feedbackForm = this.formBuilder.group({ email: ['', [Validators.required]], @@ -28,7 +28,7 @@ export class FeedbackComponent { ngOnInit(): void { - if(localStorage.getItem('email')) { + if (localStorage.getItem('email')) { this.loggedInEmail = localStorage.getItem('email'); } console.log('loggedInEmail: ' + this.loggedInEmail); @@ -55,10 +55,10 @@ export class FeedbackComponent { .feedback(this.feedbackForm.value) .subscribe( result => { - if ( result.success == true ) { + if ( result.success === true ) { console.log('Successful Upload'); console.log(result); - this.feedbackFormStatus = "success"; + this.feedbackFormStatus = 'success'; console.log(this.feedbackFormStatus); this.feedbackForm.patchValue({ feedbacktext: '', @@ -66,7 +66,7 @@ export class FeedbackComponent { } else { console.log('Upload Error'); this.feedbackFormStatusError = JSON.stringify(result.status) + 'Error, ' + JSON.stringify(result.message); - this.feedbackFormStatus = "send_failed"; + this.feedbackFormStatus = 'send_failed'; console.log(this.feedbackFormStatus); } }, @@ -75,13 +75,13 @@ export class FeedbackComponent { console.log(error); try { console.log(error.error); - let jsonError = error.json(); - console.log("boop"); + const jsonError = error.json(); + console.log('boop'); this.feedbackFormStatusError = '"' + jsonError.error + '" Error, ' + jsonError.message; - } catch(e) { + } catch (e) { this.feedbackFormStatusError = 'There was a server error, please try again later.'; } - this.feedbackFormStatus = "send_failed"; + this.feedbackFormStatus = 'send_failed'; console.log(this.feedbackFormStatus); } ); diff --git a/src/app/dashboard/map.component.html b/src/app/dashboard/map.component.html new file mode 100644 index 0000000..1c408a4 --- /dev/null +++ b/src/app/dashboard/map.component.html @@ -0,0 +1,41 @@ +
+
+
+
+
+ Supplier Map + Required Data marked in bold. +
+
+
+ +
+
+ + + + + + + {{m.name}} + + + +
+
+
+
+
+
diff --git a/src/app/dashboard/map.component.ts b/src/app/dashboard/map.component.ts new file mode 100644 index 0000000..71faed0 --- /dev/null +++ b/src/app/dashboard/map.component.ts @@ -0,0 +1,66 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { ApiService } from '../providers/api-service'; +import { AgmCoreModule } from '@agm/core'; +import 'rxjs/add/operator/map'; + +@Component({ + templateUrl: 'map.component.html', +}) +export class MapComponent implements OnInit { + + lat: number = 54.0466; + lng: number = -2.8007; + zoom: number = 12; + + dataReceived: string = 'yes'; + + markers: Array<{latitude: number, longitude: number, name: string}>; + + map: any; + + constructor( + private http: Http, + private api: ApiService, + ) { } + + ngOnInit(): void { } + + public onMapReady(map: any) { + this.map = map; + } + + public viewBoundsChanged() { + console.log("finding bounds"); + const resp = this.map.getBounds(); + console.log("found bounds"); + console.log(resp.getNorthEast().lat()); + console.log(resp.getNorthEast().lng()); + console.log(resp.getSouthWest().lat()); + console.log(resp.getSouthWest().lng()); + const mapData = { + north_east: { + latitude: resp.getNorthEast().lat(), + longitude: resp.getNorthEast().lng() + }, + south_west: { + latitude: resp.getSouthWest().lat(), + longitude: resp.getSouthWest().lng() + }, + } + this.api.getMapData(mapData).subscribe( + result => { + this.dataReceived = 'yes'; + this.markers = result.suppliers; + }, + error => { + // this.dataReceived = 'no'; + console.log('Retrieval Error'); + console.log( error._body ); + } + ); + } + + + +} diff --git a/src/app/dashboard/payroll-log.component.html b/src/app/dashboard/payroll-log.component.html new file mode 100644 index 0000000..0b08ed8 --- /dev/null +++ b/src/app/dashboard/payroll-log.component.html @@ -0,0 +1,49 @@ +
+
+
+
+
+ Log of Payroll submissions + Sorted descending from submission date. +
+
+ + + + + + + + + + + +
Entry PeriodGross PayrollEmployees
+ + + +
+
+ No Payroll data available. +
+
+
+
+
diff --git a/src/app/dashboard/payroll-log.component.ts b/src/app/dashboard/payroll-log.component.ts new file mode 100644 index 0000000..3e7a3ce --- /dev/null +++ b/src/app/dashboard/payroll-log.component.ts @@ -0,0 +1,77 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { ApiService } from '../providers/api-service'; +// import { PaginatePipe } from 'ngx-pagination'; +import {PaginationInstance} from 'ngx-pagination'; +// import { PaginationControlsComponent } from 'ngx-pagination'; +// import { PaginationControlsDirective } from 'ngx-pagination'; +// import { TransactionResultComponent } from '../shared/transaction-result.component'; +import * as moment from 'moment'; +import 'rxjs/add/operator/map'; + +@Component({ + templateUrl: 'payroll-log.component.html', +}) +export class PayrollLogComponent implements OnInit { + + payrollList; + noPayrollList = true; + myDate: any; + minDate: any; + + public paginateConfig: PaginationInstance = { + id: 'transpaginate', + itemsPerPage: 10, + currentPage: 1, + totalItems: 0 + }; + + constructor( + private http: Http, + private api: ApiService, + ) { + this.myDate = moment().format('YYYY-MM-DD[T]HH:mm'); + // this.myDate = new Date().toISOString().slice(0, 16); + } + + ngOnInit(): void { + this.getMinDate(); + this.loadPayrolls(1); + } + + getMinDate(){ + // gets the April 1st date of the current year + let aprilDate = moment().month(3).date(1); + let now = moment(); + // Checks if current time is before April 1st, if so returns true + let beforeApril = now.isBefore(aprilDate); + if ( beforeApril == true ) { + this.minDate = aprilDate.subtract(2, 'years').format('YYYY-MM-DD'); + } else { + this.minDate = aprilDate.subtract(1, 'years').format('YYYY-MM-DD'); + } + } + + loadPayrolls(logPage: number) { + console.log(logPage); + this.api.payrollList(logPage).subscribe( + result => { + if(result.payrolls.length > 0) { + this.payrollList = result.payrolls; + //TODO Rename in server + this.paginateConfig.totalItems = result.page_no; + this.paginateConfig.currentPage = logPage; + this.noPayrollList = false; + } else { + // handle the case when the payrollList is empty + this.payrollList = null; + this.noPayrollList = true; + } + }, + error => { + console.log(error); + } + ); + } + +} diff --git a/src/app/dashboard/transaction-log.component.ts b/src/app/dashboard/transaction-log.component.ts index f707e83..60c4e6f 100644 --- a/src/app/dashboard/transaction-log.component.ts +++ b/src/app/dashboard/transaction-log.component.ts @@ -12,12 +12,13 @@ import 'rxjs/add/operator/map'; @Component({ templateUrl: 'transaction-log.component.html', }) -export class TransactionLogComponent { +export class TransactionLogComponent implements OnInit { transactionList; noTransactionList = true; myDate: any; minDate: any; + public p: any; public paginateConfig: PaginationInstance = { id: 'transpaginate', @@ -28,8 +29,8 @@ export class TransactionLogComponent { constructor( private http: Http, - private api: ApiService, - ) { + private api: ApiService, + ) { this.myDate = moment().format('YYYY-MM-DD[T]HH:mm'); // this.myDate = new Date().toISOString().slice(0, 16); } @@ -39,13 +40,13 @@ export class TransactionLogComponent { this.loadTransactions(1); } - getMinDate(){ + getMinDate() { // gets the April 1st date of the current year - let aprilDate = moment().month(3).date(1); - let now = moment(); + const aprilDate = moment().month(3).date(1); + const now = moment(); // Checks if current time is before April 1st, if so returns true - let beforeApril = now.isBefore(aprilDate); - if ( beforeApril == true ) { + const beforeApril = now.isBefore(aprilDate); + if ( beforeApril === true ) { this.minDate = aprilDate.subtract(2, 'years').format('YYYY-MM-DD'); } else { this.minDate = aprilDate.subtract(1, 'years').format('YYYY-MM-DD'); @@ -56,9 +57,9 @@ export class TransactionLogComponent { console.log(logPage); this.api.transList(logPage).subscribe( result => { - if(result.transactions.length > 0) { + if (result.transactions.length > 0) { this.transactionList = result.transactions; - //TODO Rename in server + // TODO Rename in server this.paginateConfig.totalItems = result.page_no; this.paginateConfig.currentPage = logPage; this.noTransactionList = false; diff --git a/src/app/layouts/full-layout.component.html b/src/app/layouts/full-layout.component.html index 51a7564..4fc7f4c 100644 --- a/src/app/layouts/full-layout.component.html +++ b/src/app/layouts/full-layout.component.html @@ -40,11 +40,21 @@ Enter Feedback + +
diff --git a/src/app/layouts/full-layout.component.ts b/src/app/layouts/full-layout.component.ts index 7007e35..453a8df 100644 --- a/src/app/layouts/full-layout.component.ts +++ b/src/app/layouts/full-layout.component.ts @@ -7,16 +7,16 @@ import { Router } from '@angular/router'; templateUrl: './full-layout.component.html', }) export class FullLayoutComponent implements OnInit { - displayName: any; + public displayName: string; + public accountType: any; + public disabled = false; + public status: {isopen: boolean} = {isopen: false}; constructor( private api: ApiService, private router: Router, ) {} - public disabled = false; - public status: {isopen: boolean} = {isopen: false}; - public toggled(open: boolean): void { console.log('Dropdown is now: ', open); } @@ -30,6 +30,7 @@ export class FullLayoutComponent implements OnInit { // getDisplayName function from api didnt work ngOnInit(): void { this.displayName = localStorage.getItem('displayname') || 'User'; + this.accountType = localStorage.getItem('usertype'); } userLogout() { diff --git a/src/app/pages/404.component.html b/src/app/pages/404.component.html index e76245d..cd46b4d 100644 --- a/src/app/pages/404.component.html +++ b/src/app/pages/404.component.html @@ -7,9 +7,9 @@

Oops! You're lost.

The page you are looking for was not found.

- - - + + +
diff --git a/src/app/pages/404.component.ts b/src/app/pages/404.component.ts index 0e91023..b309577 100644 --- a/src/app/pages/404.component.ts +++ b/src/app/pages/404.component.ts @@ -7,11 +7,10 @@ import { Location } from '@angular/common'; export class P404Component { constructor( - private location: Location - ) { - } + private location: Location, + ) { } - goBack(): void { - this.location.back(); -} + goBack(): void { + this.location.back(); + } } diff --git a/src/app/pages/500.component.html b/src/app/pages/500.component.html index c08396f..e09fae4 100644 --- a/src/app/pages/500.component.html +++ b/src/app/pages/500.component.html @@ -8,8 +8,8 @@

The page you are looking for is temporarily unavailable.

- - + + diff --git a/src/app/pages/500.component.ts b/src/app/pages/500.component.ts index fa459e6..a80ff31 100644 --- a/src/app/pages/500.component.ts +++ b/src/app/pages/500.component.ts @@ -7,11 +7,10 @@ import { Location } from '@angular/common'; export class P500Component { constructor( - private location: Location - ) { - } + private location: Location, + ) { } - goBack(): void { - this.location.back(); -} -} \ No newline at end of file + goBack(): void { + this.location.back(); + } +} diff --git a/src/app/providers/api-service.ts b/src/app/providers/api-service.ts index e0f27a2..378035b 100644 --- a/src/app/providers/api-service.ts +++ b/src/app/providers/api-service.ts @@ -136,12 +136,25 @@ export class ApiService { ).map( response => response.json() ); } + // gets payroll list for log + + public payrollList(data) { + const key = this.sessionKey; + return this.http.post( + this.apiUrl + '/v1/organisation/payroll', + { + session_key : key, + page : data + } + ).map( response => response.json() ); + } + // handles Org data added public orgPayroll(data) { data.session_key = this.sessionKey; return this.http.post( - this.apiUrl + '/org/payroll', + this.apiUrl + '/v1/organisation/payroll/add', data ).map( response => response.json() ); } @@ -149,7 +162,7 @@ export class ApiService { public orgSupplier(data) { data.session_key = this.sessionKey; return this.http.post( - this.apiUrl + '/org/supplier', + this.apiUrl + '/v1/organisation/supplier/add', data ).map( response => response.json() ); } @@ -157,7 +170,7 @@ export class ApiService { public orgEmployee(data) { data.session_key = this.sessionKey; return this.http.post( - this.apiUrl + '/org/employee', + this.apiUrl + '/v1/organisation/employee/add', data ).map( response => response.json() ); } @@ -251,6 +264,15 @@ export class ApiService { ).map( response => response.json() ); } + // Initial Map Data + public getMapData(data) { + data.session_key = this.sessionKey; + return this.http.post( + this.apiUrl + '/v1/supplier/location', + data + ).map( response => response.json() ); + } + // Basic Customer User stats API public basicStats() { const key = this.sessionKey; diff --git a/src/app/shared/org-result.component.ts b/src/app/shared/org-result.component.ts index d7c599f..f22fbea 100644 --- a/src/app/shared/org-result.component.ts +++ b/src/app/shared/org-result.component.ts @@ -9,6 +9,7 @@ interface OrgData { } @Component({ + // tslint:disable-next-line selector: '[org-result]', templateUrl: 'org-result.component.html', }) @@ -19,6 +20,6 @@ export class OrgResultComponent { public orgClick(): void { this.onClick.emit( this.org - ) + ); } } diff --git a/src/app/shared/org-table.component.ts b/src/app/shared/org-table.component.ts index 8e0979d..764385c 100644 --- a/src/app/shared/org-table.component.ts +++ b/src/app/shared/org-table.component.ts @@ -10,6 +10,7 @@ interface OrgData { } @Component({ + // tslint:disable-next-line selector: 'org-table', templateUrl: 'org-table.component.html', }) diff --git a/src/app/shared/payroll-result.component.html b/src/app/shared/payroll-result.component.html new file mode 100644 index 0000000..6d891c6 --- /dev/null +++ b/src/app/shared/payroll-result.component.html @@ -0,0 +1,3 @@ +{{payrollDate}} +{{payroll.gross_payroll | currency:'GBP':true:'1.2-2' }} +{{payroll.employee_amount}} diff --git a/src/app/shared/payroll-result.component.ts b/src/app/shared/payroll-result.component.ts new file mode 100644 index 0000000..fdf3fa7 --- /dev/null +++ b/src/app/shared/payroll-result.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import * as moment from 'moment'; + +interface PayrollData { + entry_period: string; + gross_payroll: number; + employee_amount: number; +} + +@Component({ + // tslint:disable-next-line + selector: '[payroll-result]', + templateUrl: 'payroll-result.component.html', +}) +export class PayrollResultComponent implements OnInit { + @Input() public payroll: PayrollData; + public payrollDate: string; + + ngOnInit(): void { + this.payrollDate = moment(this.payroll.entry_period).format('MMMM YYYY'); + } +} diff --git a/src/app/shared/transaction-result.component.ts b/src/app/shared/transaction-result.component.ts index 782830a..a293b72 100644 --- a/src/app/shared/transaction-result.component.ts +++ b/src/app/shared/transaction-result.component.ts @@ -3,11 +3,12 @@ import * as moment from 'moment'; interface TransactionData { seller: number; - value: string; + value: number; purchase_time: string; } @Component({ + // tslint:disable-next-line selector: '[transaction-result]', templateUrl: 'transaction-result.component.html', }) diff --git a/src/environments/environment.ci.ts.enc b/src/environments/environment.ci.ts.enc new file mode 100644 index 0000000..d7f9745 --- /dev/null +++ b/src/environments/environment.ci.ts.enc @@ -0,0 +1,2 @@ +gԟ^ f^ՍjAF$Qh0L+lD)9; +@&;q蠩 iE0#ҡŎbK7U%x_x/6m=P ?qFA$|'A製b1Ռ2~/,dL”P>S L \ No newline at end of file diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts deleted file mode 100644 index 49d8dc6..0000000 --- a/src/environments/environment.prod.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const environment = { - production: true, - apiUrl: 'https://app.peartrade.org/api' -}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index bd894d3..725706a 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -5,5 +5,6 @@ export const environment = { production: false, - apiUrl: 'https://dev.peartrade.org/api' + apiUrl: 'https://dev.peartrade.org/api', + mapApiKey: 'CHANGEME', }; diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss index 08dacc5..f3e9c04 100644 --- a/src/scss/_custom.scss +++ b/src/scss/_custom.scss @@ -14,6 +14,12 @@ background-color: #0f81a8; color: #e8ebed; } + +// Map styling +agm-map { + height: 75vh; +} + // white title font variant on type-2 as defined in _widgets.css .horizontal-bars { padding: 0;