Skip to content

Commit b222ca1

Browse files
authored
Merge pull request #449 from CodingFactory-Repos/develop-G5
Develop g5
2 parents 283ea6a + 1fb9bf3 commit b222ca1

10 files changed

Lines changed: 263 additions & 111 deletions

File tree

back-end/src/base/ideasComments/ideasComments.module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,18 @@ import { UsersRepository } from 'src/base/users/users.repository';
77
import { IdeasCommentsRepository } from 'src/base/ideasComments/ideasComments.repository';
88
import { IdeasCommentsService } from 'src/base/ideasComments/ideasComments.service';
99
import { IdeasCommentsController } from 'src/base/ideasComments/ideasComments.controller';
10+
import { IdeasCommentGateway } from '@/common/gateways/ideasComment.global.gateway';
11+
import { JwtService } from '@nestjs/jwt';
1012

1113
@Module({
1214
imports: [DatabaseModule, forwardRef(() => AuthModule)],
13-
providers: [IdeasCommentsService, IdeasCommentsRepository, UsersRepository],
15+
providers: [
16+
IdeasCommentsService,
17+
IdeasCommentsRepository,
18+
UsersRepository,
19+
IdeasCommentGateway,
20+
JwtService,
21+
],
1422
controllers: [IdeasCommentsController],
1523
exports: [IdeasCommentsService, IdeasCommentsRepository],
1624
})
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { JwtService } from '@nestjs/jwt';
2+
import { Server } from 'socket.io';
3+
import { Inject, UseFilters, forwardRef } from '@nestjs/common';
4+
import {
5+
WebSocketGateway,
6+
WebSocketServer,
7+
OnGatewayInit,
8+
OnGatewayConnection,
9+
OnGatewayDisconnect,
10+
SubscribeMessage,
11+
} from '@nestjs/websockets';
12+
13+
import { WSServiceErrorCatcher } from '@/common/decorators/ws.catch.decorator';
14+
import {
15+
MaterialSocket,
16+
MaterialAuthMiddleware,
17+
} from '@/common/middlewares/socket.ideasComment.middleware';
18+
import { IdeasCommentsRepository } from '@/base/ideasComments/ideasComments.repository';
19+
import { IdeaComment } from '@/base/ideasComments/interfaces/ideasComments.interface';
20+
21+
@UseFilters(WSServiceErrorCatcher)
22+
@WebSocketGateway({
23+
transports: ['websocket'],
24+
cors: {
25+
origin: '*', // to be defined later
26+
},
27+
namespace: 'ideasEquipements',
28+
})
29+
export class IdeasCommentGateway
30+
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
31+
{
32+
constructor(
33+
@Inject(forwardRef(() => IdeasCommentsRepository))
34+
private ideasCommentsRepository: IdeasCommentsRepository,
35+
private readonly jwtService: JwtService,
36+
) {}
37+
@WebSocketServer() server: Server;
38+
items = [];
39+
40+
afterInit(server: Server) {
41+
server.use(MaterialAuthMiddleware(this.jwtService));
42+
}
43+
44+
async handleConnection(client: MaterialSocket) {
45+
client.join(client.roomId);
46+
client.to(client.roomId).emit('peer-connected', client.id);
47+
}
48+
49+
async handleDisconnect(client: MaterialSocket) {
50+
client.to(client.roomId).emit('peer-disconnected', client.id);
51+
}
52+
53+
@SubscribeMessage('add-comment')
54+
async addComment(client: MaterialSocket, data: IdeaComment) {
55+
56+
this.items.unshift(data);
57+
58+
client.to(client.roomId).emit('comment-added', this.items[0]);
59+
}
60+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { JwtPayload } from '@/auth/interfaces/jwt.interface';
2+
import { Socket } from 'socket.io';
3+
import { JwtService } from '@nestjs/jwt';
4+
import { ObjectId } from 'mongodb';
5+
6+
import { parseCookieString } from '@/common/helpers/string.helper';
7+
import { config } from '@/config/config';
8+
import { Logger as NestLogger } from '@nestjs/common';
9+
import { WSServiceError } from '@/common/decorators/ws.catch.decorator';
10+
11+
export interface MaterialSocket extends Socket {
12+
user: JwtPayload;
13+
roomId: string;
14+
}
15+
16+
export type MaterialMiddleware = (socket: Socket, next: (err?: Error) => void) => void;
17+
18+
export const MaterialAuthMiddleware = (jwtService: JwtService): MaterialMiddleware => {
19+
return (socket: MaterialSocket, next) => {
20+
try {
21+
const materialCookies = socket.handshake.headers.cookie || '';
22+
const tokenMaterialCookie = parseCookieString(materialCookies);
23+
if (Object.keys(tokenMaterialCookie).length === 0)
24+
throw new Error('Could not find any cookies in the ws headers');
25+
const parsedTokenCookie = JSON.parse(tokenMaterialCookie['token']);
26+
const materialToken = parsedTokenCookie['token'];
27+
if (!materialToken) throw new Error('Token is undefined');
28+
29+
const materialPayload = <JwtPayload>(
30+
jwtService.verify(materialToken, { secret: config.jwt.secret })
31+
);
32+
if (!materialPayload?.id || !(materialPayload?.role >= 0 && materialPayload?.role <= 3))
33+
throw new Error('The jwt content is invalid');
34+
materialPayload.id = new ObjectId(materialPayload.id);
35+
36+
const roomId = socket.handshake.auth.roomId;
37+
38+
socket.roomId = roomId;
39+
socket.user = materialPayload;
40+
next();
41+
} catch (err) {
42+
if (err instanceof Error) {
43+
NestLogger.error(err.message);
44+
}
45+
46+
next(
47+
new WSServiceError('UNAUTHORIZED', 'You do not have the rights to access this resource'),
48+
);
49+
}
50+
};
51+
};

front-end/src/components/materials/ButtonsMaterials.vue

Lines changed: 108 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
11
<template>
22
<div class="mb-5"></div>
33
<form @submit.prevent="addMaterial">
4-
<div class="form-group relative z-0 w-full mb-6">
5-
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
6-
>Name</label
7-
>
8-
<input
9-
type="text"
10-
id="name"
11-
v-model="name"
12-
name="name"
13-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
14-
placeholder="Enter name"
15-
required
16-
/>
4+
<div class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2">
5+
<div>
6+
<label for="name" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
7+
>Nom</label
8+
>
9+
<input
10+
type="text"
11+
id="name"
12+
v-model="name"
13+
name="name"
14+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
15+
placeholder="Entrez le nom du matériel"
16+
required
17+
/>
18+
</div>
19+
<div>
20+
<label for="Type" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
21+
>Type</label
22+
>
23+
<select
24+
id="type"
25+
v-model="type"
26+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
27+
required
28+
>
29+
<option value="" disabled selected>Sélectionnez le type</option>
30+
<option value="Hardware">Hardware</option>
31+
<option value="Mac">Mac</option>
32+
<option value="Livre">Livres</option>
33+
</select>
34+
</div>
1735
</div>
18-
19-
<div class="form-group">
20-
<label for="Type" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
21-
>Type</label
22-
>
23-
<select
24-
id="type"
25-
v-model="type"
26-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
27-
required
28-
>
29-
<option value="" disabled selected>Select the Type</option>
30-
<option value="Hardware">Hardware</option>
31-
<option value="Mac">Mac</option>
32-
<option value="Livre">Livres</option>
33-
</select>
34-
<!-- Put the button in center -->
36+
<!-- Put the button in center -->
37+
<div class="row justify-center">
38+
<div class="form-group">
39+
<div class="flex justify-center">
40+
<img :src="picture" alt="Selected Image" class="mt-4 w-28 h-28" />
41+
</div>
42+
</div>
3543
<button
3644
type="button"
3745
@click="showImageModal = true"
38-
class="block w-full px-4 py-2 mt-2 text-white bg-blue-500 rounded-md hover:bg-blue-600 focus:outline-none focus:bg-blue-600"
46+
class="bg-blue-500 text-white py-2 px-4 rounded mt-2 mb-4 max-w-128 left-16"
3947
>
4048
Choisir une image
4149
</button>
@@ -44,88 +52,88 @@
4452
<ImagePicker @selectImage="onImageSelected" />
4553
</template>
4654
</Modal>
47-
<div class="form-group">
48-
<div class="flex justify-center">
49-
<img :src="picture" alt="Selected Image" class="mt-4 w-28 h-28" />
50-
</div>
51-
</div>
5255
</div>
5356

54-
<div class="form-group">
55-
<label for="price" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
56-
>Price</label
57-
>
58-
<input
59-
type="number"
60-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
61-
id="price"
62-
v-model="price"
63-
placeholder="Enter price"
64-
required
65-
/>
66-
</div>
57+
<div class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2">
58+
<div>
59+
<label for="price" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
60+
>Prix</label
61+
>
62+
<input
63+
type="number"
64+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
65+
id="price"
66+
v-model="price"
67+
placeholder="Entrez le prix du matériel"
68+
required
69+
/>
70+
</div>
6771

68-
<div class="form-group">
69-
<label for="state" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
70-
>State</label
71-
>
72-
<select
73-
v-model="state"
74-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
75-
required
76-
>
77-
<option value="" disabled selected>Select the State</option>
78-
<option value="Excellent">Etat Excellent</option>
79-
<option value="Bon">Bon Etat</option>
80-
<option value="Mauvais">Mauvais Etat</option>
81-
</select>
72+
<div class="form-group">
73+
<label for="state" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
74+
>État</label
75+
>
76+
<select
77+
v-model="state"
78+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
79+
required
80+
>
81+
<option value="" disabled selected>Sélectionnez l'état du matériel</option>
82+
<option value="Excellent">Excellent État</option>
83+
<option value="Bon">Bon État</option>
84+
<option value="Mauvais">Mauvais État</option>
85+
</select>
86+
</div>
8287
</div>
8388

84-
<div class="form-group">
85-
<label for="site" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
86-
>Site</label
87-
>
88-
<select
89-
v-model="siteLocation"
90-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
91-
required
92-
>
93-
<option value="" disabled selected>Select the Site</option>
94-
<option value="Cergy">Cergy</option>
95-
<option value="Paris">Paris</option>
96-
</select>
97-
</div>
89+
<div class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2">
90+
<div>
91+
<label for="site" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
92+
>Campus</label
93+
>
94+
<select
95+
v-model="siteLocation"
96+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
97+
required
98+
>
99+
<option value="" disabled selected>Sélectionnez le campus</option>
100+
<option value="Cergy">Cergy</option>
101+
<option value="Paris">Paris</option>
102+
</select>
103+
</div>
98104

99-
<div class="form-group">
100-
<label
101-
for="storageCupboard"
102-
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
103-
>Storage Cupboard</label
104-
>
105-
<select
106-
v-model="storageCupboard"
107-
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
108-
required
109-
>
110-
<option value="" disabled selected>Select the Storage</option>
111-
<option value="1">1</option>
112-
<option value="2">2</option>
113-
<option value="3">3</option>
114-
<option value="4">4</option>
115-
<option value="5">5</option>
116-
</select>
105+
<div class="form-group">
106+
<label
107+
for="storageCupboard"
108+
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
109+
>Étagère de stockage</label
110+
>
111+
<select
112+
v-model="storageCupboard"
113+
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
114+
required
115+
>
116+
<option value="" disabled selected>Sélectionnez l'étagère</option>
117+
<option value="1">1</option>
118+
<option value="2">2</option>
119+
<option value="3">3</option>
120+
<option value="4">4</option>
121+
<option value="5">5</option>
122+
</select>
123+
</div>
117124
</div>
118-
119125
<div class="form-group">
120-
<label for="description" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
126+
<label
127+
for="description"
128+
class="block mb-2 mt-4 text-sm font-medium text-gray-900 dark:text-white"
121129
>Description</label
122130
>
123131
<input
124132
type="text"
125133
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
126134
id="description"
127135
v-model="description"
128-
placeholder="Enter description"
136+
placeholder="Entrer la description du matériel"
129137
required
130138
/>
131139
</div>
@@ -134,7 +142,7 @@
134142
type="submit"
135143
class="text-white font-bold rounded-lg text-l px-4 py-2 focus:outline-none gap-2 gradiant"
136144
>
137-
Submit
145+
Ajouter
138146
</Button>
139147
</form>
140148
</template>
@@ -152,7 +160,7 @@ const showImageModal = ref(false);
152160
const name = ref('');
153161
const type = ref('');
154162
const price = ref(0);
155-
const picture = ref('');
163+
const picture = ref('/template-no-image.png');
156164
const state = ref('');
157165
const siteLocation = ref('');
158166
const storageCupboard = ref('');

front-end/src/views/MaterialDashboardView.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="py-8">
3-
<h1 class="text-dark-primary dark:text-light-primary text-center">Inventory Dashboard</h1>
4-
<div class="grid grid-cols-3 gap-6 py-10 px-20">
3+
<h1 class="text-dark-primary dark:text-light-primary text-center">Dashboard de l'inventaire</h1>
4+
<div class="sm:grid sm:grid-cols-3 grid-cols-1 px-3 py-5 sm:gap-6 lg:py-10 lg:px-20">
55
<DataOlderMaterials ref="bar" />
66
<DataNbMaterials ref="doughnut" />
77
<DataStatusMaterials ref="doughnut" />

0 commit comments

Comments
 (0)