diff --git a/Client/src/app/app.module.ts b/Client/src/app/app.module.ts index e43d952..39199aa 100644 --- a/Client/src/app/app.module.ts +++ b/Client/src/app/app.module.ts @@ -31,6 +31,7 @@ import { PhotoEditorComponent } from './components/members/photo-editor/photo-ed import { FileUploadModule } from 'ng2-file-upload'; import { TimeAgoPipe } from 'time-ago-pipe'; import { ListsResolver } from './resolvers/lists.resolver'; +import { MessagesResolver } from './resolvers/messages.resolver'; export function tokenGetter() { @@ -83,7 +84,8 @@ export function tokenGetter() { MemberDetailResolver, MemberListResolver, MemberEditResolver, - ListsResolver + ListsResolver, + MessagesResolver ], bootstrap: [AppComponent] }) diff --git a/Client/src/app/components/messages/messages.component.ts b/Client/src/app/components/messages/messages.component.ts index 1ff6603..38dfecc 100644 --- a/Client/src/app/components/messages/messages.component.ts +++ b/Client/src/app/components/messages/messages.component.ts @@ -1,4 +1,10 @@ import { Component, OnInit } from '@angular/core'; +import { Message } from '../../models/message' +import { Pagination, PaginatedResult } from 'src/app/models/pagination'; +import { AuthService } from 'src/app/services/auth.service'; +import { ActivatedRoute } from '@angular/router'; +import { AlertifyService } from 'src/app/services/alertify.service'; +import { UserService } from 'src/app/services/user.service'; @Component({ selector: 'app-messages', @@ -6,10 +12,40 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./messages.component.css'] }) export class MessagesComponent implements OnInit { + messages: Message[]; + pagination: Pagination; + messageContainer: string = "Unread"; - constructor() { } + constructor( + private authService: AuthService, + private userService: UserService, + private route: ActivatedRoute, + private alertify: AlertifyService) { } ngOnInit() { + this.route.data.subscribe(data => { + this.messages = data['messages'].result; + this.pagination = data['messages'].pagination; + }); + } + + loadMessages() { + this.userService.getMessages( + this.authService.decodedToken.nameid, + this.pagination.currentPage, + this.pagination.itemsPerPage, + this.messageContainer) + .subscribe((result: PaginatedResult) => { + this.messages = result.result; + this.pagination = result.pagination; + }, error => { + this.alertify.error(error); + }); + } + + pageChanged(event: any): void { + this.pagination.currentPage = event.page; + this.loadMessages; } } diff --git a/Client/src/app/models/message.ts b/Client/src/app/models/message.ts new file mode 100644 index 0000000..3a20a01 --- /dev/null +++ b/Client/src/app/models/message.ts @@ -0,0 +1,12 @@ +export interface Message { + id: number; + senderId: number; + senderKnownAs: string; + senderPhotoUrl: string; + recipientId: number; + recipientKnownAs: string; + content: string; + markedAsRead: boolean; + readDate: Date; + messageSent: Date; +} diff --git a/Client/src/app/resolvers/messages.resolver.ts b/Client/src/app/resolvers/messages.resolver.ts new file mode 100644 index 0000000..28f9336 --- /dev/null +++ b/Client/src/app/resolvers/messages.resolver.ts @@ -0,0 +1,31 @@ +import { Injectable } from "@angular/core"; +import { User } from "../models/user"; +import { UserService } from "../services/user.service"; +import { Resolve, Router, ActivatedRouteSnapshot } from "@angular/router"; +import { AlertifyService } from "../services/alertify.service"; +import { Observable, of } from "rxjs"; +import { catchError } from "rxjs/operators"; +import { Message } from "../models/message"; +import { AuthService } from "../services/auth.service"; + +@Injectable() +export class MessagesResolver implements Resolve { + pageNumber: number = 1; + pageSize: number = 12; + messageContainer: string = "Unread"; + + constructor( + private userService: UserService, + private authService: AuthService, + private router: Router, + private alertify: AlertifyService) { } + + resolve(route: ActivatedRouteSnapshot): Observable { + return this.userService.getMessages(this.authService.decodedToken.nameid, this.pageNumber, this.pageSize, this.messageContainer) + .pipe(catchError(error => { + this.alertify.error('Problem retrieving messages'); + this.router.navigate(['/home']); + return of(null); + })); + } +} diff --git a/Client/src/app/routes.ts b/Client/src/app/routes.ts index b4d9b75..237dfe7 100644 --- a/Client/src/app/routes.ts +++ b/Client/src/app/routes.ts @@ -11,6 +11,7 @@ import { MemberEditComponent } from './components/members/member-edit/member-edi import { MemberEditResolver } from './resolvers/member-edit.resolver'; import { UnsavedChangesGuard } from './guards/unsaved-changes.guard'; import { ListsResolver } from './resolvers/lists.resolver'; +import { MessagesResolver } from './resolvers/messages.resolver'; export const appRoutes: Routes = [ { path: '', component: HomeComponent }, @@ -22,7 +23,7 @@ export const appRoutes: Routes = [ { path: 'members', component: MemberListComponent, resolve: { users: MemberListResolver } }, { path: 'members/edit', component: MemberEditComponent, resolve: { user: MemberEditResolver }, canDeactivate: [UnsavedChangesGuard] }, { path: 'members/:id', component: MemberDetailComponent, resolve: { user: MemberDetailResolver } }, - { path: 'messages', component: MessagesComponent }, + { path: 'messages', component: MessagesComponent, resolve: { messages: MessagesResolver } }, { path: 'lists', component: ListsComponent, resolve: { users: ListsResolver } } ] }, diff --git a/Client/src/app/services/user.service.ts b/Client/src/app/services/user.service.ts index 9e9bdf6..3812edf 100644 --- a/Client/src/app/services/user.service.ts +++ b/Client/src/app/services/user.service.ts @@ -4,6 +4,7 @@ import { Observable } from 'rxjs'; import { User } from '../models/user'; import { PaginatedResult } from '../models/pagination'; import { map } from 'rxjs/operators'; +import { Message } from '../models/message'; @Injectable({ @@ -15,7 +16,7 @@ export class UserService { constructor(private http: HttpClient) { } getUsers(page?, itemsPerPage?, userParameters?, likesParameter?): Observable> { - + const paginatedResult: PaginatedResult = new PaginatedResult(); let params = new HttpParams(); @@ -42,6 +43,7 @@ export class UserService { if (response.headers.get('Pagination') != null) { paginatedResult.pagination = JSON.parse(response.headers.get('Pagination')); } + return paginatedResult; })); } @@ -65,4 +67,25 @@ export class UserService { likeUser(userId: number, recipientId: number) { return this.http.post(`${this.usersUrl}${userId}/like/${recipientId}`, {}); } + + getMessages(userId: number, page?, itemsPerPage?, messageContainer?): Observable> { + const paginatedResult: PaginatedResult = new PaginatedResult(); + let params = new HttpParams(); + params = params.append('MessageContainer', messageContainer); + + if (page != null && itemsPerPage != null) { + params = params.append('pageNumber', page); + params = params.append('pageSize', itemsPerPage); + } + + return this.http.get(`${this.usersUrl}${userId}/messages`, { observe: 'response', params }) + .pipe(map(response => { + paginatedResult.result = response.body; + if (response.headers.get('Pagination') != null) { + paginatedResult.pagination = JSON.parse(response.headers.get('Pagination')); + } + + return paginatedResult; + })); + } } diff --git a/Controllers/MessagesController.cs b/Controllers/MessagesController.cs index f7c4286..95a29c6 100644 --- a/Controllers/MessagesController.cs +++ b/Controllers/MessagesController.cs @@ -73,6 +73,23 @@ public async Task GetMessages(int userId, [FromQuery]MessageParam return Ok(messagesResource); } + [HttpGet("thread/{recipientId}")] + public async Task GetMessageThread(int userId, int recipientId) + { + int id = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value); + + if (id != userId) + { + return Unauthorized(); + } + + var messages = await _repo.GetMessageThread(userId, recipientId); + + var messagesResource = _mapper.Map, IEnumerable>(messages); + + return Ok(messagesResource); + } + [HttpPost] public async Task SendMessage(int userId, SendMessageResource sendMessageResource) { diff --git a/Data/FriendRepository.cs b/Data/FriendRepository.cs index c10cd29..afcbeae 100644 --- a/Data/FriendRepository.cs +++ b/Data/FriendRepository.cs @@ -150,7 +150,16 @@ public async Task> GetMessages(MessageParameters messageParam public async Task> GetMessageThread(int userId, int recipientId) { - throw new NotImplementedException(); + var messages = await _context.Messages + .Include(u => u.Sender) + .ThenInclude(p => p.Photos) + .Include(u => u.Recipient) + .ThenInclude(p => p.Photos) + .Where(m => m.RecipientId == userId && m.SenderId == recipientId || m.RecipientId == recipientId && m.SenderId == userId) + .OrderByDescending(m => m.MessageSent) + .ToListAsync(); + + return messages; } } }