diff --git a/src/app/assets/components/view-defendant/view-defendant.component.html b/src/app/assets/components/view-defendant/view-defendant.component.html index 044a0ed..4730e59 100644 --- a/src/app/assets/components/view-defendant/view-defendant.component.html +++ b/src/app/assets/components/view-defendant/view-defendant.component.html @@ -44,4 +44,12 @@

Inculpat

> +
+ +
diff --git a/src/app/assets/components/view-defendant/view-defendant.component.scss b/src/app/assets/components/view-defendant/view-defendant.component.scss index 1eec3d6..ab1d42a 100644 --- a/src/app/assets/components/view-defendant/view-defendant.component.scss +++ b/src/app/assets/components/view-defendant/view-defendant.component.scss @@ -19,4 +19,9 @@ flex-basis: 50%; } } + + .buttons { + display: flex; + justify-content: flex-end; + } } diff --git a/src/app/assets/components/view-defendant/view-defendant.component.ts b/src/app/assets/components/view-defendant/view-defendant.component.ts index e75dcd7..66608b4 100644 --- a/src/app/assets/components/view-defendant/view-defendant.component.ts +++ b/src/app/assets/components/view-defendant/view-defendant.component.ts @@ -1,14 +1,27 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Defendant, DefendantType, Identifier } from '@app/core'; +import * as fromDefendants from '@app/core/store'; +import { select, Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; @Component({ selector: 'app-view-defendant', templateUrl: './view-defendant.component.html', styleUrls: ['./view-defendant.component.scss'], }) -export class ViewDefendantComponent { +export class ViewDefendantComponent implements OnInit { @Input() defendant: Defendant; @Input() identifiers: Identifier[]; + @Output() defendantDeleted: EventEmitter + = new EventEmitter(); + + deleting$: Observable; + + constructor(private store: Store) { } + + ngOnInit(): void { + this.deleting$ = this.store.pipe(select(fromDefendants.getDefendantDeletingById(this.defendant.id))); + } getDefendantType(aIsPerson: boolean) { return aIsPerson ? DefendantType.Person.toString() : DefendantType.Company.toString(); @@ -17,4 +30,12 @@ export class ViewDefendantComponent { getIdentifier(aIdentifierType: number): Identifier { return this.identifiers.find(aIdentifier => aIdentifier.id === aIdentifierType); } + + onDefendantDeleted() { + const payload: fromDefendants.DeleteDefendantPayload = { + defendantId: this.defendant.id, + assetId: this.defendant.getAsset().id, + }; + this.defendantDeleted.emit(payload); + } } diff --git a/src/app/assets/containers/asset-detail/asset-detail.component.html b/src/app/assets/containers/asset-detail/asset-detail.component.html index 4f02dd1..1711fd6 100644 --- a/src/app/assets/containers/asset-detail/asset-detail.component.html +++ b/src/app/assets/containers/asset-detail/asset-detail.component.html @@ -53,6 +53,7 @@

{{theAsset.name}}

diff --git a/src/app/assets/containers/asset-detail/asset-detail.component.ts b/src/app/assets/containers/asset-detail/asset-detail.component.ts index a902ff4..c356268 100644 --- a/src/app/assets/containers/asset-detail/asset-detail.component.ts +++ b/src/app/assets/containers/asset-detail/asset-detail.component.ts @@ -175,6 +175,10 @@ export class AssetDetailComponent implements OnInit { this.setStateView(); } + onDefendantDeleted(payload: fromStore.DeleteDefendantPayload) { + this.store.dispatch(new fromStore.DeleteDefendant(payload)); + } + private resetSelectedProperty() { this.selectedProperty = undefined; } diff --git a/src/app/core/error-strings.ts b/src/app/core/error-strings.ts index 43ed27e..ba18467 100644 --- a/src/app/core/error-strings.ts +++ b/src/app/core/error-strings.ts @@ -7,4 +7,5 @@ export class ErrorStrings { static ERROR_FETCH_ASSETS = 'Could not fetch assets'; static ERROR_SEARCH_DECISIONS = 'Could not search decisions'; static ERROR_ADD_MINIMAL_ASSET = 'Could not add asset'; + static ERROR_DELETE_DEFENDANT = 'Could not delete defendant'; } diff --git a/src/app/core/http/defendants-api.service.ts b/src/app/core/http/defendants-api.service.ts index 6685631..ae673cc 100644 --- a/src/app/core/http/defendants-api.service.ts +++ b/src/app/core/http/defendants-api.service.ts @@ -24,4 +24,11 @@ export class DefendantsApiService { catchError(aError => observableThrowError(aError)) ); } + + public deleteDefendant(assetId: number, defendantId: number): Observable { + return this.http.delete(`${environment.api_url}/assets/${assetId}/defendants/${defendantId}`) + .pipe( + catchError(aError => observableThrowError(aError)) + ); + } } diff --git a/src/app/core/models/asset/asset-properties/defendant.model.ts b/src/app/core/models/asset/asset-properties/defendant.model.ts index 8b6e644..087d172 100644 --- a/src/app/core/models/asset/asset-properties/defendant.model.ts +++ b/src/app/core/models/asset/asset-properties/defendant.model.ts @@ -86,7 +86,7 @@ export class Defendant extends AssetProperty { identification: this.identification, isPerson: this.isPerson, name: this.name, - birthdate: this.birthdate.isValid() ? this.birthdate.toISOString() : undefined, + birthdate: this.birthdate && this.birthdate.isValid() ? this.birthdate.toISOString() : undefined, firstName: this.firstName, identifierId: this.identifierId, nationality: this.nationality, diff --git a/src/app/core/services/defendants.service.ts b/src/app/core/services/defendants.service.ts index 497d389..77670d1 100644 --- a/src/app/core/services/defendants.service.ts +++ b/src/app/core/services/defendants.service.ts @@ -35,6 +35,10 @@ export class DefendantsService { ) } + public deleteDefendant$(assetId: number, defendantId: number): Observable { + return this.defendantsApiService.deleteDefendant(assetId, defendantId); + } + private toRequest(aDefendant: Defendant): DefendantRequest { return { id: aDefendant.id, @@ -43,7 +47,7 @@ export class DefendantsService { identification: aDefendant.identification, isPerson: aDefendant.isPerson, name: aDefendant.name, - birthdate: aDefendant.birthdate.isValid() ? aDefendant.birthdate.format() : undefined, + birthdate: aDefendant.birthdate && aDefendant.birthdate.isValid() ? aDefendant.birthdate.format() : undefined, firstName: aDefendant.firstName, identifierId: aDefendant.identifierId, nationality: aDefendant.nationality, diff --git a/src/app/core/store/actions/defendants.action.ts b/src/app/core/store/actions/defendants.action.ts index e60ccd7..a75c5bb 100644 --- a/src/app/core/store/actions/defendants.action.ts +++ b/src/app/core/store/actions/defendants.action.ts @@ -47,6 +47,30 @@ export interface DefendantsSuccessPayload { asset: Asset; } +export interface DeleteDefendantPayload { + assetId: number; + defendantId: number; +} + +export const DEFENDANT_DELETE = '[Defendants] Delete Defendant'; +export const DEFENDANT_DELETE_FAIL = '[Defendants] Delete Defendant Fail'; +export const DEFENDANT_DELETE_SUCCESS = '[Defendants] Delete Defendant Success'; + +export class DeleteDefendant implements Action { + readonly type: string = DEFENDANT_DELETE; + constructor(public payload: DeleteDefendantPayload) {} +} + +export class DeleteDefendantFail implements Action { + readonly type: string = DEFENDANT_DELETE_FAIL; + constructor(public payload: number) {} +} + +export class DeleteDefendantSuccess implements Action { + readonly type: string = DEFENDANT_DELETE_SUCCESS; + constructor(public payload: number) {} +} + // action types export type DefendantsAction = CreateDefendant @@ -54,4 +78,7 @@ export type DefendantsAction = | CreateDefendantSuccess | LoadDefendants | LoadDefendantsFail - | LoadDefendantsSuccess; + | LoadDefendantsSuccess + | DeleteDefendant + | DeleteDefendantFail + | DeleteDefendantSuccess; diff --git a/src/app/core/store/effects/defendants.effect.ts b/src/app/core/store/effects/defendants.effect.ts index 7b653d6..eafcdb6 100644 --- a/src/app/core/store/effects/defendants.effect.ts +++ b/src/app/core/store/effects/defendants.effect.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ofType, Actions, Effect } from '@ngrx/effects'; import { of } from 'rxjs'; -import { catchError, filter, map, mergeMap, switchMap } from 'rxjs/operators'; +import { catchError, filter, map, mergeMap, switchMap, tap } from 'rxjs/operators'; import { Defendant } from '../../models'; import { DefendantsService } from '../../services'; @@ -54,6 +54,20 @@ export class DefendantsEffects { }) ); + @Effect() + deleteDefendant$ = this.actions$ + .pipe( + ofType(defendantsActions.DEFENDANT_DELETE), + map((action: defendantsActions.DeleteDefendant) => action.payload), + switchMap((aPayload: defendantsActions.DeleteDefendantPayload) => + this.defendantsService.deleteDefendant$(aPayload.assetId, aPayload.defendantId) + .pipe( + map((aResponse: number) => new defendantsActions.DeleteDefendantSuccess(aResponse)), + catchError(() => of(new defendantsActions.DeleteDefendantFail(aPayload.defendantId))) + ) + ) + ); + constructor( private actions$: Actions, private defendantsService: DefendantsService, diff --git a/src/app/core/store/reducers/defendants.reducer.ts b/src/app/core/store/reducers/defendants.reducer.ts index 0b93e36..cf6d59a 100644 --- a/src/app/core/store/reducers/defendants.reducer.ts +++ b/src/app/core/store/reducers/defendants.reducer.ts @@ -5,12 +5,16 @@ export interface DefendantsState { entities: { [id: number]: Defendant }; loaded: { [id: number]: boolean }; loading: { [id: number]: boolean }; + deleted: { [id: number]: boolean }; + deleting: { [id: number]: boolean }; } export const initialState: DefendantsState = { entities: {}, loaded: {}, loading: {}, + deleted: {}, + deleting: {}, }; export function reducer( @@ -85,6 +89,59 @@ export function reducer( } as DefendantsState; } + case fromDefendants.DEFENDANT_DELETE: { + const theDefendantId = (action.payload as fromDefendants.DeleteDefendantPayload).defendantId; + + return { + ...state, + deleting: { + ...state.deleting, + [theDefendantId]: true, + }, + } as DefendantsState + } + + case fromDefendants.DEFENDANT_DELETE_FAIL: { + const theDefendantId = action.payload; + + return { + ...state, + deleting: { + ...state.deleting, + [theDefendantId]: false, + }, + deleted: { + ...state.deleted, + [theDefendantId]: false, + }, + } as DefendantsState + } + + case fromDefendants.DEFENDANT_DELETE_SUCCESS: { + const theDefendantId: number = action.payload; + // const entities = state.entities; + // var theDefendants: Defendant[] = [] + // for(var key in Object.keys(entities)) { + // theDefendants = [...theDefendants, entities[key]]; + // } + // theDefendants = theDefendants.filter(d => d.id != theDefendantId); + const entities: { [id: number]: Defendant } = { ...state.entities } + delete entities[theDefendantId]; + + return { + ...state, + entities, + deleting: { + ...state.deleting, + [theDefendantId]: false, + }, + deleted: { + ...state.deleted, + [theDefendantId]: true, + }, + } as DefendantsState + } + default: { return { ...state, @@ -96,3 +153,5 @@ export function reducer( export const getDefendantsEntities = (state: DefendantsState) => state.entities; export const getDefendantsLoading = (state: DefendantsState) => state.loading; export const getDefendantsLoaded = (state: DefendantsState) => state.loaded; +export const getDefendantsDeleting = (state: DefendantsState) => state.deleting; +export const getDefendantsDeleted = (state: DefendantsState) => state.deleted; diff --git a/src/app/core/store/selectors/defendants.selectors.ts b/src/app/core/store/selectors/defendants.selectors.ts index e572518..a7dc525 100644 --- a/src/app/core/store/selectors/defendants.selectors.ts +++ b/src/app/core/store/selectors/defendants.selectors.ts @@ -52,3 +52,15 @@ export const getDefendantsLoadingForAssetId = (aAssetId: number) => createSelect getDefendantsLoading, (aLoading) => aLoading[aAssetId] || false ); + +export const getDefendantsDeleted = createSelector(getDefendantsState, fromDefendants.getDefendantsDeleted); +export const getDefendantDeleting = (aDefendantId: number) => createSelector( + getDefendantsDeleted, + (aDeleted) => aDeleted[aDefendantId] || false +); + +export const getDefendantsDeleting = createSelector(getDefendantsState, fromDefendants.getDefendantsDeleting); +export const getDefendantDeletingById = (aDefendantId: number) => createSelector( + getDefendantsDeleting, + (aDeleting) => aDeleting[aDefendantId] || false +);