Added Astute Client Files

In the AstuteClient2 folder
This commit is contained in:
Akash Shah 2018-08-15 14:33:03 -04:00 committed by GitHub
parent 6000ecdef9
commit 3554518563
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 14187 additions and 0 deletions

27
AstuteClient2/README.md Normal file
View File

@ -0,0 +1,27 @@
# AstuteClient2
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.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|guard|interface|enum|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/).
## 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).

122
AstuteClient2/angular.json Normal file
View File

@ -0,0 +1,122 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"AstuteClient2": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/AstuteClient2",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "AstuteClient2:build"
},
"configurations": {
"production": {
"browserTarget": "AstuteClient2:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "AstuteClient2:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.css"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"AstuteClient2-e2e": {
"root": "e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "AstuteClient2:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "AstuteClient2"
}

View File

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@ -0,0 +1,14 @@
import { AppPage } from './app.po';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});

View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

10647
AstuteClient2/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
{
"name": "astute-client2",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^6.0.2",
"@angular/common": "^6.0.2",
"@angular/compiler": "^6.0.2",
"@angular/core": "^6.0.2",
"@angular/forms": "^6.0.2",
"@angular/http": "^6.0.2",
"@angular/platform-browser": "^6.0.2",
"@angular/platform-browser-dynamic": "^6.0.2",
"@angular/router": "^6.0.2",
"@ng-bootstrap/ng-bootstrap": "^2.2.1",
"ag-grid": "^18.1.2",
"ag-grid-angular": "^18.1.0",
"bootstrap": "^4.1.3",
"core-js": "^2.5.4",
"jquery": "^3.3.1",
"popper.js": "^1.14.3",
"rxjs": "^6.0.0",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular/compiler-cli": "^6.0.2",
"@angular-devkit/build-angular": "~0.6.3",
"typescript": "~2.7.2",
"@angular/cli": "~6.0.3",
"@angular/language-service": "^6.0.2",
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"codelyzer": "~4.2.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~1.7.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~1.4.2",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.3.0",
"ts-node": "~5.0.1",
"tslint": "~5.9.1"
}
}

View File

@ -0,0 +1,15 @@
.box {
height: 130px;
width: 348px;
cursor: pointer;
transition: 200ms ease;
}
.box:hover {
box-shadow: 3px 3px 10px lightgrey;
transform: translateX(-3px) translateY(-3px);
transition: 300ms ease;
}

View File

@ -0,0 +1,38 @@
<!--<div class="card card-stats box">-->
<!--<div class="card-header card-header-icon" style="text-align: left">-->
<!--<div class="card-icon" [style.background-color]="color">-->
<!--<i class="material-icons">{{symbol}}</i>-->
<!--</div>-->
<!--<h3 class="card-title">{{name}}</h3>-->
<!--</div>-->
<!--<div class="card-footer">-->
<!--<div class="stats">-->
<!---->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<div class="card box text-light" [style.background-color]="color">
<div class="card-header">
<div class="container-fluid">
<div class="row">
<div class="col-2 text-left">
<i class="material-icons">{{symbol}}</i>
</div>
<div class="col-10 text-right">
<h5 class="card-title">{{name}}</h5>
</div>
</div>
</div>
</div>
<div class="card-body">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ng-content></ng-content>
</div>
</div>
</div>
<!--<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>-->
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AppBoxComponent } from './app-box.component';
describe('AppBoxComponent', () => {
let component: AppBoxComponent;
let fixture: ComponentFixture<AppBoxComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AppBoxComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppBoxComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,37 @@
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-app-box',
templateUrl: './app-box.component.html',
styleUrls: ['./app-box.component.css']
})
export class AppBoxComponent implements OnInit {
@Input() name;
@Input() symbol;
@Input() description;
@Input() color;
constructor() { }
ngOnInit() {
this.color = this.getColor();
}
getColor() {
if (this.color) {
return this.color;
} else {
const clr = this.padStart(Math.floor((Math.random() * 16777215)).toString(16), 6, '0');
return '#' + clr;
}
}
padStart(str: string, l: number, append: string) {
let len = str.length;
while (len < l) {
str = append + str;
len = str.length;
}
return str;
}
}

View File

@ -0,0 +1,13 @@
import { AppRoutingModule } from './app-routing.module';
describe('AppRoutingModule', () => {
let appRoutingModule: AppRoutingModule;
beforeEach(() => {
appRoutingModule = new AppRoutingModule();
});
it('should create an instance', () => {
expect(appRoutingModule).toBeTruthy();
});
});

View File

@ -0,0 +1,25 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {RouterModule, Routes} from '@angular/router';
import {CustomerComponent} from './customer/customer.component';
import {SalesOrderComponent} from './sales-order/sales-order.component';
import {InvoiceComponent} from './invoice/invoice.component';
import {HomepageComponent} from './homepage/homepage.component';
const routes: Routes = [
{ path: '', redirectTo: 'homepage', pathMatch: 'full'},
{ path: 'homepage', component: HomepageComponent },
{ path: 'customer', component: CustomerComponent },
{ path: 'sales-order', component: SalesOrderComponent },
{ path: 'invoice', component: InvoiceComponent }
];
@NgModule({
exports: [RouterModule],
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
declarations: []
})
export class AppRoutingModule { }

View File

@ -0,0 +1 @@
<router-outlet></router-outlet>

View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to AstuteClient2!');
}));
});

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
}

View File

@ -0,0 +1,39 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CustomerComponent } from './customer/customer.component';
import { AstuteClientService } from './services/astute-client-service';
import { AgGridModule } from 'ag-grid-angular';
import { ModalFormComponent } from './modal-form/modal-form.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import {HttpClientModule} from '@angular/common/http';
import { AppRoutingModule } from './/app-routing.module';
import { NavBarComponent } from './nav-bar/nav-bar.component';
import { SalesOrderComponent } from './sales-order/sales-order.component';
import { InvoiceComponent } from './invoice/invoice.component';
import { HomepageComponent } from './homepage/homepage.component';
import { AppBoxComponent } from './app-box/app-box.component';
@NgModule({
declarations: [
AppComponent,
CustomerComponent,
ModalFormComponent,
NavBarComponent,
SalesOrderComponent,
InvoiceComponent,
HomepageComponent,
AppBoxComponent
],
imports: [
BrowserModule,
AgGridModule.withComponents([]),
NgbModule.forRoot(),
HttpClientModule,
AppRoutingModule
],
providers: [AstuteClientService],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -0,0 +1,271 @@
<app-nav-bar [customerActive]="true"></app-nav-bar>
<h1 align="center">Customers</h1>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
#agGrid
style="height: 500px;"
class="ag-theme-balham"
[enableSorting]="true"
[enableFilter]="true"
[rowData]="rowData | async"
[columnDefs]="columnDefs"
rowSelection="single"
></ag-grid-angular>
</div>
</div>
<div class="row justify-content-center mt-2">
<div class="col-6">
<button class="btn btn-primary" style="width: 100%" (click)="open(edit)">Edit Customer</button>
</div>
<div class="col-6">
<button class="btn btn-success" style="width: 100%" (click)="open(new)">Add Customer</button>
</div>
</div>
</div>
<!--MODAL: new customer-->
<app-modal-form [title]="'New Customer'" #new>
<div class="modal-body">
<table class="table table-borderless table-sm">
<tbody>
<tr>
<td style="width: 10%">
<span class="input-group-text">ID*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inId>
</td>
</tr>
<tr>
<td style="width: 10%">
<span class="input-group-text">Name*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inName>
</td>
</tr>
<tr>
<td style="width: 10%">
<span class="input-group-text">Bill To Dept*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inBillToDept>
</td>
</tr>
<tr>
<td style="width: 10%">
<span class="input-group-text">Address 1*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inAdd1>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Address 2</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inAdd2>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">City*</span>
</td>
<td>
<input type="text" class="form-control" #inCity>
</td>
<td style="width: 1%">
<span class="input-group-text">State*</span>
</td>
<td>
<select class="custom-select" #inState>
<option selected>Choose...</option>
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</td>
<td style="width: 1%">
<span class="input-group-text">ZIP*(+4)</span>
</td>
<td style="width: 25%">
<div class="input-group">
<input type="number" class="form-control" #inZIP>
<input type="number" class="form-control" #inZIP4>
</div>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Email*</span>
</td>
<td colspan="7">
<input type="email" class="form-control" #inEmail>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Phone*</span>
</td>
<td colspan="7">
<input type="tel" class="form-control" #inPhone>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Fax*</span>
</td>
<td colspan="7">
<input type="tel" class="form-control" #inFax>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-success" type="button"
[disabled]="!(inId.value && inName.value && inBillToDept.value && inAdd1.value && inCity.value && inState.value && inZIP.value && inEmail.value && inPhone.value && inFax.value)"
(click)="addCustomer(inId.value, inName.value, inBillToDept.value, inAdd1.value, inAdd2.value, inCity.value, inState.value, inZIP.value, inZIP4.value, inEmail.value, inPhone.value, inFax.value, new)">
+
</button>
<button type="button" class="btn btn-danger" (click)="close(new)">Cancel</button>
</div>
</app-modal-form>
<!--MODAL: edit customer-->
<app-modal-form [title]="'Editing'" #edit>
<div *ngIf="selected">
<div class="modal-body">
<table class="table table-borderless table-sm">
<tbody>
<tr>
<td style="width: 10%">
<span class="input-group-text">Name*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inName [value]="selected.customerName">
</td>
</tr>
<tr>
<td style="width: 10%">
<span class="input-group-text">Bill To Dept*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inBillToDept [value]="selected.billToDept">
</td>
</tr>
<tr>
<td style="width: 10%">
<span class="input-group-text">Address 1*</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inAdd1 [value]="selected.add1">
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Address 2</span>
</td>
<td colspan="7">
<input type="text" class="form-control" #inAdd2 [value]="selected.add2">
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">City*</span>
</td>
<td>
<input type="text" class="form-control" #inCity [value]="selected.city">
</td>
<td style="width: 1%">
<span class="input-group-text">State*</span>
</td>
<td>
<select class="custom-select" #inState [value]="selected.state">
<option selected>Choose...</option>
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</td>
<td style="width: 1%">
<span class="input-group-text">ZIP*(+4)</span>
</td>
<td style="width: 25%">
<div class="input-group">
<input type="number" class="form-control" #inZIP [value]="selected.zip">
<input type="number" class="form-control" #inZIP4 [value]="selected.ziplast4">
</div>
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Email*</span>
</td>
<td colspan="7">
<input type="email" class="form-control" #inEmail [value]="selected.email">
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Phone*</span>
</td>
<td colspan="7">
<input type="tel" class="form-control" #inPhone [value]="selected.phone">
</td>
</tr>
<tr>
<td style="width: 1%">
<span class="input-group-text">Fax*</span>
</td>
<td colspan="7">
<input type="tel" class="form-control" #inFax [value]="selected.fax">
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-warning" type="button"
[disabled]="!(inName.value && inBillToDept.value && inAdd1.value && inCity.value && inState.value && inZIP.value && inEmail.value && inPhone.value && inFax.value)"
(click)="editCustomer(selected.customerId ,inName.value, inBillToDept.value, inAdd1.value, inAdd2.value, inCity.value, inState.value, inZIP.value, inZIP4.value, inEmail.value, inPhone.value, inFax.value, edit)">
Update
</button>
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
<div *ngIf="!selected">
<div class="modal-body">
Choose a Customer First!
</div>
<div class="modal-footer">
<button class="btn btn-warning" type="button"
[disabled]="true">
Update
</button>
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
</app-modal-form>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CustomerComponent } from './customer.component';
describe('CustomerComponent', () => {
let component: CustomerComponent;
let fixture: ComponentFixture<CustomerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CustomerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CustomerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,170 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {AstuteClientService} from '../services/astute-client-service';
@Component({
selector: 'app-customer',
templateUrl: './customer.component.html',
styleUrls: ['./customer.component.css']
})
export class CustomerComponent implements OnInit {
@ViewChild('agGrid') agGrid;
selected = null;
customers;
columnDefs = [
{headerName: 'Customer ID', field: 'customerId', checkboxSelection: true},
{headerName: 'Customer Name', field: 'customerName'},
{headerName: 'Bill To Department', field: 'billToDept'},
{headerName: 'Address 1', field: 'add1'},
{headerName: 'Address 2', field: 'add2'},
{headerName: 'City', field: 'city'},
{headerName: 'Email', field: 'email'},
{headerName: 'Fax', field: 'fax'},
{headerName: 'Phone', field: 'phone'},
{headerName: 'State', field: 'state'},
{headerName: 'ZIP', field: 'zip'},
{headerName: 'ZIP-4', field: 'ziplast4'}
];
rowData: any;
states = [
'AL',
'AK',
'AR',
'AZ',
'CA',
'CO',
'CT',
'DC',
'DE',
'FL',
'GA',
'HI',
'IA',
'ID',
'IL',
'IN',
'KS',
'KY',
'LA',
'MA',
'MD',
'ME',
'MI',
'MN',
'MO',
'MS',
'MT',
'NC',
'NE',
'NH',
'NJ',
'NM',
'NV',
'NY',
'ND',
'OH',
'OK',
'OR',
'PA',
'RI',
'SC',
'SD',
'TN',
'TX',
'UT',
'VT',
'VA',
'WA',
'WI',
'WV',
'WY'
];
constructor(protected astuteClientService: AstuteClientService) {
}
ngOnInit() {
this.refreshData();
}
getSelectedRows() {
const selectedNodes = this.agGrid.api.getSelectedNodes();
if (selectedNodes.length) {
this.selected = selectedNodes.map( node => node.data )[0];
} else {
this.selected = null;
}
}
// inName.value, inBillToDept.value, inAdd1.value, inAdd2.value, inCity.value, inState.value, inZIP.value, inZIP4.value, inEmail.value, inPhone.value, inFax.value
addCustomer(customerId, name, billTo, add1, add2, city, state, zip, zip4, email, phone, fax, ref) {
let customerData = {
"customerId":customerId,
"customerName":name,
"billToDept":billTo,
"add1":add1,
"add2":add2,
"city":city,
"state":state,
"zip":zip,
"ziplast4":zip4,
"email":email,
"phone":phone,
"fax":fax
};
this.astuteClientService.createCustomer(customerData).then((data) => {
if (data) {
this.refreshData();
ref.close();
} else {
alert ("Customer Creation Failed, Check Input Fields")
}
},(reason) => {
alert("add customer failed for " + reason);
});
}
editCustomer(id, name, billTo, add1, add2, city, state, zip, zip4, email, phone, fax, ref) {
const customerData = {
"customerId": id,
"customerName":name,
"billToDept":billTo,
"add1":add1,
"add2":add2,
"city":city,
"state":state,
"zip":zip,
"ziplast4":zip4,
"email":email,
"phone":phone,
"fax":fax
};
this.astuteClientService.updateCustomer(id, customerData).then((data) => {
if (data) {
this.refreshData();
ref.close();
} else {
alert ("Customer Updating Failed, Check Input Fields")
}
},(reason) => {
alert("update customer failed for " + reason);
});
}
open(ref) {
this.getSelectedRows();
ref.open();
}
close(ref) {
ref.close();
}
refreshData () {
this.rowData = this.astuteClientService.getCustomers();
this.astuteClientService.getCustomers().then((data) => {
this.customers = data;
});
}
}

View File

@ -0,0 +1,26 @@
.top-buffer {
margin-top:20px;
}
.sep-buffer {
margin-top:20px;
}
.app-buffer {
margin-right:20px;
margin-left:20px;
padding: auto 0;
}
/*.custom-bg {*/
/*!* The image used *!*/
/*background-image: url("bg.png");*/
/*!* Full height *!*/
/*height: 100%;*/
/*!* Center and scale the image nicely *!*/
/*background-position: center;*/
/*background-repeat: no-repeat;*/
/*background-size: cover;*/
/*}*/

View File

@ -0,0 +1,69 @@
<app-nav-bar></app-nav-bar>
<div>
<div class="container">
<!--welcome message and search bar-->
<div class="row top-buffer align-items-center">
<div class="col-lg-8">
<h1 class="display-4" *ngIf="currentUser">
Welcome to the Astute Internal System, {{currentUser}}!
</h1>
</div>
<div class="col-lg-4">
<div class="input-group mb-3 float-right">
<input type="text" class="form-control" placeholder="Search...">
<div class="input-group-prepend">
<button class="btn btn-sm btn-info btn-round">
<i class="material-icons">search</i>
</button>
</div>
</div>
</div>
</div>
<!--applications-->
<div>
<div class="row sep-buffer">
<div class="col-12">
<h3>
Applications
</h3>
</div>
</div>
<div class="row">
<app-app-box class="m-3" [color]="'#00bcd4'" [name]="'Customer'" [symbol]="'supervised_user_circle'" routerLink="/customer">
<h6 class="card-subtitle mb-2 text-muted">Go here to add or edit customers</h6>
<!--<i class="material-icons text-info">info</i> -->
</app-app-box>
<app-app-box class="m-3" [color]="'#f44336'" [name]="'Sales Order'" [symbol]="'assignment'" routerLink="/sales-order">
<h6 class="card-subtitle mb-2 text-muted">Go here to add sales orders or make change orders</h6>
<!--<i class="material-icons text-info">info</i> Medical Records Application-->
</app-app-box>
<app-app-box class="m-3" [color]="'#4caf50'" [name]="'Invoice'" [symbol]="'view_headline'" routerLink="/invoice">
<h6 class="card-subtitle mb-2 text-muted">Go here to interact with invoices</h6>
<!--<i class="material-icons text-danger">info</i> Not yet implemented-->
</app-app-box>
<app-app-box class="m-3" [name]="'Invoice Payment'" [symbol]="'attach_money'" routerLink="/invoice-payment">
<h6 class="card-subtitle mb-2 text-muted">Go here to to pay an invoice</h6>
<!--<i class="material-icons text-danger">info</i> Not yet implemented-->
</app-app-box>
</div>
</div>
<!--Some Extra Info-->
<div>
<div class="row sep-buffer">
<div class="col-12">
<h3>
Extra info section
</h3>
</div>
</div>
<div class="row top-buffer justify-content-start">
<h5 class="app-buffer">
Some sort of info here, maybe about recent invoices, or upcoming payment due dates.<br>
Maybe something for each users tasks...
</h5>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomepageComponent } from './homepage.component';
describe('HomepageComponent', () => {
let component: HomepageComponent;
let fixture: ComponentFixture<HomepageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomepageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomepageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,22 @@
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.css']
})
export class HomepageComponent implements OnInit {
currentUser: any = {};
constructor() {
}
ngOnInit() {
this.currentUser = this.getSessionUser();
console.log(this.currentUser);
}
private getSessionUser() {
return localStorage.getItem('SESSION_USER');
}
}

View File

@ -0,0 +1,14 @@
.cell {
height: 100%;
width: 100%;
background-color: white;
border-radius: 0px;
border-width: 0px;
/*margin: 0px;*/
/*padding: 0;*/
/*overflow-x: auto;*/
}
.cell:focus {
outline: none;
}

View File

@ -0,0 +1,383 @@
<app-nav-bar [invoiceActive]="true"></app-nav-bar>
<h1 align="center">Invoices</h1>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
#agGrid
style="height: 500px;"
class="ag-theme-balham"
[gridOptions]="gridOptions"
[enableSorting]="true"
[enableFilter]="true"
[rowData]="source"
[columnDefs]="columnDefs"
rowSelection="single"
rowDeselection="true"
></ag-grid-angular>
</div>
</div>
<div class="row justify-content-center mt-2">
<div class="col-2">
<button class="btn btn-light" style="width: 100%" (click)="open(edit)" [disabled]="!chosenInv">Print</button>
</div>
<div class="col-2">
<button class="btn btn-primary" style="width: 100%" (click)="submitInvoice(chosenInv.invoiceNumber)"
[disabled]="!chosenInv">Submit
</button>
</div>
<div class="col-2">
<button class="btn btn-secondary" style="width: 100%" (click)="open(new)" [disabled]="!chosenInv">Payment
Received
</button>
</div>
<div class="col-2">
<button class="btn btn-warning" style="width: 100%" (click)="voidInvoice(chosenInv.invoiceNumber)"
[disabled]="!chosenInv">Void
</button>
</div>
<div class="col-2">
<button class="btn btn-info" style="width: 100%" (click)="open(edit)" [disabled]="!chosenInv">Edit</button>
</div>
<div class="col-2">
<button class="btn btn-success" style="width: 100%" (click)="open(new)">Add</button>
</div>
</div>
</div>
<!--<div class="container-fluid">-->
<!--<div class="row">-->
<!--<table class="table table-striped">-->
<!--<thead>-->
<!--<tr>-->
<!--<th scope="col" *ngFor="let col of columns">{{col}}</th>-->
<!--</tr>-->
<!--</thead>-->
<!--<tbody>-->
<!--&lt;!&ndash;'Actions',&ndash;&gt;-->
<!--&lt;!&ndash;'Invoice Number',&ndash;&gt;-->
<!--&lt;!&ndash;'Invoice Date',&ndash;&gt;-->
<!--&lt;!&ndash;'Purchase Order Number',&ndash;&gt;-->
<!--&lt;!&ndash;'Change Order Number',&ndash;&gt;-->
<!--&lt;!&ndash;'Payment Status',&ndash;&gt;-->
<!--&lt;!&ndash;'Bill Amount',&ndash;&gt;-->
<!--<tr *ngFor="let invoice of source; let i = index">-->
<!--<th scope="row">{{i + 1}}</th>-->
<!--<td>-->
<!--<button class="btn btn-sm btn-outline-warning" (click)="open(edit, null, i)">Edit</button>-->
<!--<button class="btn btn-sm btn-outline-primary" (click)="assignActity()">Print</button>-->
<!--<button class="btn btn-sm btn-outline-primary" (click)="assignActity()">Submit</button>-->
<!--</td>-->
<!--<td>{{invoice.invoiceNumber}}</td>-->
<!--<td>{{invoice.invoiceDate}}</td>-->
<!--<td>{{invoice.poNum}}</td>-->
<!--<td>{{invoice.changeOrderNum}}</td>-->
<!--<td>{{invoice.pmtStatus ? "Paid" : "Not Paid"}}</td>-->
<!--<td><span>$</span>{{invoice.billAmt}}</td>-->
<!--</tr>-->
<!--</tbody>-->
<!--</table>-->
<!--</div>-->
<!--<div class="row">-->
<!--&lt;!&ndash;<div class="col-xs-6">&ndash;&gt;-->
<!--<div class="input-group">-->
<!--<div class="input-group-prepend">-->
<!--<span class="input-group-text">Customer</span>-->
<!--</div>-->
<!--<select class="custom-select" (change)="dropdownChange(customerSelec.value)" #customerSelec>-->
<!--<option>Choose Customer...</option>-->
<!--<option *ngFor="let customer of customers; let i = index;" [value]="i">{{customer.customerName}}</option>-->
<!--</select>-->
<!--<div class="input-group-prepend">-->
<!--<span class="input-group-text">Purchase Order Number</span>-->
<!--</div>-->
<!--<select class="custom-select" #poSelec>-->
<!--<option *ngFor="let po of getCorrespondingPos(); let i = index;" [value]="i">{{po.ponum}}</option>-->
<!--</select>-->
<!--<div class="input-group-append">-->
<!--<button class="btn btn-outline-success" type="button" [disabled]="!(customerSelec.value && poSelec.value)"-->
<!--(click)="open(new, poSelec.options[poSelec.selectedIndex].value)">Add-->
<!--</button>-->
<!--</div>-->
<!--</div>-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--</div>-->
<!--</div>-->
<!--MODAL: edit Invoice-->
<app-modal-form [title]="'Edit Invoice'" #edit>
<!--General-->
<div class="modal-body" *ngIf="chosenInv">
<p class="h4 text-right">General</p>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Invoice Number*</span>
</div>
<input type="text" class="form-control" #inNumIn [value]="chosenInv.invoiceNumber">
<div class="input-group-prepend">
<span class="input-group-text">PO Number*</span>
</div>
<input type="text" class="form-control" [disabled]="true" #poNumIn [value]="chosenInv.poNum">
<div class="input-group-prepend">
<span class="input-group-text">Change Order Num</span>
</div>
<input type="text" class="form-control" #coNumIn [value]="chosenInv.changeOrderNum">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Payment Status*</span>
</div>
<select class="custom-select" [value]="chosenInv.pmtStatus" #pmtStatusIn>
<option value=0>Not Paid</option>
<option value=1>Paid</option>
</select>
</div>
</div>
<!--Detials-->
<div class="modal-body" *ngIf="chosenInv">
<p class="h4 text-right">Detail</p>
<table class="table">
<thead>
<tr >
<th scope="col" style="width: 50px">#</th>
<th scope="col">Description</th>
<th scope="col" style="width: 150px">Fee Type</th>
<th scope="col" style="width: 100px">Fee</th>
<th scope="col" style="width: 100px">Quantity</th>
</tr>
</thead>
<!--<tbody>-->
<tbody *ngFor="let inDet of selectedInDetails; let i = index">
<tr class="p-0 m-0">
<!--INV Detail Items: invoiceNum, lineItemNum, poLineItemNum, serviceTypeId, desc, qty, fee-->
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="inDet.lineItemNum" disabled></td>
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="inDet.desc" (change)="onNewCellChange(i, 'desc', desc.value)" #desc></td>
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="feeTypes[inDet.feeTypeId - 1]" disabled></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="inDet.fee" (change)="onNewCellChange(i, 'fee', fee.value); updateNewBillAmt();" #fee></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="inDet.qty" (change)="onNewCellChange(i, 'qty', qty.value); updateNewBillAmt();" #qty></td>
</tr>
<tr class="p-0 m-0">
<th class="align-content-center">
<p>{{getPerc(fee.value * qty.value, inDet.remainingQty)}}%</p>
</th>
<td colspan="4">
<div class="progress" style="height: 25px;">
<div class="progress-bar bg-success" role="progressbar"
[ngStyle]="{'width': getPerc(fee.value * qty.value, inDet.remainingQty) + '%'}">${{fee.value * qty.value}}
</div>
<div class="progress-bar bg-danger" role="progressbar"
[ngStyle]="{'width': (100 - getPerc(fee.value * qty.value, inDet.remainingQty)) + '%'}">${{inDet.remainingQty - (fee.value * qty.value)}}
</div>
</div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="5">
<select class="custom-select"
(change)="pushOntoSelectedDetail(inNumIn.value, newInDetails.length + 1, selectedPODetails[poDetSelec.value].lineItemNo,
selectedPODetails[poDetSelec.value].feeTypeId, selectedPODetails[poDetSelec.value].serviceTypeId,
selectedPODetails[poDetSelec.value].serviceDesc, 1, 0, selectedPODetails[poDetSelec.value].remainingQty)"
[disabled]="!selectedPODetails.length"
#poDetSelec>
<option>Choose PO Detail...</option>
<option *ngFor="let po of selectedPODetails; let i = index;" [value]="i">{{po.serviceDesc}}</option>
</select>
</td>
</tr>
</tbody>
</table>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Bill Amount*</span>
<span class="input-group-text">$</span>
</div>
<input type="number" class="form-control" [value]="selectedBillAmt" #billAmtIn>
<div class="input-group-append">
<span class="input-group-text">.00</span>
</div>
</div>
</div>
<!--Footer-->
<div class="modal-body" *ngIf="chosenInv">
<p class="h4 text-right">Footer</p>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Special Notes*</span>
</div>
<textarea class="form-control" [value]="chosenInv.specialNotes" #notesIn></textarea>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Certification*</span>
</div>
<textarea class="form-control" [value]="chosenInv.certification" #certIn></textarea>
</div>
</div>
<!--Select Invoice Message-->
<div class="modal-body" *ngIf="!chosenInv">
<p>Choose an Invoice First!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success"
(click)="editInvoice(inNumIn.value, poNumIn.value, coNumIn.value, pmtStatusIn.value, notesIn.value, certIn.value)"
[disabled]="!(inNumIn.value && poNumIn.value && pmtStatusIn.value && notesIn.value && certIn.value)">Confirm
</button>
<button type="button" class="btn btn-danger" (click)="close(edit)">Cancel</button>
</div>
</app-modal-form>
<!--MODAL: new invoice-->
<app-modal-form [title]="'New Invoice'" #new>
<div class="modal-body">
<p class="h4 text-right">General</p>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Customer</span>
</div>
<select class="custom-select" (change)="customerDropdownChange(customerSelec.value)" #customerSelec>
<option>Choose Customer...</option>
<option *ngFor="let customer of customers; let i = index;" [value]="i">{{customer.customerName}}</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">SO Number*</span>
</div>
<select class="custom-select" (change)="poDropdownChange(poNumIn.value)" [disabled]="!correspondingPos.length" #poNumIn>
<option>Choose Sales Order...</option>
<option *ngFor="let po of correspondingPos;" [value]="po.ponum">{{po.ponum}}</option>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Invoice Number*</span>
</div>
<input type="text" class="form-control" [value]="generatedInvoiceNumber" #inNumIn disabled>
<div class="input-group-prepend">
<span class="input-group-text">Change Order Num</span>
</div>
<input type="text" class="form-control" #coNumIn>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Payment Status*</span>
</div>
<select class="custom-select" #pmtStatusIn>
<option value=0>Not Paid</option>
<option value=1>Paid</option>
</select>
</div>
</div>
<!--Detail-->
<div class="modal-body">
<p class="h4 text-right">Detail</p>
<table class="table">
<thead>
<tr >
<th scope="col" style="width: 50px">#</th>
<th scope="col">Description</th>
<th scope="col" style="width: 150px">Fee Type</th>
<th scope="col" style="width: 100px">Fee</th>
<th scope="col" style="width: 100px">Quantity</th>
</tr>
</thead>
<!--<tbody>-->
<tbody *ngFor="let inDet of newInDetails; let i = index">
<tr class="p-0 m-0">
<!--INV Detail Items: invoiceNum, lineItemNum, poLineItemNum, serviceTypeId, desc, qty, fee-->
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="inDet.lineItemNum" disabled></td>
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="inDet.desc" (change)="onNewCellChange(i, 'desc', desc.value)" #desc></td>
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="feeTypes[inDet.feeTypeId - 1]" disabled></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="inDet.fee" (change)="onNewCellChange(i, 'fee', fee.value); updateNewBillAmt();" #fee></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="inDet.qty" (change)="onNewCellChange(i, 'qty', qty.value); updateNewBillAmt();" #qty></td>
</tr>
<tr class="p-0 m-0">
<th class="align-content-center">
<p>{{getPerc(fee.value * qty.value, inDet.remainingQty)}}%</p>
</th>
<td colspan="4">
<div class="progress" style="height: 25px;">
<div class="progress-bar bg-success" role="progressbar"
[ngStyle]="{'width': getPerc(fee.value * qty.value, inDet.remainingQty) + '%'}">${{fee.value * qty.value}}
</div>
<div class="progress-bar bg-danger" role="progressbar"
[ngStyle]="{'width': (100 - getPerc(fee.value * qty.value, inDet.remainingQty)) + '%'}">${{inDet.remainingQty - (fee.value * qty.value)}}
</div>
</div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="5">
<select class="custom-select"
(change)="pushOntoNewDetail(inNumIn.value, newInDetails.length + 1, poDetails[poDetSelec.value].lineItemNo,
poDetails[poDetSelec.value].feeTypeId, poDetails[poDetSelec.value].serviceTypeId,
poDetails[poDetSelec.value].serviceDesc, 1, 0, poDetails[poDetSelec.value].remainingQty)"
[disabled]="!poDetails.length"
#poDetSelec>
<option>Choose PO Detail...</option>
<option *ngFor="let po of poDetails; let i = index;" [value]="i">{{po.serviceDesc}}</option>
</select>
</td>
</tr>
</tbody>
</table>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Bill Amount*</span>
<span class="input-group-text">$</span>
</div>
<input type="number" class="form-control" [value]="newBillAmt" #billAmtIn disabled>
<div class="input-group-append">
<span class="input-group-text">.00</span>
</div>
</div>
</div>
<div class="modal-body">
<p class="h4 text-right">Footer</p>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Special Notes*</span>
</div>
<textarea class="form-control" #notesIn></textarea>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Certification*</span>
</div>
<textarea class="form-control"
[value]="'Certified that the above items and rates are in accordance with the contractual agreement as verified by the undersigned'"
#certIn></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success"
(click)="addInvoice(inNumIn.value, poNumIn.value, coNumIn.value, pmtStatusIn.value, billAmtIn.value, notesIn.value, certIn.value, 1, new)"
[disabled]="!(inNumIn.value && poNumIn.value && pmtStatusIn.value && billAmtIn.value && notesIn.value && certIn.value)">
Confirm
</button>
<button type="button" class="btn btn-danger" (click)="close(new)">Cancel</button>
</div>
</app-modal-form>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InvoiceComponent } from './invoice.component';
describe('InvoiceComponent', () => {
let component: InvoiceComponent;
let fixture: ComponentFixture<InvoiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InvoiceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(InvoiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,375 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import {AstuteClientService} from '../services/astute-client-service';
@Component({
selector: 'app-invoice',
templateUrl: './invoice.component.html',
styleUrls: ['./invoice.component.css']
})
export class InvoiceComponent implements OnInit {
@ViewChild('agGrid') agGrid;
chosenCustomerID: any = 0;
chosenInv: any = 0;
source;
customers;
pos = [];
correspondingPos = [];
generatedInvoiceNumber = '';
feeTypes = ['Fixed Fee', 'Hourly'];
serviceTypes = ['Study', 'Design', 'Peer Review', 'Cost Investigation', 'Forensic Investigation'];
columnDefs = [
{headerName: 'Invoice Number', field: 'invoiceNumber'},
{headerName: 'Date', field: 'invoiceDate'},
{headerName: 'Sales Order Number', field: 'poNum'},
{headerName: 'Change Order Number', field: 'changeOrderNum'},
{headerName: 'Paid', field: 'pmtStatus'},
{headerName: 'Bll Amount', field: 'billAmt'}
];
newInDetails = [];
newBillAmt;
selectedInDetails = [];
selectedBillAmt;
poDetails = [];
selectedPODetails = [];
gridOptions = {
// PROPERTIES - object properties, myRowData and myColDefs are created somewhere in your application
rowData: this.source,
columnDefs: this.columnDefs,
// PROPERTIES - simple boolean / string / number properties
enableColResize: true,
rowSelection: 'single',
// EVENTS - add event callback handlers
onRowClicked: (event) => { this.getSelectedRows() },
onColumnResized: function(event) { console.log('a column was resized'); },
onGridReady: (event) => {},
// this.agGrid.sizeColumnsToFit();
// 1: draft
// 2: submitted
// 3: void
// getRowStyle: function(params) {
// if (params.data.invoiceStatus === 1) {
// return { 'color': 'red' }
// } else if (params.data.invoiceStatus === 3) {
// return { 'text-decoration': 'line-through'}
// }
// }
rowClassRules: {
// apply green to 2008
// 'bg-red': true,
// apply amber 2004
'text-danger': function(params) { return params.data.invoiceStatus === 1},
'text-primary': function(params) { return params.data.invoiceStatus === 2},
'text-warning': function(params) { return params.data.invoiceStatus === 3},
// apply red to 2000
// 'rag-red-outer': function(params) { return params.data.year === 2000}
}
}
constructor(protected astuteClientService: AstuteClientService) {
}
customerDropdownChange(index) {
this.chosenCustomerID = this.customers[index].customerId;
this.setCorrespondingPos();
}
poDropdownChange(ponum) {
this.astuteClientService.getPODetail(ponum).then((data) => {
if (data) {
// fee
// feeTypeId
// lineItemNo
// ponum
// qty
// remainingQty
// serviceDesc
// serviceTypeId
this.poDetails = data;
console.log(data);
} else {
alert("get PO detail failed!");
}
});
this.astuteClientService.generateInvoiceNumber(ponum).then((data) => {
if (data) {
this.generatedInvoiceNumber = data;
console.log (this.generatedInvoiceNumber);
} else {
alert('gen inv num failed!');
}
});
}
ngOnInit() {
this.refreshData();
}
refreshData () {
this.astuteClientService.getInvoices().then((data) => {
this.source = data;
});
this.astuteClientService.getCustomers().then ( (data) => {
this.customers = data;
});
this.astuteClientService.getPOs().then ( (data) => {
this.pos = data;
});
}
getPODetails (poIndex) {
let ponum = this.pos[poIndex].ponum;
this.astuteClientService.getPODetail(ponum).then ( (data) => {
this.selectedInDetails = data;
console.log ("inDetails:");
console.log (this.selectedInDetails);
});
}
onSelectedCellChange(row: number, col: string, value) {
this.selectedInDetails[row][col] = value;
console.log(this.selectedInDetails);
}
onNewCellChange(row: number, col: string, value) {
this.newInDetails[row][col] = value;
console.log(this.newInDetails);
}
pushOntoSelectedDetail(invoiceNum, lineItemNum, poLineItemNum, serviceTypeId, desc, qty, fee) {
this.selectedInDetails.push({
'invoiceNum': invoiceNum,
'lineItemNum': lineItemNum,
'poLineItemNum': poLineItemNum,
'serviceTypeId': serviceTypeId,
'desc': desc,
'qty': qty,
'fee': fee,
});
}
pushOntoNewDetail(invoiceNum, lineItemNum, poLineItemNum, feeTypeId, serviceTypeId, desc, qty, fee, remainingQty) {
this.newInDetails.push({
'invoiceNum': invoiceNum,
'lineItemNum': lineItemNum,
'poLineItemNum': poLineItemNum,
'feeTypeId': feeTypeId,
'serviceTypeId': serviceTypeId,
'desc': desc,
'qty': +qty,
'fee': +fee,
'remainingQty' : +remainingQty
});
console.log(this.newInDetails);
}
updateNewBillAmt () {
let tot = 0;
this.newInDetails.forEach((d) => {
tot += parseInt(d.qty, 10) * parseInt(d.fee, 10);
});
this.newBillAmt = tot;
}
assignActity(): void {
window.open('/invoice-gen');
}
getSelectedRows() {
const selectedNodes = this.agGrid.api.getSelectedNodes();
if (selectedNodes.length) {
this.chosenInv = selectedNodes.map(node => node.data)[0];
console.log(this.chosenInv)
// console.log (this.chosenInv);
this.astuteClientService.getPODetail(this.chosenInv.ponum).then((poDetails) => {
if (poDetails) {
this.selectedPODetails = poDetails;
this.astuteClientService.getInvoiceDetail(this.chosenInv.invoiceNumber).then ((invoiceDetails) => {
if (invoiceDetails) {
this.selectedInDetails = invoiceDetails;
} else {
alert("get Inv detail failed!");
}
});
} else {
alert("get PO detail failed!")
}
});
} else {
this.chosenInv = null;
this.selectedPODetails = [];
}
}
open(content, indexPO, indexINV) {
content.open()
// this.detailDescription = ViewChild('detailDescription');
// this.detailAmount = ViewChild('detailAmount');
// this.detailRate = ViewChild('detailRate');
// this.detailTotal = ViewChild('detailTotal');
// if (indexINV) {
// this.chosenInv = indexINV;
// }
// if (indexPO) {
// this.chosenPo = indexPO;
// this.getPODetails(this.chosenPo);
// }
// this.modalService.open(content, { size: 'lg' }).result.then((result) => {
// this.closeResult = `Closed with: ${result}`;
// }, (reason) => {
// this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
// });
}
close(content) {
content.close();
}
getCurrDate() {
let d = new Date(),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return [year, month, day].join('-');
}
addInvoice(invoiceNumber, poNum, changeOrderNum, pmtStatus, billAmt, specialNotes, certification, status, ref) {
// String invoiceNumber;
// Date invoiceDate;
// String poNum;
// String changeOrderNum;
// int pmtStatus;
// Double billAmt;
// String specialNotes;
// String certification;
// Date pmtReceivedDate;
const invData = {
"invoiceNumber": invoiceNumber,
"invoiceDate": new Date(),
"poNum": poNum,
"changeOrderNum": changeOrderNum,
"pmtStatus": +pmtStatus,
"billAmt": +billAmt,
"specialNotes": specialNotes,
"certification": certification,
"pmtReceivedDate": new Date(),
'invoiceStatus': status
};
this.astuteClientService.createInvoice(invData)
.catch((response) => {
console.log("rejected: " + response);
})
.then((data) => {
if (data) {
this.refreshData();
this.addInvoiceDetail(this.newInDetails);
ref.close();
} else {
alert ("Invoice Creation Failed, Check Input Fields")
}
});
}
addInvoiceDetail(details) {
if (details.length) {
console.log(details[0]);
this.astuteClientService.createInvoiceDetail(details[0]).then((data) => {
if (data) {
details.splice(0, 1);
this.addInvoiceDetail(details);
} else {
alert("add inv detail failed");
}
});
} else {
this.newInDetails = [];
}
}
editInvoice(invoiceNumber, poNum, changeOrderNum, pmtStatus, billAmt, specialNotes, certification) {
// String invoiceNumber;
// Date invoiceDate;
// String poNum;
// String changeOrderNum;
// int pmtStatus;
// Double billAmt;
// String specialNotes;
// String certification;
// Date pmtReceivedDate;
const invData = {
"invoiceNumber": invoiceNumber,
"invoiceDate": new Date(),
"poNum": poNum,
"changeOrderNum": changeOrderNum,
"pmtStatus": +pmtStatus,
"billAmt": +billAmt,
"specialNotes": specialNotes,
"certification": certification,
"pmtReceivedDate": new Date()
};
this.astuteClientService.updateInvoice(invoiceNumber, invData)
.catch((response) => {
console.log("rejected: " + response);
})
.then((data) => {
if (data) {
alert("invoice " + invoiceNumber + " updated!");
console.log("fulfilled: " + data);
// this.source[this.chosenInv] = invData;
this.refreshData();
} else {
alert ("Invoice Update Failed, Check Input Fields")
}
});
}
voidInvoice(invoiceNumber) {
this.astuteClientService.voidInvoice(invoiceNumber).then ((data) => {
if (data) {
this.refreshData();
} else {
alert('void invoice failed.')
}
});
}
submitInvoice(invoiceNumber) {
this.astuteClientService.submitInvoice(invoiceNumber).then ((data) => {
if (data) {
this.refreshData();
} else {
alert('submit invoice failed.')
}
});
}
getPerc (amt, total): number {
return Math.floor(((amt) / total) * 100);
}
getRangeMax(total, num) {
return Math.floor (total/num);
}
setCorrespondingPos () {
this.correspondingPos = this.pos.filter((po, index, array) => {
return po.customerId == this.chosenCustomerID
});
}
}

View File

@ -0,0 +1,12 @@
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title">{{title}}</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<ng-content></ng-content>
<!--<div class="modal-footer">-->
<!--<button type="button" class="btn btn-outline-dark" (click)="c('Close click')">Close</button>-->
<!--</div>-->
</ng-template>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ModalFormComponent } from './modal-form.component';
describe('ModalFormComponent', () => {
let component: ModalFormComponent;
let fixture: ComponentFixture<ModalFormComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ModalFormComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModalFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,40 @@
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {NgbModal, ModalDismissReasons, NgbActiveModal} from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-modal-form',
templateUrl: './modal-form.component.html',
styleUrls: ['./modal-form.component.css']
})
export class ModalFormComponent implements OnInit {
closeResult: string;
@Input() title: string;
@ViewChild('content') content;
activeModal;
constructor(private modalService: NgbModal) {}
ngOnInit() {
}
open() {
this.activeModal = this.modalService.open(this.content, { size: 'lg' });
this.activeModal.result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
close () {
this.activeModal.close();
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}

View File

@ -0,0 +1,139 @@
/*green nav bar*/
.navbar-green {
background-color:#43ac6a;
color:#ffffff;
border-radius:0;
}
.navbar-green .navbar-nav > li > a {
color:#fff;
}
.navbar-green .navbar-nav > .active > a {
color: #ffffff;
background-color:transparent;
}
.navbar-green .navbar-nav > li > a:hover,
.navbar-green .navbar-nav > li > a:focus,
.navbar-green .navbar-nav > .active > a:hover,
.navbar-green .navbar-nav > .active > a:focus,
.navbar-green .navbar-nav > .open >a {
text-decoration: none;
background-color: #39935a;
}
.navbar-green .navbar-brand {
color:#eeeeee;
}
.navbar-green .navbar-toggle {
background-color:#eeeeee;
}
.navbar-green .icon-bar {
background-color:#39935a;
}
/*purple nav bar*/
.navbar-purple {
background-color:#BF76C5;
color:#ffffff;
border-radius:0;
}
.navbar-purple .navbar-nav > li > a {
color:#fff;
}
.navbar-purple .navbar-nav > .active > a {
color: #ffffff;
background-color:transparent;
}
.navbar-purple .navbar-nav > li > a:hover,
.navbar-purple .navbar-nav > li > a:focus,
.navbar-purple .navbar-nav > .active > a:hover,
.navbar-purple .navbar-nav > .active > a:focus,
.navbar-purple .navbar-nav > .open >a {
text-decoration: none;
background-color: #A960AF;
}
.navbar-purple .navbar-brand {
color:#eeeeee;
}
.navbar-purple .navbar-toggle {
background-color:#eeeeee;
}
.navbar-purple .icon-bar {
background-color:#A960AF;
}
/*blue nav bar*/
.navbar-blue {
background-color:#008cba;
color:#ffffff;
border-radius:0;
}
.navbar-blue .navbar-nav > li > a {
color:#fff;
}
.navbar-blue .navbar-nav > .active > a {
color: #ffffff;
background-color:transparent;
}
.navbar-blue .navbar-nav > li > a:hover,
.navbar-blue .navbar-nav > li > a:focus,
.navbar-blue .navbar-nav > .active > a:hover,
.navbar-blue .navbar-nav > .active > a:focus,
.navbar-blue .navbar-nav > .open >a {
text-decoration: none;
background-color: #007399;
}
.navbar-blue .navbar-brand {
color:#eeeeee;
}
.navbar-blue .navbar-toggle {
background-color:#eeeeee;
}
.navbar-blue .icon-bar {
background-color:#007399;
}
/*light blue nav bar*/
.navbar-lightblue {
background-color:#5bc0de;
color:#ffffff;
border-radius:0;
}
.navbar-lightblue .navbar-nav > li > a {
color:#fff;
}
.navbar-lightblue .navbar-nav > .active > a {
color: #ffffff;
background-color:transparent;
}
.navbar-lightblue .navbar-nav > li > a:hover,
.navbar-lightblue .navbar-nav > li > a:focus,
.navbar-lightblue .navbar-nav > .active > a:hover,
.navbar-lightblue .navbar-nav > .active > a:focus,
.navbar-lightblue .navbar-nav > .open >a {
text-decoration: none;
background-color: #41b5d8;
}
.navbar-lightblue .navbar-brand {
color:#eeeeee;
}
.navbar-lightblue .navbar-toggle {
background-color:#eeeeee;
}
.navbar-lightblue .icon-bar {
background-color:#41b5d8;
}

View File

@ -0,0 +1,33 @@
<nav class="navbar navbar-expand-lg navbar-dark navbar-lightblue">
<a class="navbar-brand" routerLink="/">Astute Internal System</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-link" [ngClass]="customerActive ? 'active' : ''" routerLink="/customer" routerLinkActive="active">Customer</a>
<a class="nav-link" [ngClass]="salesOrderActive ? 'active' : ''"routerLink="/sales-order" routerLinkActive="active">Sales Order</a>
<a class="nav-link" [ngClass]="invoiceActive ? 'active' : ''"routerLink="/invoice" routerLinkActive="active">Invoice</a>
</div>
</div>
</nav>
<!--<div class="card text-center">-->
<!--<div class="card-header">-->
<!--<a class="navbar-brand" href="#">Astute Internal System</a>-->
<!--<ul class="nav nav-pills card-header-pills">-->
<!--<li class="nav-item">-->
<!--<a class="nav-link" [ngClass]="customerActive ? 'active' : ''" routerLink="/customer" routerLinkActive="active">Customer</a>-->
<!--</li>-->
<!--<li class="nav-item">-->
<!--<a class="nav-link" [ngClass]="salesOrderActive ? 'active' : ''"routerLink="/sales-order" routerLinkActive="active">Sales Order</a>-->
<!--</li>-->
<!--<li class="nav-item">-->
<!--<a class="nav-link" [ngClass]="invoiceActive ? 'active' : ''"routerLink="/invoice" routerLinkActive="active">Invoice</a>-->
<!--</li>-->
<!--</ul>-->
<!--</div>-->
<!--<div class="card-body">-->
<!--<app-homepage></app-homepage>-->
<!--</div>-->
<!--</div>-->

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavBarComponent } from './nav-bar.component';
describe('NavBarComponent', () => {
let component: NavBarComponent;
let fixture: ComponentFixture<NavBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavBarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,18 @@
import {Component, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-nav-bar',
templateUrl: './nav-bar.component.html',
styleUrls: ['./nav-bar.component.css']
})
export class NavBarComponent implements OnInit {
@Input() customerActive: boolean;
@Input() salesOrderActive: boolean;
@Input() invoiceActive: boolean;
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,14 @@
.cell {
height: 100%;
width: 100%;
background-color: white;
border-radius: 0px;
border-width: 0px;
/*margin: 0px;*/
/*padding: 0;*/
/*overflow-x: auto;*/
}
.cell:focus {
outline: none;
}

View File

@ -0,0 +1,347 @@
<app-nav-bar [salesOrderActive]="true"></app-nav-bar>
<h1 align="center">Sales Orders</h1>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<ag-grid-angular
#agGrid
style="height: 500px;"
class="ag-theme-balham"
[enableSorting]="true"
[enableFilter]="true"
[rowData]="rowData"
[columnDefs]="columnDefs"
rowSelection="single"
></ag-grid-angular>
</div>
</div>
<div class="row justify-content-center mt-2">
<div class="col-6">
<button class="btn btn-primary" style="width: 100%" (click)="open(edit)">Edit Sales Order</button>
</div>
<div class="col-6">
<button class="btn btn-success" style="width: 100%" (click)="open(new)">Add Sales Order</button>
</div>
</div>
</div>
<!--MODAL: new po-->
<app-modal-form [title]="'New Sales Order'" #new>
<div class="modal-body">
<form>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Astute Project Number</label>
<div class="col-sm-10">
<input type="number" class="form-control" placeholder="Project Number" #projNum>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Customer Name</label>
<div class="col-sm-10">
<select class="form-control" #customerid>
<option *ngFor="let customer of customers" [value]="customer.customerId">{{customer.customerName}}</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">SO Title</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="SO Title" #potitle>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">SO Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="SO Number" maxlength="40" #ponum>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">SO Date</label>
<div class="col-sm-10">
<input type="date" class="form-control" [value]="getCurrDate()" #podate>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Contract Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Contract Number" #contractnum>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Contract Amount</label>
<div class="col-sm-10">
<input type="number" class="form-control" placeholder="Contract Amount" #contractamt>
</div>
</div>
</form>
</div>
<!--fee-->
<!--feeTypeId-->
<!--lineItemNo-->
<!--ponum-->
<!--qty-->
<!--remainingQty-->
<!--serviceDesc-->
<!--serviceTypeId-->
<!--Detail-->
<div class="modal-body">
<p class="h4 text-right">Detail</p>
<hr>
<table class="table">
<thead>
<tr>
<th scope="col"></th>
<th scope="col" style="width: 50px">#</th>
<th scope="col">Description</th>
<th scope="col">Fee Type</th>
<th scope="col">Service Type</th>
<th scope="col" style="width: 75px">Qty</th>
<th scope="col" style="width: 100px">Fee</th>
</tr>
</thead>
<tbody *ngFor="let poDetail of newPODetail; let i = index">
<tr class="p-0 m-0">
<td class="p-1 m-0">
<button class="btn btn-outline-danger" type="button" (click)="newPODetail.splice(i, 1);">
-
</button>
</td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.lineItemNo" (change)="onNewCellChange(i, 'lineItemNo', lineItemNo.value)" #lineItemNo></td>
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="poDetail.serviceDesc" (change)="onNewCellChange(i, 'serviceDesc', serviceDesc.value)" #serviceDesc></td>
<td class="p-0 m-0">
<select class="form-control cell" [value]="poDetail.feeTypeId" (change)="onNewCellChange(i, 'feeTypeId', feeTypeId.value)" #feeTypeId>
<option value="1">Fixed Fee</option>
<option value="2">Hourly</option>
</select>
</td>
<td class="p-0 m-0">
<select class="form-control cell" [value]="poDetail.serviceTypeId" (change)="onNewCellChange(i, 'serviceTypeId', serviceTypeId.value)" #serviceTypeId>
<option value="1">Study</option>
<option value="2">Design</option>
<option value="3">Peer Review</option>
<option value="4">Cost Estimation</option>
<option value="5">Forensic Investigation</option>
</select>
</td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.qty" (change)="onNewCellChange(i, 'qty', qty.value); onNewCellChange(i, 'remainingQty', qty.value * fee.value);" #qty></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.fee" (change)="onNewCellChange(i, 'fee', fee.value); onNewCellChange(i, 'remainingQty', qty.value * fee.value);" #fee></td>
<!--<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="poDetail.remainingQty" [id]="'remainingQty' + i"></td>-->
</tr>
</tbody>
<tr class="p-0 m-0">
<td class="p-1 m-0">
<button class="btn btn-success" type="button"
[disabled]="!ponum.value"
(click)="pushOntoNewDetail(newPODetail.length + 1, ponum.value, '', '1', '1', 1, 0, 0)">
<!--(click)="pushOntoNewDetail((lineItemNo) ? lineItemNo.value + 1: 1, ponum.value, serviceDesc.value,-->
<!--feeTypeId.value, serviceTypeId.value, qty.value, fee.value, 0)">-->
+</button>
</td>
<!--<td class="p-0 m-0">-->
<!--<input type="number" class="form-control cell" [value]="(selectedPODetail.length) ? selectedPODetail[selectedPODetail.length-1].lineItemNo + 1: 1" #lineItemNo>-->
<!--</td>-->
<!--<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="''" #serviceDesc></td>-->
<!--<td class="p-0 m-0">-->
<!--<select class="form-control cell" [value]="1" #feeTypeId>-->
<!--<option value="1">Fixed Fee</option>-->
<!--<option value="2">Hourly</option>-->
<!--</select>-->
<!--</td>-->
<!--<td class="p-0 m-0">-->
<!--<select class="form-control cell" [value]="1" #serviceTypeId>-->
<!--<option value="1">Study</option>-->
<!--<option value="2">Design</option>-->
<!--<option value="3">Peer Review</option>-->
<!--<option value="4">Cost Estimation</option>-->
<!--<option value="5">Forensic Investigation</option>-->
<!--</select>-->
<!--</td>-->
<!--<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="1" #qty></td>-->
<!--<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="0" #fee></td>-->
<!--&lt;!&ndash;<td class="p-0 m-0"><input type="number" class="form-control cell" #remainingQty></td>&ndash;&gt;-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-success" type="button"
[disabled]="!(ponum.value && podate.value && customerid.value && contractnum.value && contractamt.value)"
(click)="addPo(projNum.value, ponum.value, podate.value, customerid.value, contractnum.value, contractamt.value, new)"
>
Add
</button>
<button class="btn btn-outline-danger" (click)="close(new)">Cancel</button>
</div>
</app-modal-form>
<!--MODAL: edit po-->
<app-modal-form [title]="'Edit Sales Order'" #edit>
<div *ngIf="selected">
<div class="modal-body">
<p class="h4 text-right">General</p>
<hr>
<form>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Astute Project Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Project Number" [value]="selected.astuteProjectNumber" #projNum>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Customer Name</label>
<div class="col-sm-10">
<select class="form-control" [value]="selected.customerId" #customerid disabled>
<option *ngFor="let customer of customers" [value]="customer.customerId">{{customer.customerName}}
</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">PO Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="PO Number" [value]="selected.ponum" #ponum disabled>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">PO Date</label>
<div class="col-sm-10">
<input type="date" class="form-control" [value]="selected.podate" #podate>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Contract Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Contract Number" [value]="selected.contractNum"
#contractnum>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Contract Amount</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Contract Amount" [value]="selected.contractAmt"
#contractamt>
</div>
</div>
</form>
</div>
<!--fee-->
<!--feeTypeId-->
<!--lineItemNo-->
<!--ponum-->
<!--qty-->
<!--remainingQty-->
<!--serviceDesc-->
<!--serviceTypeId-->
<!--Detail-->
<div class="modal-body" *ngIf="selectedPODetail">
<p class="h4 text-right">Detail</p>
<hr>
<table class="table">
<thead>
<tr>
<th scope="col" style="width: 50px">#</th>
<!--<th scope="col">Purchase Order Number</th>-->
<th scope="col">Description</th>
<th scope="col">Fee Type</th>
<th scope="col">Service Type</th>
<th scope="col" style="width: 75px">Qty</th>
<th scope="col" style="width: 100px">Fee</th>
<!--<th scope="col">Remaining Quantity</th>-->
</tr>
</thead>
<!--<tbody>-->
<tbody *ngFor="let poDetail of selectedPODetail; let i = index">
<tr class="p-0 m-0">
<!--<td class="p-0 m-0">-->
<!--<button class="btn btn-outline-danger" type="button" (click)="selectedPODetail.splice(i, 1);">-->
<!-- - -->
<!--</button>-->
<!--</td>-->
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.lineItemNo" (change)="onSelectedCellChange(i, 'lineItemNo', lineItemNo.value)" #lineItemNo></td>
<!--<td class="p-0"><input type="text" class="form-control cell" [value]="poDetail.ponum"></td>-->
<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="poDetail.serviceDesc" (change)="onSelectedCellChange(i, 'serviceDesc', serviceDesc.value)" #serviceDesc></td>
<td class="p-0 m-0">
<select class="form-control cell" [value]="poDetail.feeTypeId" (change)="onSelectedCellChange(i, 'feeTypeId', feeTypeId.value)" #feeTypeId>
<option value="1">Fixed Fee</option>
<option value="2">Hourly</option>
</select>
<!--<input type="number" class="form-control cell" [value]="poDetail.feeTypeId">-->
</td>
<td class="p-0 m-0">
<select class="form-control cell" [value]="poDetail.serviceTypeId" (change)="onSelectedCellChange(i, 'serviceTypeId', serviceTypeId.value)" #serviceTypeId>
<option value="1">Study</option>
<option value="2">Design</option>
<option value="3">Peer Review</option>
<option value="4">Cost Estimation</option>
<option value="5">Forensic Investigation</option>
</select>
<!--<input type="number" class="form-control cell" [value]="poDetail.serviceTypeId" #serviceTypeId>-->
</td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.qty" (change)="onSelectedCellChange(i, 'qty', qty.value)" #qty></td>
<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="poDetail.fee" (change)="onSelectedCellChange(i, 'fee', fee.value)" #fee></td>
<!--<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="poDetail.remainingQty" [id]="'remainingQty' + i"></td>-->
</tr>
</tbody>
<tr class="p-0 m-0">
<td class="p-1 m-0">
<button class="btn btn-success" type="button"
(click)="pushOntoSelectedDetail(selectedPODetail.length + 1, ponum.value, '', '1', '1', 1, 0, 0)">
<!--(click)="pushOntoSelectedDetail(selectedPODetail[selectedPODetail.length-1].lineItemNo + 1, selected.ponum, serviceDesc.value,-->
<!--feeTypeId.value, serviceTypeId.value, qty.value, fee.value, 0)">-->
+</button>
</td>
<!--<td class="p-0 m-0"><input type="text" class="form-control cell" [value]="''" #serviceDesc></td>-->
<!--<td class="p-0 m-0">-->
<!--<select class="form-control cell" [value]="1" #feeTypeId>-->
<!--<option value="1">Fixed Fee</option>-->
<!--<option value="2">Hourly</option>-->
<!--</select>-->
<!--</td>-->
<!--<td class="p-0 m-0">-->
<!--<select class="form-control cell" [value]="1" #serviceTypeId>-->
<!--<option value="1">Study</option>-->
<!--<option value="2">Design</option>-->
<!--<option value="3">Peer Review</option>-->
<!--<option value="4">Cost Estimation</option>-->
<!--<option value="5">Forensic Investigation</option>-->
<!--</select>-->
<!--</td>-->
<!--<td class="p-0 m-0"><input type="number" class="form-control cell" [value]="0" #qty></td>-->
<!--<td class="p-0 m-0"><input type="number" class="form-control cell" #remainingQty></td>-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-success" type="button"
[disabled]="!(ponum.value && podate.value && contractnum.value && contractamt.value)"
(click)="editPo(projNum.value, ponum.value, podate.value, contractnum.value, contractamt.value, edit)"
>
Update
</button>
<button class="btn btn-outline-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
<div *ngIf="!selected">
<div class="modal-body">
Choose a Purchase Order Fisrt!
</div>
<div class="modal-footer">
<button class="btn btn-success" type="button"
[disabled]="true"
>
Update
</button>
<button class="btn btn-outline-danger" (click)="close(edit)">Cancel</button>
</div>
</div>
</app-modal-form>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SalesOrderComponent } from './sales-order.component';
describe('SalesOrderComponent', () => {
let component: SalesOrderComponent;
let fixture: ComponentFixture<SalesOrderComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SalesOrderComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SalesOrderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,226 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {AstuteClientService} from '../services/astute-client-service';
@Component({
selector: 'app-sales-order',
templateUrl: './sales-order.component.html',
styleUrls: ['./sales-order.component.css']
})
export class SalesOrderComponent implements OnInit {
@ViewChild('agGrid') agGrid;
selected = null;
selectedPODetail = [];
newPODetail = [];
customers;
pos;
columnDefs = [
{headerName: 'Project Number', field: 'astuteProjectNumber'},
{headerName: 'SO Number', field: 'ponum'},
// {headerName: 'Customer ID', field: 'customerId'},
{headerName: 'Customer Name', field: 'customerName'},
{headerName: 'Contract Number', field: 'contractNum'},
{headerName: 'Contract Amount', field: 'contractAmt'},
{headerName: 'SO Date', field: 'podate'}
];
rowData: any;
constructor(private astuteClientService: AstuteClientService) {
}
ngOnInit() {
this.refreshData();
}
addPo(projNum, ponum, podate, customerid, contractnum, contractamt, ref) {
const poData = {
"astuteProjectNumber": projNum,
"poNum": ponum,
"PODate": this.formatDate(new Date(podate)),
"customerId": customerid,
"contractNum": contractnum,
"contractAmt": contractamt,
}
console.log (poData.PODate);
this.astuteClientService.createPO(poData).then((data) => {
if (data) {
this.refreshData();
this.addPODetail(this.newPODetail);
ref.close();
} else {
alert("PO Creation failed, check input fields");
}
}, (reason) => {
alert("add po failed for " + reason);
});
}
addPODetail(details) {
if (details.length) {
console.log(details[0]);
this.astuteClientService.createPODetail(details[0]).then((data) => {
if (data) {
details.splice(0, 1);
this.addPODetail(details);
} else {
alert("add detail failed");
}
});
} else {
this.newPODetail = [];
}
}
editPo(projNum, ponum, podate, contractnum, contractamt, ref) {
const poData = {
"astuteProjectNumber": projNum,
"poNum": ponum,
"PODate": this.formatDate(new Date(podate)),
"contractNum": contractnum,
"contractAmt": contractamt,
}
console.log(poData);
this.astuteClientService.updatePO(ponum, poData).then((data) => {
if (data) {
this.refreshData();
this.editPODetail(this.selectedPODetail);
ref.close();
} else {
alert("PO updating failed, check input fields");
}
}, (reason) => {
alert("update po failed for " + reason);
});
}
editPODetail (details) {
if (details.length) {
console.log(details[0]);
this.astuteClientService.updatePODetail(details[0].ponum, details[0].lineItemNo, details[0]).then((data) => {
if (data) {
details.splice(0, 1);
this.editPODetail(details);
} else {
alert("add detail failed")
}
});
} else {
this.newPODetail = [];
}
}
pushOntoSelectedDetail(lineItemNo: number, ponum, serviceDesc, feeTypeId, serviceTypeId, qty, fee, remainingQty) {
this.selectedPODetail.push({
'lineItemNo': lineItemNo,
'ponum': ponum,
'serviceDesc': serviceDesc,
'feeTypeId': feeTypeId,
'serviceTypeId': serviceTypeId,
'qty': qty,
'fee': fee,
'remainingQty': remainingQty
});
}
pushOntoNewDetail(lineItemNo: number, ponum, serviceDesc, feeTypeId, serviceTypeId, qty, fee, remainingQty) {
this.newPODetail.push({
'lineItemNo': lineItemNo,
'poNum': ponum,
'serviceDesc': serviceDesc,
'feeTypeId': feeTypeId,
'serviceTypeId': serviceTypeId,
'qty': qty,
'fee': fee,
'remainingQty': remainingQty
});
}
open(ref) {
this.getSelectedRows();
ref.open();
}
close(ref) {
this.newPODetail = [];
this.selectedPODetail = [];
ref.close();
}
onSelectedCellChange(row: number, col: string, value) {
this.selectedPODetail[row][col] = value;
console.log(this.selectedPODetail);
}
onNewCellChange(row: number, col: string, value) {
this.newPODetail[row][col] = value;
console.log(this.newPODetail);
}
getCurrDate() {
const d = new Date();
return this.formatDate(d);
}
formatDate(d: Date) {
let month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
return [year, month, day].join('-');
}
getSelectedRows() {
const selectedNodes = this.agGrid.api.getSelectedNodes();
if (selectedNodes.length) {
this.selected = selectedNodes.map(node => node.data)[0];
this.astuteClientService.getPODetail(this.selected.ponum).then((data) => {
if (data) {
this.selectedPODetail = data;
console.log(this.selectedPODetail);
} else {
alert("get PO detail failed!")
}
});
} else {
this.selected = null;
this.selectedPODetail = [];
}
}
refreshData() {
this.astuteClientService.getCustomers().then((customers) => {
if (customers) {
this.customers = customers;
this.astuteClientService.getPOs().then((data) => {
if (data) {
this.pos = data;
this.rowData = data;
this.rowData.forEach((row) => {
row.customerName = this.getCustomerName(row.customerId);
});
}
});
} else {
alert("get Customers Failed!");
}
});
// this.rowData = this.astuteClientService.getPOs();
}
getCustomerName(customerId) {
let name = "";
this.customers.forEach((customer) => {
if (customer.customerId === customerId) {
name = customer.customerName;
}
});
return name;
}
}

View File

@ -0,0 +1,345 @@
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Injectable} from '@angular/core';
@Injectable()
export class AstuteClientService {
headers = {
headers: new HttpHeaders().set('Content-Type', 'application/json'),
};
private authUrl = 'http://localhost:8080/astutesystem/auth';
private customerUrl = 'http://localhost:8080/astutesystem/customer';
private POUrl = 'http://localhost:8080/astutesystem/po';
private PODetailUrl = 'http://localhost:8080/astutesystem/po/detail';
private invoiceUrl = 'http://localhost:8080/astutesystem/invoice';
private invoiceDetailUrl = 'http://localhost:8080/astutesystem/invoice/detail';
private invoiceGenUrl = 'http://localhost:8080/astutesystem/invoice/generatedInvoice';
private sessionId;
constructor(private http: HttpClient) { }
// **************************************** AUTH Service methods
public login(username: string, password: string): Promise<string> {
const data = {
'username': username,
'password': password
};
return this.http
.post(this.authUrl, data, this.headers)
.toPromise()
.then(response => {
console.log(response['entity']);
const sessionId = response['entity'];
if (sessionId != null) {
localStorage.setItem('SESSION_ID', sessionId);
return sessionId;
} else {
return null;
}
});
}
private getSessionId(): string {
console.log(localStorage.getItem('SESSION_ID'));
return localStorage.getItem('SESSION_ID');
}
// **************************************** Customer Service methods
public getCustomers(): Promise<any> {
console.log("*** In getCustomers()");
const url = `${this.customerUrl}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public updateCustomer(customerId: number, data: any): Promise<any> {
console.log("*** In updateCustomer()");
const url = `${this.customerUrl}/${customerId}`; //TODO send sessionId
return this.http.put(url, data)
.toPromise()
.then(response => response['entity']);
}
public createCustomer(data: any): Promise<any> {
console.log("*** In createCustomer()");
const url = `${this.customerUrl}`; //TODO send sessionId
return this.http.post(url, data)
.toPromise()
.then(response => response['entity']);
}
// **************************************** PO Service methods
public getPOs(): Promise<any> {
console.log("*** In getPOs()");
const url = `${this.POUrl}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public getPODetail(ponum): Promise<any> {
console.log("*** In getPOs()");
const url = `${this.PODetailUrl}?PONum=${ponum}`;
console.log(url);
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public updatePO(ponum: string, data: any): Promise<any> {
console.log("*** In updatePO()");
const url = `${this.POUrl}/${ponum}`; //TODO send sessionId
return this.http.put(url, data)
.toPromise()
.then(response => response['entity']);
}
public createPO(data: any): Promise<any> {
console.log("*** In createPO()");
const url = `${this.POUrl}`; //TODO send sessionId
return this.http.post(url, data)
.toPromise()
.then(response => response['entity']);
}
// String serviceDesc;
// int feeTypeId;
// Double qty;
// int serviceTypeId;
// String schedule;
// Date deliverBy;
public updatePODetail(ponum, lineItemNo, data) {
console.log("*** In updatePODetail()");
const url = `${this.POUrl}/detail/${ponum}/${lineItemNo}`; //TODO send sessionId
return this.http.put(url, data)
.toPromise()
.then(response => response['entity']);
}
public createPODetail(data) {
console.log("*** In createPODetail()");
const url = `${this.POUrl}/detail`; //TODO send sessionId
return this.http.post(url, data)
.toPromise()
.then(response => response['entity']);
}
// **************************************** Invoice Service methods
// /{InvoiceNumber}/void
public submitInvoice (invoiceNumber) {
console.log("*** In submitInvoice()");
const url = `${this.invoiceUrl}/${invoiceNumber}/submit`;
return this.http.put(url, {})
.toPromise()
.then(response => {
console.log (response['entity']);
return response['entity'];
});
}
public voidInvoice (invoiceNumber) {
console.log("*** In voidInvoice()");
const url = `${this.invoiceUrl}/${invoiceNumber}/void`;
return this.http.put(url, {})
.toPromise()
.then(response => {
console.log (response['entity']);
return response['entity'];
});
}
public generateInvoiceNumber (ponum) {
console.log("*** In generateInvoiceNumber()");
const url = `${this.invoiceUrl}/generateInvoiceNumber/${ponum}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log (response['entity'])
return response['entity'];
});
}
public getInvoices(): Promise<any> {
console.log("*** In getInvoices()");
const url = `${this.invoiceUrl}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public getInvoiceDetail(invoiceId: string): Promise<any> {
console.log("*** In getInvoiceDetail()");
const url = `${this.invoiceDetailUrl}/${invoiceId}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public getInvoiceGen (invoiceId: string): Promise<any> {
console.log("*** In getInvoiceGen()");
const url = `${this.invoiceGenUrl}/${invoiceId}`;
return this.http.get(url)
.toPromise()
.then(response => {
console.log(response['entity']);
return response['entity'];
});
}
public updateInvoice(invoiceNumber: string, data: any): Promise<any> {
console.log("*** In updateInvoice()");
const url = `${this.invoiceUrl}/${invoiceNumber}`; //TODO send sessionId
return this.http.put(url, data)
.toPromise()
.then(response => response['entity']);
}
public createInvoice(data: any): Promise<any> {
console.log("*** In createInvoice()");
const url = `${this.invoiceUrl}`; //TODO send sessionId
return this.http.post(url, data)
.toPromise()
.then(response => response['entity']);
}
public updateInvoiceDetail(invNum, lineItemNo, data) {
console.log("*** In updateInvoiceDetail()");
const url = `${this.invoiceUrl}/detail/${invNum}/${lineItemNo}`; //TODO send sessionId
return this.http.put(url, data)
.toPromise()
.then(response => response['entity']);
}
public createInvoiceDetail(data) {
console.log("*** In createInvoiceDetail()");
const url = `${this.invoiceUrl}/detail`; //TODO send sessionId
return this.http.post(url, data)
.toPromise()
.then(response => response['entity']);
}
// public getRecord(patientId: number): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// console.log(response);
// });
// }
//
// public getInfo(patientId: number): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// return response['entity'];
// });
// }
//
// public getVisits(patientId: number): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}/visits?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// return response['entity'];
// });
// }
//
// public getAllVisits(): Promise<any> {
// const url = `${this.recordsUrl}/visits?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// return response['entity'];
// });
// }
//
// public getVitals(visitId: number): Promise<any> {
// const url = `${this.visitsUrl}/${visitId}/vitals?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// return response['entity'];
// });
// }
//
// public getLatestVitals(patientId: number): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}/vitals?sessionId=${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// return response['entity'];
// });
// }
//
// public updateInfo(patientId: number, data: any): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}?sessionId=${this.getSessionId()}`;
// return this.http.put(url, data)
// .toPromise()
// .then(response => response['entity']);
// }
// public updateVisit(patientId: number, visit: any): Promise<any> {
// console.log(visit);
//
// const url = `${this.recordsUrl}/${patientId}/visits/${visit.visitId}?sessionId=${this.getSessionId()}`;
// return this.http.put(url, visit)
// .toPromise()
// .then(response => {
// console.log(response['entity']);
// return response['entity'];
// });
// }
//
// public getSessionPatientId(): Promise<number> {
// const url = `${this.sessionsUrl}/${this.getSessionId()}`;
// console.log(url);
// return this.http.get(url)
// .toPromise()
// .then(response => {
// console.log(response);
// return response['entity'].patientId;
// });
// }
//
// public startVisit(patientId: number): Promise<any> {
// const url = `${this.recordsUrl}/${patientId}/visits?${this.getSessionId()}`;
// return this.http.post(url, null)
// .toPromise()
// .then(response => {
// console.log(response);
// return response['entity'];
// });
// }
//
// getMedications() {
// const url = `${this.medsUrl}?${this.getSessionId()}`;
// return this.http.get(url)
// .toPromise()
// .then(response => {
// console.log(response);
// return response['entity'];
// });
// }
}

View File

@ -0,0 +1,9 @@
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For IE 9-11 support, please uncomment the last line of the file and adjust as needed
> 0.5%
last 2 versions
Firefox ESR
not dead
# IE 9-11

View File

@ -0,0 +1,3 @@
export const environment = {
production: true
};

View File

@ -0,0 +1,15 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* In development mode, to ignore zone related error stack frames such as
* `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
* import the following file, but please comment it out in production mode
* because it will have performance impact when throw error
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AstuteClient2</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@ -0,0 +1,31 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../coverage'),
reports: ['html', 'lcovonly'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

12
AstuteClient2/src/main.ts Normal file
View File

@ -0,0 +1,12 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));

View File

@ -0,0 +1,80 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
**/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
*/
// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
/*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*/
// (window as any).__Zone_enable_cross_context_check = true;
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

View File

@ -0,0 +1,4 @@
/* You can add global styles to this file, and also import other style files */
@import '~bootstrap/dist/css/bootstrap.min.css';
@import "~ag-grid/dist/styles/ag-grid.css";
@import "~ag-grid/dist/styles/ag-theme-balham.css";

20
AstuteClient2/src/test.ts Normal file
View File

@ -0,0 +1,20 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@ -0,0 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"types": []
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

View File

@ -0,0 +1,19 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"module": "commonjs",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -0,0 +1,17 @@
{
"extends": "../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}

View File

@ -0,0 +1,20 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}

130
AstuteClient2/tslint.json Normal file
View File

@ -0,0 +1,130 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"no-output-on-prefix": true,
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true
}
}