Merge pull request #23 from Pear-Trading/Release-v0.0.2

Release v0.0.2
This commit is contained in:
Tom Bloor 2017-09-28 14:38:34 +01:00 committed by GitHub
commit 1171f935a7
40 changed files with 636 additions and 225 deletions

View file

@ -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"
}
}
],

3
.gitignore vendored
View file

@ -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

View file

@ -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

View file

@ -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

23
bin/build-releases Executable file
View file

@ -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"

9
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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;
}

View file

@ -37,7 +37,7 @@
</form>
</div>
</div>
<div class="card card-inverse card-primary py-5 d-md-down-none" style="width:44%">
<div class="card card-inverse card-primary py-5">
<div class="card-block text-center">
<div>
<h2>Sign up</h2>

View file

@ -137,7 +137,7 @@
Form validation failed, please ensure the form is filled correctly.
</div>
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
Failed to send to server, please try again later.
{{registerStatusError}}
</div>
</div>
</div>

View file

@ -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,6 +16,7 @@ export class RegisterComponent {
organisationForm: ValidationManager;
years: Object[];
registerStatus: any;
registerStatusError = 'Error received, please try again.';
constructor(
private http: Http,
@ -24,10 +25,10 @@ export class RegisterComponent {
private api: ApiService,
) {
this.years = [];
let max = new Date().getFullYear() - 10,
const max = new Date().getFullYear() - 10,
min = max - 140;
for (let i = max; i>=min; i--){
for (let i = max; i >= min; i--) {
this.years.push(i);
}
this.signupForm = new ValidationManager({
@ -41,7 +42,7 @@ export class RegisterComponent {
display_name: 'required',
full_name: 'required',
postcode: 'required',
year_of_birth:'required',
year_of_birth: 'required',
});
this.organisationForm = new ValidationManager({
name: 'required',
@ -56,15 +57,15 @@ export class RegisterComponent {
console.log(this.signupForm.isValid());
if (!this.signupForm.isValid() && !this.customerForm.isValid()) {
console.log("Not Valid!");
this.registerStatus = "validation_failed";
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;
const signupForm = this.signupForm.getForm().value;
const customerForm = this.customerForm.getForm().value;
let data = {
const data = {
token: signupForm.token,
usertype: signupForm.usertype,
email: signupForm.email,
@ -72,7 +73,7 @@ export class RegisterComponent {
display_name: customerForm.display_name,
full_name: customerForm.full_name,
postcode: customerForm.postcode,
year_of_birth:customerForm.year_of_birth,
year_of_birth: customerForm.year_of_birth,
};
console.log(data);
this.api
@ -80,14 +81,23 @@ export class RegisterComponent {
.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(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);
}
);
}
@ -95,15 +105,15 @@ export class RegisterComponent {
console.log(this.signupForm.isValid());
if (!this.signupForm.isValid() || !this.organisationForm.isValid()) {
console.log("Not Valid!");
this.registerStatus = "validation_failed";
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;
const signupForm = this.signupForm.getForm().value;
const organisationForm = this.organisationForm.getForm().value;
let data = {
const data = {
token: signupForm.token,
usertype: signupForm.usertype,
email: signupForm.email,
@ -120,13 +130,22 @@ export class RegisterComponent {
.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);
}
);

View file

@ -122,7 +122,7 @@
Form validation failed, please ensure the form is filled correctly.
</div>
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
Failed to send to server, please try again later.
{{submitStatusError}}
</div>
</div>
</div>
@ -160,7 +160,7 @@
Form validation failed, please ensure the form is filled correctly.
</div>
<div *ngSwitchCase="'send_failed'" class="alert alert-danger" role="alert">
Failed to send to server, please try again later.
{{submitStatusError}}
</div>
</div>
</div>

View file

@ -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);
}
);

View file

@ -72,7 +72,7 @@
<button type="submit" (click)="postTransaction()" [disabled]="transactionFormInvalid" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
</div>
</div>
<div *ngIf="false" class="card">
<div *ngIf="accountType == 'organisation'" class="card">
<div class="card-header">
<strong>Profile & Payroll Data</strong>
<small>Required Data marked in <strong>bold</strong>.</small>

View file

@ -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 = {
@ -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,6 +240,7 @@ export class AddDataComponent {
this.storeList = null;
this.amount = null;
this.transactionFormInvalid = true;
this.showAddStore = false;
}
onSubmitPayroll() {
@ -249,12 +251,12 @@ export class AddDataComponent {
.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);
}
);
@ -268,12 +270,12 @@ export class AddDataComponent {
.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);
}
);
@ -287,12 +289,12 @@ export class AddDataComponent {
.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);
}
);

View file

@ -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;

View file

@ -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 { }

View file

@ -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,

View file

@ -7,13 +7,13 @@ 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,
@ -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);
}
);

View file

@ -0,0 +1,41 @@
<div class="animated fadeIn">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<strong>Supplier Map</strong>
<small>Required Data marked in <strong>bold</strong>.</small>
</div>
<div [ngSwitch]="dataReceived">
<div *ngSwitchCase="'no'"class="card-block">
<div class="alert alert-danger" role="alert">
No map data received, check your connection.
</div>
</div>
<div *ngSwitchCase="'yes'">
<!-- this creates a google map on the page with the given lat/lng from -->
<!-- the component as the initial center of the map: -->
<agm-map
(mapReady)="onMapReady($event)"
[latitude]="lat"
[longitude]="lng"
[zoom]="zoom"
[scaleControl]="true"
(idle)="viewBoundsChanged($event)">
<agm-marker
*ngFor="let m of markers"
[latitude]="m.latitude"
[longitude]="m.longitude"
[label]="m.name[0]">
<agm-info-window>
<strong>{{m.name}}</strong>
</agm-info-window>
</agm-marker>
</agm-map>
</div>
</div>
</div>
</div>
</div><!--/.row-->
</div>

View file

@ -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 );
}
);
}
}

View file

@ -0,0 +1,49 @@
<div class="animated fadeIn">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<strong>Log of Payroll submissions</strong>
<small>Sorted descending from submission date.</small>
</div>
<div *ngIf="!noPayrollList" class="card-block">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Entry Period</th>
<th>Gross Payroll</th>
<th>Employees</th>
</tr>
</thead>
<tbody>
<tr payroll-result *ngFor="let payroll of payrollList | paginate: paginateConfig" [payroll]="payroll"></tr>
</tbody>
</table>
<pagination-template #p="paginationApi"
[id]="paginateConfig.id"
(pageChange)="loadPayrolls($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="noPayrollList" class="card-block">
No Payroll data available.
</div>
</div>
</div>
</div>
</div>

View file

@ -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);
}
);
}
}

View file

@ -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',
@ -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;

View file

@ -40,11 +40,21 @@
<i class="icon-envelope-letter"></i> Enter Feedback
</a>
</li>
<li *ngIf="accountType == 'organisation'" class="nav-item">
<a class="nav-link" routerLinkActive="active" [routerLink]="['/map']">
<i class="icon-map"></i> Supplier Map
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLinkActive="active" [routerLink]="['/transaction-log']">
<i class="icon-basket"></i> Transaction Log
</a>
</li>
<li *ngIf="accountType == 'organisation'" class="nav-item">
<a class="nav-link" routerLinkActive="active" [routerLink]="['/payroll-log']">
<i class="icon-basket"></i> Payroll Log
</a>
</li>
</ul>
</nav>
</div>

View file

@ -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() {

View file

@ -7,11 +7,10 @@ import { Location } from '@angular/common';
export class P404Component {
constructor(
private location: Location
) {
}
private location: Location,
) { }
goBack(): void {
this.location.back();
}
}
}

View file

@ -7,11 +7,10 @@ import { Location } from '@angular/common';
export class P500Component {
constructor(
private location: Location
) {
}
private location: Location,
) { }
goBack(): void {
this.location.back();
}
}
}

View file

@ -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;

View file

@ -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
)
);
}
}

View file

@ -10,6 +10,7 @@ interface OrgData {
}
@Component({
// tslint:disable-next-line
selector: 'org-table',
templateUrl: 'org-table.component.html',
})

View file

@ -0,0 +1,3 @@
<td>{{payrollDate}}</td>
<td>{{payroll.gross_payroll | currency:'GBP':true:'1.2-2' }}</td>
<td>{{payroll.employee_amount}}</td>

View file

@ -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');
}
}

View file

@ -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',
})

View file

@ -0,0 +1,2 @@
ײֶ<67><D7B0>^f^ױ<>jA<6A>Fמ£†ֳ₪י$<24>אQםhֿ0<D6BF>L•+l™<6C>Dבג)9;
@¾&;q<>ƒט ©<C2A0>׀ iEֻײץֱװ0ו#ׂ¡<D782>ְְֵ<D6B0>׳bK<62>װס<D7B0>7<EFBFBD>U¦%¸x<C2B8>_x/6m‡=P <0C>q‡¶F™A$|װײ'Aט£½b1ױ<31><32>~הג/,אd¡×זLֲ”P<05>¢>S L

View file

@ -1,4 +0,0 @@
export const environment = {
production: true,
apiUrl: 'https://app.peartrade.org/api'
};

View file

@ -5,5 +5,6 @@
export const environment = {
production: false,
apiUrl: 'https://dev.peartrade.org/api'
apiUrl: 'https://dev.peartrade.org/api',
mapApiKey: 'CHANGEME',
};

View file

@ -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;