Skip to content

Instantly share code, notes, and snippets.

@vinicius91
Created March 26, 2019 12:46
Show Gist options
  • Select an option

  • Save vinicius91/f850d85d3cf980f0ea95e1a07d7153c3 to your computer and use it in GitHub Desktop.

Select an option

Save vinicius91/f850d85d3cf980f0ea95e1a07d7153c3 to your computer and use it in GitHub Desktop.
Reducer Example @ngrx
import { Component, OnInit } from '@angular/core';
import { Recipient } from './model';
import { GetRecipientStart } from './store';
import {
recipientLoading,
selectAllRecipient
} from './store/recipient.selector';
import { Observable } from 'rxjs';
import { MatTableDataSource } from '@angular/material';
import { select, Store } from '@ngrx/store';
import { AppState } from 'src/app/reducers';
@Component({
selector: 'app-recipient',
templateUrl: './recipient.component.html',
styleUrls: ['./recipient.component.scss']
})
export class RecipientComponent implements OnInit {
loading$: Observable<boolean>;
recipients$: Observable<Recipient[]>;
recipients: MatTableDataSource<Recipient>;
constructor(private store: Store<AppState>) {}
ngOnInit() {
this.store.dispatch(new GetRecipientStart());
this.loading$ = this.store.pipe(select(recipientLoading));
this.recipients$ = this.store.pipe(select(selectAllRecipient));
this.recipients$.subscribe((data) => {
this.recipients = new MatTableDataSource<Recipient>(data);
});
}
}
import { Action } from '@ngrx/store';
import { Recipient } from '../model';
import { UserByEntity } from 'src/app/shared/model';
export enum RecipientActionTypes {
GetRecipientStart = '[Recipient List Page] Get Recipient start',
GetRecipientSuccess = '[Recipient API] Get Recipient success',
GetRecipientError = '[Recipient API] Get Recipient error',
FindRecipientStart = '[Recipient Detail Page] Find Recipient start',
FindRecipientSuccess = '[Recipient API] Find Recipient success',
FindRecipientError = '[Recipient API] Find Recipient error',
GetUserByEntityListStart = '[Recipient Detail Page] Get user by entity Start',
GetUserByEntityListSuccess = '[Recipient Detail Page] Get user by entity Success',
GetUserByEntityListError = '[Recipient Detail Page] Get user by entity Error',
AlterUserSendEmailStatusStart = '[Recipient Users Page] Alter user send email status Start',
AlterUserSendEmailStatusSuccess = '[Recipient Users Page] Alter user send email status Success',
AlterUserSendEmailStatusError = '[Recipient Users Page] Alter user send email status Error'
}
export class GetRecipientStart implements Action {
readonly type = RecipientActionTypes.GetRecipientStart;
}
export class GetRecipientSuccess implements Action {
readonly type = RecipientActionTypes.GetRecipientSuccess;
constructor(public payload: { recipients: Recipient[] }) {}
}
export class GetRecipientError implements Action {
readonly type = RecipientActionTypes.GetRecipientError;
}
export class FindRecipientStart implements Action {
readonly type = RecipientActionTypes.FindRecipientStart;
constructor(public payload: { recipientId: number }) {}
}
export class FindRecipientSuccess implements Action {
readonly type = RecipientActionTypes.FindRecipientSuccess;
constructor(public payload: { recipient: Recipient }) {}
}
export class FindRecipientError implements Action {
readonly type = RecipientActionTypes.FindRecipientError;
}
export class GetUserByEntityListStart implements Action {
readonly type = RecipientActionTypes.GetUserByEntityListStart;
constructor(public payload: { entityId: number }) {}
}
export class GetUserByEntityListSuccess implements Action {
readonly type = RecipientActionTypes.GetUserByEntityListSuccess;
constructor(public payload: { usersByEntity: UserByEntity[] }) {}
}
export class GetScheduleEmailListError implements Action {
readonly type = RecipientActionTypes.GetUserByEntityListError;
}
export class AlterUserSendEmailStatusStart implements Action {
readonly type = RecipientActionTypes.AlterUserSendEmailStatusStart;
constructor(public payload: { userId: number; include: boolean }) {}
}
export class AlterUserSendEmailStatusSuccess implements Action {
readonly type = RecipientActionTypes.AlterUserSendEmailStatusSuccess;
constructor(public payload: { userId: number; success: boolean }) {}
}
export class AlterUserSendEmailStatusError implements Action {
readonly type = RecipientActionTypes.AlterUserSendEmailStatusError;
}
export type RecipientActions =
| GetRecipientStart
| GetRecipientSuccess
| GetRecipientError
| FindRecipientStart
| FindRecipientSuccess
| FindRecipientError
| GetUserByEntityListStart
| GetUserByEntityListSuccess
| GetScheduleEmailListError
| AlterUserSendEmailStatusStart
| AlterUserSendEmailStatusSuccess
| AlterUserSendEmailStatusError;
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<app-recipient-table
><div class="spinner-container" *ngIf="(loading$ | async)">
<app-truck-loading></app-truck-loading></div
></app-recipient-table>
</div>
<app-modal baseUrl="/settings/recipient"></app-modal>
</div>
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { mergeMap, map } from 'rxjs/operators';
import { RecipientService } from './side-effects';
import {
GetRecipientStart,
RecipientActionTypes,
GetRecipientSuccess,
GetUserByEntityListStart,
GetUserByEntityListSuccess,
AlterUserSendEmailStatusStart,
AlterUserSendEmailStatusSuccess,
AlterUserSendEmailStatusError
} from './recipient.actions';
@Injectable()
export class RecipientEffects {
constructor(private actions$: Actions, private service: RecipientService) {}
@Effect()
getAll$ = this.actions$.pipe(
ofType<GetRecipientStart>(RecipientActionTypes.GetRecipientStart),
mergeMap((action) => this.service.findAllRecipients()),
map((response) => {
return new GetRecipientSuccess({
recipients: response.results
});
})
);
@Effect()
getAllUsersByEntity$ = this.actions$.pipe(
ofType<GetUserByEntityListStart>(
RecipientActionTypes.GetUserByEntityListStart
),
mergeMap((action) =>
this.service.findUsersByEntity(action.payload.entityId)
),
map((usersByEntity) => {
return new GetUserByEntityListSuccess({
usersByEntity
});
})
);
@Effect()
alterUserSendEmailStatus$ = this.actions$.pipe(
ofType<AlterUserSendEmailStatusStart>(
RecipientActionTypes.AlterUserSendEmailStatusStart
),
mergeMap((action) =>
this.service.alterUserSendEmailStatus(
action.payload.userId,
action.payload.include
)
),
map(({ userId, success }) => {
if (success) {
return new AlterUserSendEmailStatusSuccess({
userId,
success
});
} else {
return new AlterUserSendEmailStatusError();
}
})
);
}
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Recipient } from '../model';
import { RecipientActions, RecipientActionTypes } from './recipient.actions';
import { UserByEntity } from 'src/app/shared/model';
export interface RecipientState extends EntityState<Recipient> {
loading: boolean;
loadingEmails: boolean;
usersByEntity: UserByEntity[];
}
export const adapter: EntityAdapter<Recipient> = createEntityAdapter<
Recipient
>();
export const initialRecipientState: RecipientState = adapter.getInitialState({
loading: false,
loadingEmails: false,
usersByEntity: []
});
export function recipientReducer(
state = initialRecipientState,
action: RecipientActions
): RecipientState {
switch (action.type) {
case RecipientActionTypes.GetRecipientStart:
return { ...state, loading: true };
case RecipientActionTypes.GetUserByEntityListStart:
return { ...state, loadingEmails: true };
case RecipientActionTypes.GetRecipientSuccess:
return adapter.addAll(action.payload.recipients, {
...state,
loading: false
});
case RecipientActionTypes.GetUserByEntityListSuccess:
return {
...state,
usersByEntity: action.payload.usersByEntity,
loadingEmails: false
};
case RecipientActionTypes.AlterUserSendEmailStatusStart:
return { ...state, loadingEmails: true };
case RecipientActionTypes.AlterUserSendEmailStatusSuccess:
const user = state.usersByEntity.find(
(x) => x.user.id === action.payload.userId
);
const notificationTypes =
user.notificationTypes.length > 0 ? [] : ['SCHEDULE'];
const usersByEntity = [
...state.usersByEntity.filter(
(x) => x.user.id !== action.payload.userId
),
{ ...user, notificationTypes }
];
return {
...state,
loadingEmails: false,
usersByEntity
};
default:
return state;
}
}
export const {
selectAll,
selectEntities,
selectIds,
selectTotal
} = adapter.getSelectors();
import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromRecipient from './recipient.reducer';
import { PageQuery } from 'src/app/shared/model';
export const selectRecipientState = createFeatureSelector<
fromRecipient.RecipientState
>('recipient');
export const selectRecipientById = (recipientId: number) =>
createSelector(
selectRecipientState,
(recipientState) => recipientState.entities[recipientId]
);
export const selectAllRecipient = createSelector(
selectRecipientState,
fromRecipient.selectAll
);
export const recipientLoading = createSelector(
selectRecipientState,
(recipientState) => recipientState.loading
);
export const selectRecipientPage = (page: PageQuery) =>
createSelector(
selectAllRecipient,
(allRecipients) => {
const start = page.pageIndex * page.pageSize,
end = start + page.pageSize;
return allRecipients.slice(start, end);
}
);
export const selectRecipientsTotal = createSelector(
selectAllRecipient,
(recipients) => recipients.length
);
export const emailsToSendLoading = createSelector(
selectRecipientState,
(recipientState) => recipientState.loadingEmails
);
export const selectUsersByEntity = createSelector(
selectRecipientState,
(recipientState) => recipientState.usersByEntity
);
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { Page } from 'src/app/shared/model/page';
import { AppState } from 'src/app/reducers';
import { Store } from '@ngrx/store';
import { Recipient } from '../../model';
import { UserByEntity } from 'src/app/shared/model';
import { NotificationService, NotificationType } from 'src/app/core/services';
import { NotificationOrigin } from 'src/app/core/services/notification-origin.enum';
import { NotificationAlignment } from 'src/app/core/services/notification-alignment.enum';
@Injectable()
export class RecipientService {
private httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'text/plain',
Accept: 'text/plain'
})
};
API_URL: string = environment.API_URL;
constructor(
private http: HttpClient,
private notification: NotificationService
) {}
findAllRecipients(): Observable<Page<Recipient>> {
return this.http
.get<any>(`${this.API_URL}/recipient?limit=100`, this.httpOptions)
.pipe(
catchError((error) => {
console.error(error);
this.notification.notify(
NotificationOrigin.TOP,
NotificationAlignment.RIGHT,
NotificationType.DANGER,
'Ocorreu um erro em sua solicitação'
);
return [];
}),
map((res) => res)
);
}
findUsersByEntity(entityId: number): Observable<UserByEntity[]> {
return this.http
.get<UserByEntity[]>(
`${
this.API_URL
}/user-by-entity-id?entityId=${entityId}&entityType=RECIPIENT`,
this.httpOptions
)
.pipe(
catchError((error) => {
console.error(error);
this.notification.notify(
NotificationOrigin.TOP,
NotificationAlignment.RIGHT,
NotificationType.DANGER,
'Ocorreu um erro em sua solicitação'
);
return [];
}),
map((res) => res)
);
}
alterUserSendEmailStatus(
userId: number,
include: boolean
): Observable<{ userId: number; success: boolean }> {
const body = include ? ['SCHEDULE'] : [];
return this.http
.post<boolean>(
`${this.API_URL}/user/${userId}/notification`,
body,
this.httpOptions
)
.pipe(
catchError((error) => {
console.error(error);
this.notification.notify(
NotificationOrigin.TOP,
NotificationAlignment.RIGHT,
NotificationType.DANGER,
'Ocorreu um erro em sua solicitação'
);
return [];
}),
map((success) => {
return { userId, success };
})
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment