Skip to content

Commit

Permalink
Merge pull request #6 from owezzy/ft-app-design-and-recipes
Browse files Browse the repository at this point in the history
Ft app design and recipes
  • Loading branch information
Owen Adira authored Feb 11, 2019
2 parents a3a537f + 3f31c5d commit 2b28c45
Show file tree
Hide file tree
Showing 38 changed files with 1,127 additions and 92 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ jobs:
- setup_remote_docker:
docker_layer_caching: false
- store_artifacts:
path: /usr/src/covarage
path: /usr/src/coverage
- store_test_results:
path: covarage
path: coverage
- run:
name: Build Docker Image
command: |
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"hammerjs": "^2.0.8",
"jwt-decode": "^2.2.0",
"rxjs": "~6.3.3",
"ts-enum-util": "^3.1.0",
"tslib": "^1.9.0",
"zone.js": "~0.8.26"
},
Expand Down
19 changes: 17 additions & 2 deletions src/app/material.module.ts → src/app/app.material.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ import {
MatIconModule,
MatInputModule,
MatListModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatSidenavModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatToolbarModule,
MatDatepickerModule,
} from '@angular/material'

@NgModule({
Expand All @@ -27,6 +32,11 @@ import {
MatSnackBarModule,
MatToolbarModule,
MatDialogModule,
MatTableModule,
MatSortModule,
MatPaginatorModule,
MatProgressSpinnerModule

],
exports: [
CommonModule,
Expand All @@ -39,7 +49,12 @@ import {
MatSidenavModule,
MatSnackBarModule,
MatToolbarModule,
MatDialogModule
MatDialogModule,
MatTableModule,
MatSortModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatDatepickerModule,
],
})
export class MaterialModule {}
export class AppMaterialModule {}
4 changes: 2 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'
import { HomeComponent } from './home/home.component'
import { MaterialModule } from './material.module'
import { AppMaterialModule } from './app.material.module'
import { PageNotFoundComponent } from './page-not-found/page-not-found.component'

import { FlexLayoutModule } from '@angular/flex-layout'
Expand All @@ -31,7 +31,7 @@ import { AuthGuard } from './auth/auth-guard.guard'
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MaterialModule,
AppMaterialModule,
HttpClientModule,
FlexLayoutModule,
FormsModule,
Expand Down
4 changes: 2 additions & 2 deletions src/app/auth/auth-guard.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import {
CanLoad, CanActivateChild, Router,
} from '@angular/router'
import { Observable } from 'rxjs'
import { AuthService, IAuthStatus } from './auth.service'
import { AuthService, AuthStatusInterface } from './auth.service'
import { Route } from '@angular/compiler/src/core'
import { UiService } from '../common/ui.service'

@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
protected currentAuthStatus: IAuthStatus
protected currentAuthStatus: AuthStatusInterface

constructor(
protected authService: AuthService,
Expand Down
8 changes: 4 additions & 4 deletions src/app/auth/auth.service.fake.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { IAuthService, IAuthStatus, defaultAuthStatus } from './auth.service'
import { AuthServiceInterface, AuthStatusInterface, defaultAuthStatus } from './auth.service'
import { BehaviorSubject, Observable, of } from 'rxjs'
import { Injectable } from '@angular/core'

@Injectable()
export class AuthServiceFake implements IAuthService {
authStatus = new BehaviorSubject<IAuthStatus>(defaultAuthStatus)
export class AuthServiceFake implements AuthServiceInterface {
authStatus = new BehaviorSubject<AuthStatusInterface>(defaultAuthStatus)

constructor() {
}

login(email: string, password: string): Observable<IAuthStatus> {
login(email: string, password: string): Observable<AuthStatusInterface> {
return of(defaultAuthStatus)
}

Expand Down
34 changes: 17 additions & 17 deletions src/app/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ import { Injectable } from '@angular/core'
import { Role } from './role.enum'
import { BehaviorSubject, Observable, of, throwError as observableThrowError } from 'rxjs'

import { sign } from 'fake-jwt-sign'
import { sign } from 'fake-jwt-sign' // for fakeAuthProvider
import { transformError } from '../common/common'
import * as decode from 'jwt-decode'
import { catchError, map } from 'rxjs/operators'

import { environment } from '../../environments/environment'
import { CacheService } from './cache.service'

export interface IAuthStatus {
export interface AuthStatusInterface {
isAuthenticated: boolean
userRole: Role
userId: string
}

export interface IAuthService {
authStatus: BehaviorSubject<IAuthStatus>
login(email: string, password: string): Observable<IAuthStatus>
export interface AuthServiceInterface {
authStatus: BehaviorSubject<AuthStatusInterface>
login(email: string, password: string): Observable<AuthStatusInterface>
logout()
getToken(): string
}

interface IServerAuthResponse {
interface ServerAuthResponseInterface {
accessToken: string
}

Expand All @@ -36,16 +36,16 @@ export const defaultAuthStatus = {
@Injectable({
providedIn: 'root'
})
export class AuthService extends CacheService implements IAuthService {
export class AuthService extends CacheService implements AuthServiceInterface {

authStatus = new BehaviorSubject<IAuthStatus>(
authStatus = new BehaviorSubject<AuthStatusInterface>(
this.getItem('authStatus') || defaultAuthStatus
)

private readonly authProvider: (
email: string,
password: string
) => Observable<IServerAuthResponse>
) => Observable<ServerAuthResponseInterface>

constructor(private httpClient: HttpClient) {
super()
Expand All @@ -58,16 +58,16 @@ export class AuthService extends CacheService implements IAuthService {
// private exampleAuthProvider(
// email: string,
// password: string
// ): Observable<IServerAuthResponse> {
// return this.httpClient.post<IServerAuthResponse>(`${environment.baseUrl}/v1/login`, {
// ): Observable<ServerAuthResponseInterface> {
// return this.httpClient.post<ServerAuthResponseInterface>(`${environment.baseUrl}/v1/login`, {
// email: email,
// password: password,
// })
// }
private fakeAuthProvider (
email: string,
password: string
): Observable<IServerAuthResponse> {
): Observable<ServerAuthResponseInterface> {
if (!email.toLowerCase().endsWith('@test.com')) {
return observableThrowError('Failed to login Email needs to end with @test.com')
}
Expand All @@ -80,25 +80,25 @@ export class AuthService extends CacheService implements IAuthService {
: email.toLowerCase().includes('clerk')
? Role.Clerk
: email.toLowerCase().includes('manager') ? Role.Manager : Role.None,
} as IAuthStatus
} as AuthStatusInterface

const authResponse = {
accessToken: sign(authStatus, 'secret', {
expiresIn: '1h',
algorithm: 'none',
}),
} as IServerAuthResponse
} as ServerAuthResponseInterface

return of(authResponse)
}

login(email: string, password: string): Observable<IAuthStatus> {
login(email: string, password: string): Observable<AuthStatusInterface> {
this.logout()

const loginResponse = this.authProvider(email, password).pipe(
map(value => {
this.setToken(value.accessToken)
return decode(value.accessToken) as IAuthStatus
return decode(value.accessToken) as AuthStatusInterface
}),
catchError(transformError)
)
Expand All @@ -125,7 +125,7 @@ export class AuthService extends CacheService implements IAuthService {
this.setItem('jwt', jwt)
}

private getDecodedToken(): IAuthStatus {
private getDecodedToken(): AuthStatusInterface {
return decode(this.getItem('jwt'))
}

Expand Down
14 changes: 11 additions & 3 deletions src/app/common/common.testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import { MediaChange } from '@angular/flex-layout'
import { SafeResourceUrl, SafeValue } from '@angular/platform-browser'
import { SecurityContext } from '@angular/platform-browser/src/security/dom_sanitization_service'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MaterialModule } from '../material.module'
import { AppMaterialModule } from '../app.material.module'
import { NoopAnimationsModule } from '@angular/platform-browser/animations'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import { RouterTestingModule } from '@angular/router/testing'
import { HttpErrorResponse } from '@angular/common/http'
import { AuthService } from '../auth/auth.service'
import { AuthServiceFake } from '../auth/auth.service.fake'
import { UiService } from './ui.service'
import { UserService } from '../user/userModel/user.service'
import { UserServiceFake } from '../user/userModel/user.service.fake'
import { SharedComponentsModule } from '../shared-components.module'
import { UserMaterialModule } from '../user/user-material.module'

const FAKE_SVGS = {
grocery: '<svg><path id="grocery" name="grocery"></path></svg>',
Expand Down Expand Up @@ -75,12 +79,16 @@ export class DomSanitizerFake {
export const commonTestingModules: any[] = [
FormsModule,
ReactiveFormsModule,
MaterialModule,
AppMaterialModule,
NoopAnimationsModule,
HttpClientTestingModule,
RouterTestingModule,
SharedComponentsModule,
UserMaterialModule,
]

export const commonTestingProviders: any[] = [
{ provide: AuthService, useClass: AuthServiceFake }, UiService,
{ provide: AuthService, useClass: AuthServiceFake },
{ provide: UserService, useClass: UserServiceFake },
UiService,
]
22 changes: 22 additions & 0 deletions src/app/common/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,25 @@ export const PasswordValidation = [
Validators.minLength(8),
Validators.maxLength(50),
]
export const OptionalTextValidation = [Validators.minLength(2),
Validators.maxLength(50)]

export const RequiredTextValidation = OptionalTextValidation.concat([Validators.required])

export const OneCharValidation = [Validators.minLength(1)]

export const BirthDateValidation = [
Validators.required,
Validators.min(new Date().getFullYear() - 100),
Validators.max(new Date().getFullYear()),
]

export const CountyZipCodeValidation = [
Validators.required,
Validators.pattern(/^\\d{5}$/), /** "Format": "NNNNN"*/
]

export const KenyaPhoneNumberValidation = [
Validators.required,
Validators.pattern(/(\+254|^)[ ]?[7]([0-3][0-9])[ ]?[0-9]{3}[ ]?[0-9]{3}\z/),
]
4 changes: 2 additions & 2 deletions src/app/inventory/inventory.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { InventoryRoutingModule } from './inventory-routing.module'
import { InventoryComponent } from './inventory.component'
import { MaterialModule } from '../material.module'
import { AppMaterialModule } from '../app.material.module'
import { InventoryDashboardComponent } from './inventory-dashboard/inventory-dashboard.component'
import { StockEntryComponent } from './stock-entry/stock-entry.component'
import { ProductsComponent } from './products/products.component'
Expand All @@ -11,6 +11,6 @@ import { FlexLayoutModule } from '@angular/flex-layout'

@NgModule({
declarations: [InventoryComponent, InventoryDashboardComponent, StockEntryComponent, ProductsComponent, CategoriesComponent],
imports: [CommonModule, InventoryRoutingModule, MaterialModule, FlexLayoutModule, ],
imports: [CommonModule, InventoryRoutingModule, AppMaterialModule, FlexLayoutModule, ],
})
export class InventoryModule {}
12 changes: 12 additions & 0 deletions src/app/manager/manager-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { ReceiptLookupComponent } from './receipt-lookup/receipt-lookup.componen
import { UserManagementComponent } from './user-management/user-management.component'
import { AuthGuard } from '../auth/auth-guard.guard'
import { Role } from '../auth/role.enum'
import { UserTableComponent } from './user-table/user-table.component'
import { ViewUserComponent } from '../user/view-user/view-user.component'
import { UserResolve } from '../user/userModel/user.resolve'

const routes: Routes = [
{
Expand All @@ -24,7 +27,16 @@ const routes: Routes = [
{
path: 'users',
component: UserManagementComponent,
children: [
{ path: '', component: UserTableComponent, outlet: 'master' },
{ path: 'user', component: ViewUserComponent, outlet: 'detail',
resolve: {
user: UserResolve
}
},
],
canActivate: [AuthGuard],
canActivateChild: [AuthGuard],
data: {
expectedRole: Role.Manager,
},
Expand Down
23 changes: 19 additions & 4 deletions src/app/manager/manager.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common'
import { NgModule } from '@angular/core'
import { MaterialModule } from '../material.module'
import { AppMaterialModule } from '../app.material.module'
import { ManagerHomeComponent } from './manager-home/manager-home.component'
import { ManagerRoutingModule } from './manager-routing.module'
import { ManagerComponent } from './manager.component'
Expand All @@ -9,15 +9,30 @@ import { UserManagementComponent } from './user-management/user-management.compo
import { FlexLayoutModule } from '@angular/flex-layout'
import { AuthGuard } from '../auth/auth-guard.guard'
import { AuthService } from '../auth/auth.service'
import { UserTableComponent } from './user-table/user-table.component'
import { UserResolve } from '../user/userModel/user.resolve'
import { SharedComponentsModule } from '../shared-components.module'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { UserService } from '../user/userModel/user.service'

@NgModule({
declarations: [
ManagerHomeComponent,
ManagerComponent,
UserManagementComponent,
ReceiptLookupComponent,
UserTableComponent,
],
imports: [CommonModule, ManagerRoutingModule, MaterialModule, FlexLayoutModule],
providers: [AuthGuard, AuthService]
imports: [
CommonModule,
ManagerRoutingModule,
AppMaterialModule,
FlexLayoutModule,
SharedComponentsModule,
FormsModule,
ReactiveFormsModule
],
providers: [AuthGuard, AuthService, UserService, UserResolve],
})
export class ManagerModule {}
export class ManagerModule {
}

This file was deleted.

Loading

0 comments on commit 2b28c45

Please sign in to comment.