Skip to content

Commit

Permalink
Merge pull request #50 from CS3219-AY2425S1/ivan-N2
Browse files Browse the repository at this point in the history
Add Profile Page, Update to User Svc
  • Loading branch information
lynnetteeee authored Nov 6, 2024
2 parents a625c99 + 648ad60 commit b82f153
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 17 deletions.
2 changes: 1 addition & 1 deletion peer-prep-collab/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const startConsume = async (onMessage: (message: Message) => void) => {

export const updateUserService = (session: Session) => {
channel.assertQueue(ADD_SESSION_QUEUE,{durable: true})
channel.sendToQueue(ADD_SESSION_QUEUE, Buffer.from(session.toString()))
channel.sendToQueue(ADD_SESSION_QUEUE, Buffer.from(JSON.stringify(session)))
}

// To implement generation of session URL @LYNETTE @YUANTING -
Expand Down
1 change: 1 addition & 0 deletions peer-prep-fe/src/app/app.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
font-size: 15px;
padding: 5px 10px;
margin-right: 1vw;
text-decoration: none;
}

.logout-button {
Expand Down
2 changes: 1 addition & 1 deletion peer-prep-fe/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<nav class="navbar" *ngIf="!hideNavbar">
<header id="header" class="cursor-pointer" routerLink="/">Peer Prep</header>
<a *ngIf="userName" class="username">-{{ userName }}-</a>
<a *ngIf="userName" routerLink="/profile" class="username">-{{ userName }}-</a>
<a class="button" routerLink="/question-list" routerLinkActive="activebutton"
>Question List</a
>
Expand Down
3 changes: 2 additions & 1 deletion peer-prep-fe/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import { adminGuard } from "./authService/admin.guard"
import {CollaborativeEditorComponent} from "../code-editor/collaborative-editor/collaborative-editor.component";
import {CollabPageComponent} from "../collab-page/collab-page.component";
import {loginGuard} from "./authService/login.guard";
import { ProfilePageComponent } from "./profile-page/profile-page.component"

export const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "login", component: LoginComponent, canActivate: [loginGuard]},
{ path: "create-account", component: CreateAccountComponent },
{ path: "profile", component: ProfilePageComponent, canActivate: [authGuard]},
{ path: "admin-controls", component: AdminComponent, canActivate: [adminGuard] },
{ path: "add-question", component: AddPageComponent },
{ path: "edit-question", component: EditPageComponent },
Expand All @@ -34,6 +36,5 @@ export const routes: Routes = [
{ path: "editor", component: CollaborativeEditorComponent }
]
},

{ path: "code-editor", component: CollaborativeEditorComponent }
];
38 changes: 38 additions & 0 deletions peer-prep-fe/src/app/profile-page/profile-page.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.container {
display: flex;
color: rgb(255, 78, 196);
flex-direction: column;
}

.header {
color: white;
font-size: 2rem;
width: 90%;
margin-top: 5vh;
font-weight: 600;
}

.inner-container {
margin-top: 3vh;
background-color: rgb(34, 36, 39);
opacity: 0.9;
border-radius: 6px;
width: 90%;
}
.details {
margin-top: 2vh;
margin-left: 1vw;
}

.field {
font-family: "Signika Negative", sans-serif;
font-weight: 600;
}

.value {
font-family: "Signika Negative", sans-serif;
font-weight: 600;
font-size: 16px;
border-radius: 10px;
color: white;
}
24 changes: 24 additions & 0 deletions peer-prep-fe/src/app/profile-page/profile-page.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div class="container">
<div class="header">Profile</div>
<div class="inner-container">
<div class="details">
<h2 class="field">Account Id:</h2>
<p class="value">{{id}}</p>
<h2 class="field">Name:</h2>
<p class="value">{{userName}}</p>
<h2 class="field">Email:</h2>
<p class="value">{{email}}</p>
<h2 class="field">Questions Attempted:</h2>
<ul class="value">
<li *ngFor="let i of matches">
<p>{{i.question_title}} ({{i.question_complexity}}) - {{i.dateTime}}</p>
</li>
</ul>
</div>



</div>


</div>
23 changes: 23 additions & 0 deletions peer-prep-fe/src/app/profile-page/profile-page.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ProfilePageComponent } from './profile-page.component';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ProfilePageComponent]
})
.compileComponents();

fixture = TestBed.createComponent(ProfilePageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
40 changes: 40 additions & 0 deletions peer-prep-fe/src/app/profile-page/profile-page.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Component } from '@angular/core';
import { authService } from '../authService/authService';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-profile-page',
standalone: true,
imports: [CommonModule],
templateUrl: './profile-page.component.html',
styleUrl: './profile-page.component.css'
})
export class ProfilePageComponent {
id: string | null = null
userName: string | null = null
email: string | null = null
matches: {
question_id: string,
question_title: string,
question_complexity: string,
question_description: string,
question_categories: string[],
dateTime: string
}[] = []

constructor(private authService: authService) {}

//Check if username is logged in, set this.userName
ngOnInit(): void {
this.authService.currentUserValue.subscribe((user) => {
if (user) {
const {username, email, id, matches} = user.data;
this.userName = username
this.email = email
this.id = id
this.matches = matches
}
})
}

}
25 changes: 14 additions & 11 deletions peer-prep-fe/src/app/userService/user-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@ import { HttpClient, HttpHeaders } from "@angular/common/http"
import { Injectable } from "@angular/core"
import { Observable } from "rxjs"

const userJson = sessionStorage.getItem("userData")
const token = userJson !== null ? JSON.parse(userJson).data.accessToken : ""

const headers = new HttpHeaders({
Authorization: `Bearer ${token}`
})

@Injectable({ providedIn: "root" })
export class UserService {

private baseUrl = "http://localhost:3001/users"
constructor(private http: HttpClient) {}

readonly userJson = sessionStorage.getItem("userData")
readonly token = this.userJson !== null ? JSON.parse(this.userJson).data.accessToken : ""

readonly headers: HttpHeaders = new HttpHeaders({
Authorization: `Bearer ${this.token}`
})


getAllUsers(): Observable<any> {
return this.http.get<any>(this.baseUrl, { headers })
return this.http.get<any>(this.baseUrl, { headers: this.headers })
}

saveUser(body: any): Observable<any> {
return this.http.patch(`${this.baseUrl}/${body.id}`, body, { headers })
return this.http.patch(`${this.baseUrl}/${body.id}`, body, { headers: this.headers })
}

updatePrivilege(user: any): Observable<any> {
Expand All @@ -30,16 +33,16 @@ export class UserService {
isAdmin: user.isAdmin
}
return this.http.patch(`${this.baseUrl}/${user.id}/privilege`, body, {
headers
headers: this.headers
})
}

getCurrUserId(): string {
return userJson !== null ? JSON.parse(userJson).data.id : "";
return this.userJson !== null ? JSON.parse(this.userJson).data.id : "";
}

getUser(id: string): Observable<any> {
return this.http.get<any>(`${this.baseUrl}/${id}`, { headers });
return this.http.get<any>(`${this.baseUrl}/${id}`, { headers: this.headers });
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export class MatchModalComponent implements OnInit {
this.queueName = params['queueName'];
});
await this.setMyUsername();
console.log('curr username', this.myUsername);
this.userData = {difficulty: this.difficulty, topic: this.category, user_id: this.userId, username: this.myUsername};
console.log('userData', this.userData);
this.findMatch();
Expand Down
3 changes: 2 additions & 1 deletion peer-prep-user/user-service/controller/user-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ export function formatUserResponse(user) {
username: user.username,
email: user.email,
isAdmin: user.isAdmin,
createdAt: user.createdAt
createdAt: user.createdAt,
matches: user.matches
}
}
23 changes: 23 additions & 0 deletions peer-prep-user/user-service/model/repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,29 @@ export async function updateUserById(userId, username, email, password) {
)
}

export async function updateUsers(user1, user2, question) {
console.log("Here")
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var time = String(today.getHours() + ":" + today.getMinutes())
var yyyy = today.getFullYear();
var dateTime = dd + '/' + mm + '/' + yyyy + " at " + time + " HOURS";
await UserModel.updateMany(
{username: user1},
{ $push:
{matches: {...{matchedUser: user2},...question, dateTime}}
}
)

await UserModel.updateMany(
{username: user2},
{ $push:
{matches: {...{matchedUser: user1},...question, dateTime}}
}
)
}

export async function updateUserPrivilegeById(userId, isAdmin) {
return UserModel.findByIdAndUpdate(
userId,
Expand Down
4 changes: 4 additions & 0 deletions peer-prep-user/user-service/model/user-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const UserModelSchema = new Schema({
type: Boolean,
required: true,
default: false
},
matches: {
type: Array,
default: []
}
})

Expand Down
38 changes: 38 additions & 0 deletions peer-prep-user/user-service/mq-consumer/consumer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import amqp from "amqplib"
import { updateUsers } from "../model/repository.js";

const QUEUE = 'add_session_queue'
let channel;

export const connectToRabbitMQ = async () => {
try {
const amqpServer = "amqps://lguugvwb:[email protected]/lguugvwb"
const connection = await amqp.connect(amqpServer)
channel = await connection.createChannel()
console.log("Connected to RabbitMQ")
} catch (err) {
console.log(err)
}
}

const startConsume = async (onMessage) => {
try {
await channel.assertQueue(QUEUE, {
durable: true,
})
channel.consume(QUEUE, msg => {
if (msg) {
onMessage(JSON.parse(Buffer.from(msg.content)))
channel.ack(msg)
}
})
} catch (err) {
console.log(err)
}
}

async function onMessage(message) {
updateUsers(message.users.username1, message.users.username2, message.question)
}

export const initConsumer = () => startConsume(onMessage)
Loading

0 comments on commit b82f153

Please sign in to comment.