Skip to content

Commit

Permalink
feature/#22_hide_credentials: display a form in order for the user to…
Browse files Browse the repository at this point in the history
… identify. closes #22
  • Loading branch information
blablanumerodeux committed Dec 20, 2020
1 parent f270dc0 commit 4ada1d3
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 20 deletions.
3 changes: 3 additions & 0 deletions src/app/actions/shelters.action.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {createAction, props} from '@ngrx/store';
import {Shelter} from '../models/Shelter.models';
import {BasicAuth} from '../models/BasicAuth.models';

export const deleteShelter = createAction('[test] Delete a shelter', props<{ shelterId: number }>());
export const getAllShelters = createAction('[Shelters Page] Load Shelters');
Expand All @@ -9,3 +10,5 @@ export const successAddShelter = createAction('[Shelters Page] Shelter added', p
export const successUpdateShelter = createAction('[Shelters Page] Shelter updated', props<{ shelter: Shelter }>());
export const successGetAllShelters = createAction('[Shelters Page] Shelters loaded', props<{ sheltersList: Shelter[] }>());
export const successDeleteShelter = createAction('[Shelters Page] Shelters deleted');

export const connexionRequest = createAction('[Login Page] connexion request', props<{ cred: BasicAuth}>());
13 changes: 8 additions & 5 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import {RouterModule} from '@angular/router';
import {AppRoutingModule} from './app.routing';
Expand All @@ -16,14 +16,16 @@ import {environment} from '../environments/environment';
import {EffectsModule} from '@ngrx/effects';
import {SheltersEffects} from './effects/shelters.effect';
import {StoreModule} from '@ngrx/store';
import {sheltersReducer} from './reducers/shelters.reducer';
import {authReducer, sheltersReducer} from './reducers/shelters.reducer';
import {BasicFormComponent} from './auth/basic-form/basic-form.component';


@NgModule({
declarations: [
AppComponent,
NavbarComponent,
FooterComponent
FooterComponent,
BasicFormComponent
],
imports: [
BrowserModule,
Expand All @@ -33,9 +35,10 @@ import {sheltersReducer} from './reducers/shelters.reducer';
ComponentsModule,
SheltersModule,
AppRoutingModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}),
EffectsModule.forRoot([SheltersEffects]),
StoreModule.forRoot({sheltersList: sheltersReducer})
StoreModule.forRoot({sheltersList: sheltersReducer, cred: authReducer}),
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
Expand Down
Empty file.
17 changes: 17 additions & 0 deletions src/app/auth/basic-form/basic-form.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="card-body">
<form (ngSubmit)="onSubmit()" [formGroup]="profileForm">
<div class="form-group">
<label for="login">login</label>
<input class="form-control" id="login"
formControlName="login" placeholder="{{cred.login}}">

<label for="password">password</label>
<input class="form-control" id="password"
formControlName="password" placeholder="{{cred.password}}">

<div class="form-row">
<button class="btn btn-outline-default btn-danger" type="submit">Save</button>
</div>
</div>
</form>
</div>
25 changes: 25 additions & 0 deletions src/app/auth/basic-form/basic-form.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { BasicFormComponent } from './basic-form.component';

describe('BasicFormComponent', () => {
let component: BasicFormComponent;
let fixture: ComponentFixture<BasicFormComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BasicFormComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(BasicFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
50 changes: 50 additions & 0 deletions src/app/auth/basic-form/basic-form.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {Component, OnInit} from '@angular/core';
import {BasicAuth} from '../../models/BasicAuth.models';
import {FormControl, FormGroup} from '@angular/forms';
import {connexionRequest} from '../../actions/shelters.action';
import {select, Store} from '@ngrx/store';
import {Clone} from '../../utils/clone';
import {Observable} from 'rxjs';

@Component({
selector: 'app-basic-form',
templateUrl: './basic-form.component.html',
styleUrls: ['./basic-form.component.css']
})
export class BasicFormComponent implements OnInit {

profileForm = new FormGroup({
login: new FormControl(''),
password: new FormControl('')
});
private cred$: Observable<BasicAuth> = this.store.pipe(select('cred'));
private cred: BasicAuth;
private edit: boolean = true;

constructor(private clone: Clone, private store: Store<{ cred: BasicAuth }>) {
this.cred$.subscribe((newCreds: BasicAuth) => {
console.log('credentials used', newCreds);
this.cred = newCreds;
}
);
}

ngOnInit(): void {
this.profileForm.get('login').setValue(this.cred.login);
this.profileForm.get('password').setValue(this.cred.password);
}

/**
*
*/
onSubmit() {
this.cred = this.clone.simpleClone(this.cred);
this.cred.login = this.profileForm.value.login;
this.cred.password = this.profileForm.value.password;

this.store.dispatch(connexionRequest({cred: this.cred}));

// TODO: change the edit status only after action is done (callback ?)
this.edit = !this.edit;
}
}
1 change: 1 addition & 0 deletions src/app/effects/shelters.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Injectable} from '@angular/core';
import {SheltersService} from '../services/shelters.service';
import {
addShelter,
connexionRequest,
deleteShelter,
getAllShelters,
successAddShelter,
Expand Down
4 changes: 4 additions & 0 deletions src/app/models/BasicAuth.models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface BasicAuth {
login: string
password: string
}
25 changes: 22 additions & 3 deletions src/app/reducers/shelters.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
import {createReducer, on} from '@ngrx/store';
import {
addShelter,
connexionRequest,
deleteShelter,
getAllShelters,
successAddShelter,
successDeleteShelter,
successGetAllShelters, successUpdateShelter, updateShelter
successGetAllShelters,
successUpdateShelter,
updateShelter
} from '../actions/shelters.action';
import {Shelter} from '../models/Shelter.models';
import {BasicAuth} from '../models/BasicAuth.models';

export let sheltersList: Shelter[] = undefined;
export let cred: BasicAuth = {
login: 'admin',
password: 'nimda'
};

const _counterReducer = createReducer(sheltersList,
const _authReducer = createReducer(cred,
on(connexionRequest, (state, action) => {
cred = action.cred;
return cred;
})
);

const _sheltersReducer = createReducer(sheltersList,
on(successDeleteShelter, (state) => {
console.log('shelter deleted reducer');
return sheltersList;
Expand Down Expand Up @@ -52,5 +67,9 @@ const _counterReducer = createReducer(sheltersList,
);

export function sheltersReducer(state, action) {
return _counterReducer(state, action);
return _sheltersReducer(state, action);
}

export function authReducer(state, action) {
return _authReducer(state, action);
}
17 changes: 16 additions & 1 deletion src/app/services/shelters.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {ShelterList} from '../models/ShelterList.models';
import {environment} from '../../environments/environment';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
import {BasicAuth} from '../models/BasicAuth.models';
import {select, Store} from '@ngrx/store';

@Injectable({
providedIn: 'root'
Expand All @@ -21,8 +23,21 @@ export class SheltersService {
private uri = 'api/v1/shelters';
private url = environment.baseUrl + '/' + this.uri;
private shelterList$: Observable<Shelter[]>;
private cred$: Observable<BasicAuth> = this.store.pipe(select('cred'));

constructor(private _httpClient: HttpClient) {
constructor(private _httpClient: HttpClient, private store: Store<{ cred: BasicAuth }>) {
this.cred$.subscribe((newCreds: BasicAuth) => {
console.log('credentials used', newCreds);
this.credentials = newCreds.login + ':' + newCreds.password;
// TODO: modify instead of recreate
this.httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa(this.credentials)
})
};
}
);
}

/**
Expand Down
29 changes: 18 additions & 11 deletions src/app/shelters/shelter/shelter.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import {Shelter} from '../../models/Shelter.models';
import {FormControl, FormGroup} from '@angular/forms';
import {deleteShelter, updateShelter} from '../../actions/shelters.action';
import {Store} from '@ngrx/store';
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {BasicFormComponent} from '../../auth/basic-form/basic-form.component';
import {Clone} from '../../utils/clone';
import {BasicAuth} from '../../models/BasicAuth.models';

@Component({
selector: 'shelter',
Expand All @@ -19,7 +23,7 @@ export class ShelterComponent implements OnInit {
availableBeds: new FormControl(''),
});

constructor(private store: Store<{ sheltersList: Shelter[] }>) {
constructor(private clone: Clone, private store: Store<{ cred: BasicAuth }>, private modalService: NgbModal) {
}

ngOnInit(): void {
Expand All @@ -31,20 +35,23 @@ export class ShelterComponent implements OnInit {
* call the effect of updating a shelter
*/
onSubmit() {
this.shelter = this.simpleClone(this.shelter);
this.shelter = this.clone.simpleClone(this.shelter);
this.shelter.address = this.profileForm.value.address;
this.shelter.availableBeds = this.profileForm.value.availableBeds;

//TODO: check if user is connected

// display modal if he's not
const modalRef = this.modalService.open(BasicFormComponent);
modalRef.componentInstance.name = 'World';

// try request if he is
this.store.dispatch(updateShelter({shelter: this.shelter}));
// todo: change the edit status only after action is done (callback ?)
this.edit = !this.edit;
}

/**
* shallow clone of an object
* @param obj
*/
simpleClone(obj: any) {
return Object.assign({}, obj);
// TODO: display spinner
// TODO: change the edit status after action is done (callback ?)
this.edit = !this.edit;
// modalRef.close();
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/app/utils/clone.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {TestBed} from '@angular/core/testing';
import {Clone} from './clone';

describe('Clone', () => {
let clone: Clone;

beforeEach(() => {
TestBed.configureTestingModule({});
clone = TestBed.inject(Clone);
});

it('should be created', () => {
expect(clone).toBeTruthy();
});
});
18 changes: 18 additions & 0 deletions src/app/utils/clone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Injectable} from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class Clone {

constructor() {
}

/**
* shallow clone of an object
* @param obj
*/
simpleClone(obj: any) {
return Object.assign({}, obj);
}
}

0 comments on commit 4ada1d3

Please sign in to comment.