Compare commits

...

11 Commits

Author SHA1 Message Date
carteronm 5d26572073 Merge remote-tracking branch 'origin/develop' into develop 2026-06-11 01:51:04 +02:00
carteronm 0b69eee16b Rôles ajoutés 2026-06-11 01:50:58 +02:00
gokhoal d43b6b746d Merge remote-tracking branch 'origin/develop' into develop 2026-06-11 01:30:43 +02:00
gokhoal dccc2a5e4d LES MESSAGES MARCHENT 2026-06-11 01:30:33 +02:00
carteronm 673269e2b8 Création de groupe terminé + affichage des noms d'utilisateur dans la discussion 2026-06-11 01:15:04 +02:00
carteronm 6ffcece3fa création de groupe début 2026-06-11 00:26:25 +02:00
gokhoal 1c663913a7 LES DISCUSSIONS S'AFFICHENT 2026-06-10 23:39:42 +02:00
gokhoal e386897dc9 Merge remote-tracking branch 'origin/develop' into develop 2026-06-10 23:30:38 +02:00
gokhoal 79cb219a38 creation de discussions 2026-06-10 23:30:31 +02:00
carteronm aec268fbce openapi réalisé encore 2026-06-10 22:50:23 +02:00
gokhoal fd8d33642e logique de creation de discussions 2026-06-10 22:46:03 +02:00
23 changed files with 1209 additions and 100 deletions
+31 -26
View File
@@ -247,6 +247,7 @@
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.23.tgz",
"integrity": "sha512-RazHPQkUEsNU/OZ75w9UeHxGFMthRiuAW2B/uA7eXExBj/1meHrrBfoCA56ujW2GUxVjRtSrMjylKh4R4meiYA==",
"license": "MIT",
"peer": true,
"dependencies": {
"ajv": "8.18.0",
"ajv-formats": "3.0.1",
@@ -283,6 +284,7 @@
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.23.tgz",
"integrity": "sha512-Jzs7YM4X6azmHU7Mw5tQSPMuvaqYS8SLnZOJbtiXCy1JyuW9bm/WBBecNHMiuZ8LHXKhvQ6AVX1tKrzF6uiDmw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@angular-devkit/core": "19.2.23",
"jsonc-parser": "3.3.1",
@@ -430,6 +432,7 @@
"resolved": "https://registry.npmjs.org/@angular/common/-/common-19.2.20.tgz",
"integrity": "sha512-1M3W3FjUUbVKXDMs+yQpBhnkD/pCe0Jn79rPE5W+EGWWxFoLSyGX+fhnRO5m4c9k66p3nvYrikWQ0ZzMv3M5tw==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -446,6 +449,7 @@
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.20.tgz",
"integrity": "sha512-LvjE8W58EACgTFaAoqmNe7FRsbvoQ0GvCB/rmm6AEMWx/0W/JBvWkQTrOQlwpoeYOHcMZRGdmPcZoUDwU3JySQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -459,6 +463,7 @@
"integrity": "sha512-tYYQk8AUz2sEkVl0a3uebduDUXPuKiGEKl2Jryrbn0xh9i1EsxoCjt1VvHnGnksGp3mz4DQihFVEnte0KeVQ5g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/core": "7.26.9",
"@jridgewell/sourcemap-codec": "^1.4.14",
@@ -535,6 +540,7 @@
"resolved": "https://registry.npmjs.org/@angular/core/-/core-19.2.20.tgz",
"integrity": "sha512-pxzQh8ouqfE57lJlXjIzXFuRETwkfMVwS+NFCfv2yh01Qtx+vymO8ZClcJMgLPfBYinhBYX+hrRYVSa1nzlkRQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -551,6 +557,7 @@
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.2.20.tgz",
"integrity": "sha512-agi7InbMzop1jrud6L7SlNwnZk3iNolORcFIwBQMvKxLkcJ+ttbSYuM0KAw56IundWHf4dL9GP4cSygm4kUeFA==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -569,6 +576,7 @@
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.20.tgz",
"integrity": "sha512-O9ZoQKILPC1T2c64OASS75XlOLBxY81m5AAgsBKhwiFWq+V28RsO0cnwpi1YSh/z4ryH8Fe7IUFz8jGrsJi3hQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -609,6 +617,7 @@
"resolved": "https://registry.npmjs.org/@angular/router/-/router-19.2.20.tgz",
"integrity": "sha512-y0fyKycxJHr82kxXKE50Vac5hPn5Kx3gw9CfqyEuwJ9VQzEixDljU+chrQK4Wods14jJn9Tt2ncNPGH1rLya3Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.3.0"
},
@@ -653,6 +662,7 @@
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.2",
@@ -2509,6 +2519,7 @@
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.3.1.tgz",
"integrity": "sha512-UF8ItlHguU1Z6GXfPTeT2gakf+ctNI8pAS1kwSBQlsJMlfD4OPoto/SmKnOxKCQvnF4WRcdWeg6C0zREUNaAQg==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
@@ -3202,6 +3213,7 @@
"integrity": "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@inquirer/checkbox": "^4.1.2",
"@inquirer/confirm": "^5.1.6",
@@ -4953,6 +4965,7 @@
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.17.tgz",
"integrity": "sha512-hLODw5Abp8OQgA+mUO4tHou4krKgDtUcM9j5Ihxncst9XeyxYBTt2bwZm4e4EQr5E352S4Fyy6V3iFx9ggxKAg==",
"license": "MIT",
"peer": true,
"dependencies": {
"file-type": "21.3.2",
"iterare": "1.2.1",
@@ -7001,6 +7014,7 @@
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -7064,6 +7078,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -7294,6 +7309,7 @@
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
"integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
"license": "MIT",
"peer": true,
"dependencies": {
"follow-redirects": "^1.16.0",
"form-data": "^4.0.5",
@@ -7619,6 +7635,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
@@ -8802,29 +8819,6 @@
"node": ">= 0.8"
}
},
"node_modules/encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"license": "MIT",
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
"node_modules/encoding/node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/enhanced-resolve": {
"version": "5.20.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz",
@@ -10569,6 +10563,7 @@
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -10710,6 +10705,7 @@
"integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"copy-anything": "^2.0.1",
"parse-node-version": "^1.0.1",
@@ -12551,6 +12547,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.8",
"picocolors": "^1.1.1",
@@ -12958,7 +12955,8 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
"license": "Apache-2.0"
"license": "Apache-2.0",
"peer": true
},
"node_modules/regenerate": {
"version": "1.4.2",
@@ -13374,6 +13372,7 @@
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
@@ -14432,6 +14431,7 @@
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
"dev": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -14631,7 +14631,8 @@
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
"license": "0BSD",
"peer": true
},
"node_modules/tuf-js": {
"version": "3.1.0",
@@ -14687,6 +14688,7 @@
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -15092,6 +15094,7 @@
"integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -15171,6 +15174,7 @@
"integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/bonjour": "^3.5.13",
"@types/connect-history-api-fallback": "^1.5.4",
@@ -15766,7 +15770,8 @@
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz",
"integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==",
"license": "MIT"
"license": "MIT",
"peer": true
}
}
}
+14 -4
View File
@@ -1,14 +1,19 @@
import { Injectable } from '@angular/core';
import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr';
import {inject, Injectable} from '@angular/core';
import { HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr';
import * as signalR from '@microsoft/signalr';
import { AuthService } from "../auth/auth.service";
@Injectable({ providedIn: 'root' })
export class ChatService {
private hub: HubConnection;
private authService = inject(AuthService);
private hub: signalR.HubConnection;
constructor() {
this.hub = new HubConnectionBuilder()
.withUrl('https://localhost:5001/hubs/chat')
.withUrl('http://localhost:5250/hubs/chat', {
accessTokenFactory: () => this.authService.getToken() ?? ''
})
.withAutomaticReconnect()
.build();
}
@@ -27,4 +32,9 @@ export class ChatService {
onMessage(callback: (message: any) => void) {
this.hub.on('ReceiveMessage', callback);
}
async joinConversation(discussionId: string) {
await this.connect();
await this.hub.invoke('JoinConversation', discussionId);
}
}
+42 -4
View File
@@ -1,5 +1,4 @@
import { Observable } from "rxjs";
import { Discussion } from "../../pages/menu/menu-users/menu-users.component";
import { HttpClient } from "@angular/common/http";
import { inject, Injectable } from "@angular/core";
@@ -7,21 +6,60 @@ export interface Message {
id: number;
contenu: string;
date: string;
authorId: number;
userId: number;
authorName: string;
}
export interface MemberWithRole {
userId: number;
username: string;
roleId: number | null;
roleLibelle: string | null;
}
export interface Discussion {
id: number;
name: string;
isGroup: boolean;
membersCount?: number;
groupId?: number;
}
@Injectable({ providedIn: 'root' })
export class discussionsService {
private http = inject(HttpClient);
private apiUrl = 'https://localhost:5250/API';
private apiUrl = 'http://localhost:5250/API';
getDiscussions(): Observable<Discussion[]> {
return this.http.get<Discussion[]>(`${this.apiUrl}/discussions`);
return this.http.get<Discussion[]>(`${this.apiUrl}/discussions/my`);
}
getMessages(discussionId: string): Observable<Message[]> {
return this.http.get<Message[]>(`${this.apiUrl}/discussions/${discussionId}/messages`);
}
createPrivateDiscussion(username: string): Observable<Discussion> {
return this.http.post<Discussion>(`${this.apiUrl}/discussions/private`, { username });
}
createGroupDiscussion(groupName: string, usernames: string[]): Observable<Discussion> {
return this.http.post<Discussion>(`${this.apiUrl}/discussions/group`, { groupName, usernames });
}
getDiscussionMembers(discussionId: string): Observable<string[]> {
return this.http.get<string[]>(`${this.apiUrl}/discussions/${discussionId}/members`);
}
getMembersWithRoles(discussionId: string): Observable<MemberWithRole[]> {
return this.http.get<MemberWithRole[]>(`${this.apiUrl}/discussions/${discussionId}/members/roles`);
}
createRole(libelle: string): Observable<{ id: number, libelle: string }> {
return this.http.post<{ id: number, libelle: string }>(`${this.apiUrl}/roles`, { libelle });
}
assignRole(groupId: number, userId: number, roleId: number): Observable<void> {
return this.http.post<void>(`${this.apiUrl}/groups/${groupId}/members/${userId}/role`, { roleId });
}
}
@@ -108,3 +108,158 @@
box-shadow: 0 1px 5px rgba(180, 80, 80, 0.1);
}
}
.mode-switch {
margin-top: auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
background: rgba(255, 255, 255, 0.2);
border-radius: 16px;
backdrop-filter: blur(8px);
box-shadow: 0 2px 12px rgba(122, 46, 46, 0.08);
}
.switch-label {
color: #7a2e2e;
font-weight: 600;
font-size: 0.95rem;
}
/* SWITCH */
.switch {
position: relative;
width: 58px;
height: 32px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
inset: 0;
cursor: pointer;
background: rgba(255, 255, 255, 0.6);
border-radius: 999px;
transition: all 0.25s ease;
box-shadow:
inset 0 1px 3px rgba(0,0,0,0.08),
0 2px 8px rgba(0,0,0,0.05);
}
.slider::before {
content: "";
position: absolute;
top: 4px;
left: 4px;
width: 24px;
height: 24px;
border-radius: 50%;
background: white;
transition: all 0.25s ease;
box-shadow:
0 2px 8px rgba(0,0,0,0.15);
}
.switch input:checked + .slider {
background: #bd5a5a;
}
.switch input:checked + .slider::before {
transform: translateX(26px);
}
.mode-switch:hover .slider {
transform: scale(1.03);
}
.add-member-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 100%;
padding: 12px 16px;
border: 2px dashed rgba(189, 90, 90, 0.35);
border-radius: 14px;
background: rgba(255, 255, 255, 0.55);
color: #bd5a5a;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
ion-icon {
font-size: 1.2rem;
}
&:hover {
background: rgba(255, 255, 255, 0.8);
border-color: #bd5a5a;
transform: translateY(-1px);
}
&:active {
transform: scale(0.98);
}
}
.remove-btn {
width: 26px;
height: 26px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 50%;
background: white;
color: #bd5a5a;
cursor: pointer;
box-shadow: 0 2px 8px rgba(180, 80, 80, 0.12);
transition: all 0.2s ease;
ion-icon {
font-size: 1.1rem;
}
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(180, 80, 80, 0.18);
}
&:active {
transform: scale(0.92);
}
}
@@ -11,30 +11,91 @@
<div class="modal-layout">
<div class="modal-header">
<h2 class="modal-title">Nouvelle conversation</h2>
<h2 class="modal-title">{{ isGroup() ? 'Nouveau groupe' : 'Nouvelle conversation' }}</h2>
<div class="header-actions">
<button class="modal-close-btn" (click)="closeNav()">
<ion-icon name="close-outline" />
</button>
</div>
</div>
<div class="modal-body">
<!-- Mode privé -->
<ng-container *ngIf="!isGroup()">
<div class="input-wrapper">
<ion-item class="custom-item">
<ion-input
[formControl]="username"
label="Nom d'utilisateur"
labelPlacement="floating"
placeholder="ex: jean_dupont"
/>
</ion-item>
<!-- message d'erreur — affiché plus tard via logique -->
<!-- <p class="error-msg">Utilisateur introuvable.</p> -->
<p class="error-msg" *ngIf="errorMsg()">{{ errorMsg() }}</p>
</div>
<button class="submit-btn" (click)="startConversation()" [disabled]="isLoading()">
{{ isLoading() ? 'Création...' : 'Démarrer la conversation' }}
</button>
</ng-container>
<!-- Mode groupe -->
<ng-container *ngIf="isGroup()">
<div class="input-wrapper">
<ion-item class="custom-item">
<ion-input
[formControl]="groupName"
label="Nom du groupe"
labelPlacement="floating"
placeholder="ex: Les amis"
/>
</ion-item>
</div>
<button class="submit-btn">
Démarrer la conversation
<div class="members-list">
<div class="member-row" *ngFor="let ctrl of groupMembers; let i = index">
<ion-item class="custom-item member-item">
<ion-input
[formControl]="ctrl"
label="Membre {{ i + 1 }}"
labelPlacement="floating"
placeholder="ex: jean_dupont"
/>
</ion-item>
<button class="remove-btn" (click)="removeMember(i)" *ngIf="groupMembers.length > 1">
<ion-icon name="close-outline" />
</button>
</div>
</div>
<button class="add-member-btn" (click)="addMember()" *ngIf="groupMembers.length < 10">
<ion-icon name="add-outline" />
Ajouter un membre
</button>
<p class="error-msg" *ngIf="errorMsg()">{{ errorMsg() }}</p>
<button class="submit-btn" (click)="startGroupConversation()" [disabled]="isLoading()">
{{ isLoading() ? 'Création...' : 'Créer le groupe' }}
</button>
</ng-container>
<div class="mode-switch">
<span class="switch-label">
{{ isGroup() ? 'Mode groupe' : 'Conversation privée' }}
</span>
<label class="switch">
<input
type="checkbox"
[checked]="isGroup()"
(change)="toggleMode()"
>
<span class="slider"></span>
</label>
</div>
</div>
</div>
</ng-template>
</ion-modal>
@@ -1,31 +1,110 @@
import { Component, inject, signal } from '@angular/core';
import { Router } from "@angular/router";
import { ReactiveFormsModule, FormControl } from "@angular/forms";
import { addIcons } from "ionicons";
import {closeOutline} from "ionicons/icons";
import {
IonButton,
IonButtons,
IonContent,
IonHeader, IonIcon, IonInput,
IonItem,
IonModal,
IonTitle,
IonToolbar
} from "@ionic/angular/standalone";
import { IonIcon, IonInput, IonItem, IonModal } from "@ionic/angular/standalone";
import { closeOutline, addOutline } from "ionicons/icons";
import { discussionsService } from "../../../core/chat/discussion.service";
import {CommonModule} from "@angular/common";
@Component({
selector: 'app-menu-nav',
imports: [IonModal, IonItem, IonInput, IonIcon],
imports: [IonModal, IonItem, IonInput, IonIcon, ReactiveFormsModule, CommonModule],
templateUrl: './menu-nav.component.html',
styleUrl: './menu-nav.component.css'
})
export class MenuNav {
private router = inject(Router);
private discussionService = inject(discussionsService);
isModalOpen = signal(false);
isLoading = signal(false);
errorMsg = signal<string | null>(null);
isGroup = signal(false);
// Mode privé
username = new FormControl('');
// Mode groupe
groupName = new FormControl('');
groupMembers: FormControl[] = [new FormControl('')];
constructor() {
addIcons({ closeOutline });
addIcons({ closeOutline, addOutline });
}
openNav() { this.isModalOpen.set(true); }
closeNav() { this.isModalOpen.set(false); }
closeNav() {
this.isModalOpen.set(false);
this.username.reset();
this.groupName.reset();
this.groupMembers = [new FormControl('')];
this.errorMsg.set(null);
this.isGroup.set(false);
}
toggleMode() {
this.isGroup.update(v => !v);
this.errorMsg.set(null);
}
addMember() {
if (this.groupMembers.length < 10) {
this.groupMembers.push(new FormControl(''));
}
}
removeMember(index: number) {
this.groupMembers.splice(index, 1);
}
startConversation() {
const name = this.username.value?.trim();
if (!name || this.isLoading()) return;
this.isLoading.set(true);
this.errorMsg.set(null);
this.discussionService.createPrivateDiscussion(name).subscribe({
next: (discussion) => {
this.isLoading.set(false);
this.closeNav();
this.router.navigate(['/main/messages', discussion.id]);
},
error: (err) => {
this.isLoading.set(false);
this.errorMsg.set(
err.status === 404 ? 'Utilisateur introuvable.' : 'Une erreur est survenue.'
);
}
});
}
startGroupConversation() {
const name = this.groupName.value?.trim();
const usernames = this.groupMembers
.map(c => c.value?.trim())
.filter(v => !!v);
if (!name || usernames.length === 0 || this.isLoading()) return;
this.isLoading.set(true);
this.errorMsg.set(null);
this.discussionService.createGroupDiscussion(name, usernames).subscribe({
next: (discussion) => {
this.isLoading.set(false);
this.closeNav();
this.router.navigate(['/main/messages', discussion.id]);
},
error: (err) => {
this.isLoading.set(false);
this.errorMsg.set(
err.status === 404 ? 'Un ou plusieurs utilisateurs introuvables.' : 'Une erreur est survenue.'
);
}
});
}
}
@@ -41,3 +41,215 @@
font-weight: 500;
color: #c07070;
}
ion-modal {
--background: transparent;
}
/* MODALE */
.modal-layout {
display: flex;
flex-direction: column;
height: 100%;
background: radial-gradient(
ellipse at top,
#fff 0%,
#f9ece9 45%,
#f3d4cc 100%
);
border-radius: 22px 22px 0 0;
box-shadow: 0 -12px 45px rgba(200, 120, 100, 0.25);
overflow: hidden;
}
/* HEADER */
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px;
background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(192, 112, 112, 0.15);
}
.modal-title {
margin: 0;
font-size: 1.15rem;
font-weight: 700;
color: #c07070;
}
/* CLOSE */
.modal-close-btn {
width: 38px;
height: 38px;
border: none;
border-radius: 50%;
background: #fff;
color: #c07070;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 3px 12px rgba(200, 120, 100, 0.15);
cursor: pointer;
transition: all 0.2s ease;
ion-icon {
font-size: 1.2rem;
}
&:hover {
transform: translateY(-1px);
box-shadow: 0 6px 18px rgba(200, 120, 100, 0.22);
}
&:active {
transform: scale(0.92);
}
}
/* BODY */
.modal-body {
display: flex;
flex-direction: column;
gap: 12px;
padding: 18px;
overflow-y: auto;
}
/* MEMBER CARD */
.member-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px;
background: rgba(255, 255, 255, 0.75);
border-radius: 16px;
box-shadow: 0 2px 12px rgba(200, 120, 100, 0.12);
transition: all 0.2s ease;
&:hover {
transform: translateY(-2px);
background: rgba(255, 255, 255, 0.92);
}
}
/* MEMBER INFO */
.member-info {
display: flex;
align-items: center;
gap: 12px;
}
.member-info img {
width: 38px;
height: 38px;
border-radius: 50%;
}
.member-text {
display: flex;
flex-direction: column;
gap: 2px;
}
.member-name {
font-size: 0.95rem;
font-weight: 600;
color: #7a3a3a;
}
.member-role {
font-size: 0.75rem;
color: rgba(122, 58, 58, 0.6);
}
/* ROLE ASSIGN */
.role-assign {
display: flex;
align-items: center;
gap: 6px;
}
/* INPUT */
.role-input {
width: 120px;
padding: 8px 10px;
border: 1px solid rgba(192, 112, 112, 0.25);
border-radius: 10px;
background: rgba(255, 255, 255, 0.8);
font-size: 0.85rem;
color: #7a3a3a;
outline: none;
transition: all 0.2s ease;
&:focus {
border-color: #c07070;
box-shadow: 0 0 0 3px rgba(192, 112, 112, 0.15);
}
}
/* BUTTON + */
.role-btn {
width: 34px;
height: 34px;
border: none;
border-radius: 10px;
background: #c07070;
color: white;
font-size: 18px;
font-weight: 600;
cursor: pointer;
box-shadow: 0 2px 10px rgba(192, 112, 112, 0.25);
transition: all 0.2s ease;
&:hover {
transform: translateY(-1px);
box-shadow: 0 6px 16px rgba(192, 112, 112, 0.35);
}
&:active {
transform: scale(0.92);
}
}
@@ -1,6 +1,40 @@
<button class="profile-btn">
<button class="profile-btn" (click)="openModal()">
<div class="icon-wrapper">
<img width="50" height="50" src="https://img.icons8.com/ios/50/user-male-circle--v1.png" alt="user"/>
</div>
<span class="username">Nom User</span>
<span class="username">{{ name || 'Utilisateur' }}</span>
</button>
<ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
<ng-template>
<div class="modal-layout">
<div class="modal-header">
<h2 class="modal-title">Membres</h2>
<button class="modal-close-btn" (click)="closeModal()">
<ion-icon name="close-outline"/>
</button>
</div>
<div class="modal-body">
<div class="member-card" *ngFor="let member of members()">
<div class="member-info">
<img width="36" height="36" src="https://img.icons8.com/ios/50/user-male-circle--v1.png" alt="user"/>
<div class="member-text">
<span class="member-name">{{ member.username }}</span>
<span class="member-role" *ngIf="member.roleLibelle">{{ member.roleLibelle }}</span>
</div>
</div>
<div class="role-assign" *ngIf="groupId">
<input
class="role-input"
[(ngModel)]="newRoleInput[member.userId]"
placeholder="Nouveau rôle..."
/>
<button class="role-btn" (click)="assignRole(member.userId)">+</button>
</div>
</div>
</div>
</div>
</ng-template>
</ion-modal>
@@ -1,11 +1,63 @@
import { Component } from '@angular/core';
import { Component, Input, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonModal, IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { closeOutline } from 'ionicons/icons';
import { discussionsService, MemberWithRole } from '../../../core/chat/discussion.service';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-messages-infouser',
imports: [],
imports: [CommonModule, IonModal, IonIcon, FormsModule],
templateUrl: './messages-infouser.component.html',
styleUrl: './messages-infouser.component.css'
})
export class MessagesInfoUser {
@Input() name: string = '';
@Input() groupId: number | null = null;
private discussionService = inject(discussionsService);
private route = inject(ActivatedRoute);
isModalOpen = signal(false);
members = signal<MemberWithRole[]>([]);
newRoleInput: { [userId: number]: string } = {};
constructor() {
addIcons({ closeOutline });
}
openModal() {
const discussionId = this.route.snapshot.paramMap.get('discussionId')!;
this.discussionService.getMembersWithRoles(discussionId).subscribe({
next: (members) => {
this.members.set(members);
this.isModalOpen.set(true);
}
});
}
closeModal() { this.isModalOpen.set(false); }
assignRole(userId: number) {
const libelle = this.newRoleInput[userId]?.trim();
if (!libelle || !this.groupId) return;
this.discussionService.createRole(libelle).subscribe({
next: (role) => {
this.discussionService.assignRole(this.groupId!, userId, role.id).subscribe({
next: () => {
this.members.update(members =>
members.map(m => m.userId === userId
? { ...m, roleId: role.id, roleLibelle: libelle }
: m
)
);
this.newRoleInput[userId] = '';
}
});
}
});
}
}
@@ -2,7 +2,7 @@
<div class="header">
<app-messages-menu/>
<app-messages-infouser/>
<app-messages-infouser [name]="discussionName" [groupId]="groupId"/>
</div>
<div class="messages">
@@ -6,6 +6,7 @@ import { MessagesSend } from "../messages-send/messages-send.component";
import { ActivatedRoute } from '@angular/router';
import { discussionsService, Message } from "../../../core/chat/discussion.service";
import { AuthService } from "../../../core/auth/auth.service";
import {ChatService} from "../../../core/chat/chat.service";
@Component({
selector: 'app-messages-main',
@@ -18,22 +19,44 @@ export class MessagesMain implements OnInit {
private route = inject(ActivatedRoute);
private discussionService = inject(discussionsService);
private authService = inject(AuthService);
private chatService = inject(ChatService);
currentDiscussionId!: string;
currentUserId!: number;
messages: Message[] = [];
discussionName: string = '';
groupId: number | null = null;
ngOnInit() {
async ngOnInit() {
this.currentDiscussionId = this.route.snapshot.paramMap.get('discussionId')!;
this.currentUserId = this.authService.getCurrentUserId();
this.discussionService.getDiscussions().subscribe({
next: (discussions) => {
const discussion = discussions.find(d => d.id === +this.currentDiscussionId);
console.log('discussion:', discussion);
this.discussionName = discussion?.name ?? '';
this.groupId = discussion?.groupId ?? null;
console.log('groupId:', this.groupId);
}
});
this.discussionService.getMessages(this.currentDiscussionId).subscribe({
next: (messages) => this.messages = messages,
error: (err) => console.error('Impossible de charger les messages', err)
});
// réception temps réel
this.chatService.onMessage((message: Message) => {
this.messages = [...this.messages, message];
});
// rejoindre la room pour ne recevoir que cette conversation
await this.chatService.connect();
await this.chatService.joinConversation(this.currentDiscussionId);
}
isSent(message: Message): boolean {
return message.authorId === this.currentUserId;
return message.userId === this.currentUserId;
}
}
@@ -27,7 +27,6 @@ model/knots-dto-key-delete-key-dto.ts
model/knots-dto-message-create-message-dto.ts
model/knots-dto-message-delete-message-dto.ts
model/knots-dto-message-get-message-details-dto.ts
model/knots-dto-role-create-role-dto.ts
model/knots-dto-role-delete-role-dto.ts
model/knots-dto-user-create-user-dto.ts
model/knots-dto-user-delete-user-dto.ts
@@ -39,6 +38,12 @@ model/knots-dto-user-update-user-description-dto.ts
model/knots-dto-user-update-user-password-dto.ts
model/knots-dto-user-update-user-profile-picture-dto.ts
model/knots-dto-user-update-username-dto.ts
model/knots-endpoints-discussion-create-group-discussion-request.ts
model/knots-endpoints-discussion-create-private-discussion-request.ts
model/knots-endpoints-discussion-member-with-role-dto.ts
model/knots-endpoints-role-assign-role-request.ts
model/knots-endpoints-role-create-role-request.ts
model/knots-endpoints-role-role-dto.ts
model/models.ts
param.ts
provide-api.ts
+272 -4
View File
@@ -24,6 +24,12 @@ import { KnotsDTODiscussionCreateDiscussionDto } from '../model/knots-dto-discus
import { KnotsDTODiscussionDeleteDiscussionDto } from '../model/knots-dto-discussion-delete-discussion-dto';
// @ts-ignore
import { KnotsDTOMessageGetMessageDetailsDto } from '../model/knots-dto-message-get-message-details-dto';
// @ts-ignore
import { KnotsEndpointsDiscussionCreateGroupDiscussionRequest } from '../model/knots-endpoints-discussion-create-group-discussion-request';
// @ts-ignore
import { KnotsEndpointsDiscussionCreatePrivateDiscussionRequest } from '../model/knots-endpoints-discussion-create-private-discussion-request';
// @ts-ignore
import { KnotsEndpointsDiscussionMemberWithRoleDto } from '../model/knots-endpoints-discussion-member-with-role-dto';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
@@ -106,6 +112,142 @@ export class DiscussionsService extends BaseService {
);
}
/**
* @endpoint post /API/discussions/group
* @param knotsEndpointsDiscussionCreateGroupDiscussionRequest
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public createGroupDiscussionEndpoint(knotsEndpointsDiscussionCreateGroupDiscussionRequest: KnotsEndpointsDiscussionCreateGroupDiscussionRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<object>;
public createGroupDiscussionEndpoint(knotsEndpointsDiscussionCreateGroupDiscussionRequest: KnotsEndpointsDiscussionCreateGroupDiscussionRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<object>>;
public createGroupDiscussionEndpoint(knotsEndpointsDiscussionCreateGroupDiscussionRequest: KnotsEndpointsDiscussionCreateGroupDiscussionRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<object>>;
public createGroupDiscussionEndpoint(knotsEndpointsDiscussionCreateGroupDiscussionRequest: KnotsEndpointsDiscussionCreateGroupDiscussionRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (knotsEndpointsDiscussionCreateGroupDiscussionRequest === null || knotsEndpointsDiscussionCreateGroupDiscussionRequest === undefined) {
throw new Error('Required parameter knotsEndpointsDiscussionCreateGroupDiscussionRequest was null or undefined when calling createGroupDiscussionEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
'application/json'
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}
const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
const localVarTransferCache: boolean = options?.transferCache ?? true;
// to determine the Content-Type header
const consumes: string[] = [
'application/json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
}
let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}
let localVarPath = `/API/discussions/group`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<object>('post', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: knotsEndpointsDiscussionCreateGroupDiscussionRequest,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
observe: observe,
...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
reportProgress: reportProgress
}
);
}
/**
* @endpoint post /API/discussions/private
* @param knotsEndpointsDiscussionCreatePrivateDiscussionRequest
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public createPrivateDiscussionEndpoint(knotsEndpointsDiscussionCreatePrivateDiscussionRequest: KnotsEndpointsDiscussionCreatePrivateDiscussionRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<object>;
public createPrivateDiscussionEndpoint(knotsEndpointsDiscussionCreatePrivateDiscussionRequest: KnotsEndpointsDiscussionCreatePrivateDiscussionRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<object>>;
public createPrivateDiscussionEndpoint(knotsEndpointsDiscussionCreatePrivateDiscussionRequest: KnotsEndpointsDiscussionCreatePrivateDiscussionRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<object>>;
public createPrivateDiscussionEndpoint(knotsEndpointsDiscussionCreatePrivateDiscussionRequest: KnotsEndpointsDiscussionCreatePrivateDiscussionRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (knotsEndpointsDiscussionCreatePrivateDiscussionRequest === null || knotsEndpointsDiscussionCreatePrivateDiscussionRequest === undefined) {
throw new Error('Required parameter knotsEndpointsDiscussionCreatePrivateDiscussionRequest was null or undefined when calling createPrivateDiscussionEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
'application/json'
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}
const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
const localVarTransferCache: boolean = options?.transferCache ?? true;
// to determine the Content-Type header
const consumes: string[] = [
'application/json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
}
let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}
let localVarPath = `/API/discussions/private`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<object>('post', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: knotsEndpointsDiscussionCreatePrivateDiscussionRequest,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
observe: observe,
...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
reportProgress: reportProgress
}
);
}
/**
* @endpoint delete /API/discussions
* @param knotsDTODiscussionDeleteDiscussionDto
@@ -177,14 +319,15 @@ export class DiscussionsService extends BaseService {
* @param name
* @param isGroup
* @param membersCount
* @param groupId
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<any>>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<any>>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any> {
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, groupId?: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, groupId?: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<any>>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, groupId?: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<any>>;
public getDiscussionEndpoint(id: number, name: string, isGroup: boolean, membersCount?: number, groupId?: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (id === null || id === undefined) {
throw new Error('Required parameter id was null or undefined when calling getDiscussionEndpoint.');
}
@@ -233,6 +376,15 @@ export class DiscussionsService extends BaseService {
);
localVarQueryParameters = this.addToHttpParams(
localVarQueryParameters,
'groupId',
<any>groupId,
QueryParamStyle.Form,
true,
);
let localVarHeaders = this.defaultHeaders;
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
@@ -273,6 +425,122 @@ export class DiscussionsService extends BaseService {
);
}
/**
* @endpoint get /API/discussions/{discussionId}/members
* @param discussionId
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public getDiscussionMembersEndpoint(discussionId: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Array<string>>;
public getDiscussionMembersEndpoint(discussionId: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Array<string>>>;
public getDiscussionMembersEndpoint(discussionId: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Array<string>>>;
public getDiscussionMembersEndpoint(discussionId: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (discussionId === null || discussionId === undefined) {
throw new Error('Required parameter discussionId was null or undefined when calling getDiscussionMembersEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
'application/json'
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}
const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
const localVarTransferCache: boolean = options?.transferCache ?? true;
let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}
let localVarPath = `/API/discussions/${this.configuration.encodeParam({name: "discussionId", value: discussionId, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}/members`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<Array<string>>('get', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
observe: observe,
...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
reportProgress: reportProgress
}
);
}
/**
* @endpoint get /API/discussions/{discussionId}/members/roles
* @param discussionId
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public getDiscussionMembersWithRolesEndpoint(discussionId: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Array<KnotsEndpointsDiscussionMemberWithRoleDto>>;
public getDiscussionMembersWithRolesEndpoint(discussionId: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Array<KnotsEndpointsDiscussionMemberWithRoleDto>>>;
public getDiscussionMembersWithRolesEndpoint(discussionId: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Array<KnotsEndpointsDiscussionMemberWithRoleDto>>>;
public getDiscussionMembersWithRolesEndpoint(discussionId: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (discussionId === null || discussionId === undefined) {
throw new Error('Required parameter discussionId was null or undefined when calling getDiscussionMembersWithRolesEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
'application/json'
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}
const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
const localVarTransferCache: boolean = options?.transferCache ?? true;
let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}
let localVarPath = `/API/discussions/${this.configuration.encodeParam({name: "discussionId", value: discussionId, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}/members/roles`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<Array<KnotsEndpointsDiscussionMemberWithRoleDto>>('get', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
observe: observe,
...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
reportProgress: reportProgress
}
);
}
/**
* @endpoint get /API/discussions/{discussionId}/messages
* @param discussionId
@@ -28,6 +28,8 @@ import { KnotsDTOGroupUpdateGroupMembersAmountDto } from '../model/knots-dto-gro
import { KnotsDTOGroupUpdateGroupNameDto } from '../model/knots-dto-group-update-group-name-dto';
// @ts-ignore
import { KnotsDTOGroupUpdateGroupProfilePictureDto } from '../model/knots-dto-group-update-group-profile-picture-dto';
// @ts-ignore
import { KnotsEndpointsRoleAssignRoleRequest } from '../model/knots-endpoints-role-assign-role-request';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
@@ -45,6 +47,81 @@ export class GroupsService extends BaseService {
super(basePath, configuration);
}
/**
* @endpoint post /API/groups/{groupId}/members/{userId}/role
* @param groupId
* @param userId
* @param knotsEndpointsRoleAssignRoleRequest
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public assignRoleEndpoint(groupId: string, userId: string, knotsEndpointsRoleAssignRoleRequest: KnotsEndpointsRoleAssignRoleRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any>;
public assignRoleEndpoint(groupId: string, userId: string, knotsEndpointsRoleAssignRoleRequest: KnotsEndpointsRoleAssignRoleRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<any>>;
public assignRoleEndpoint(groupId: string, userId: string, knotsEndpointsRoleAssignRoleRequest: KnotsEndpointsRoleAssignRoleRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<any>>;
public assignRoleEndpoint(groupId: string, userId: string, knotsEndpointsRoleAssignRoleRequest: KnotsEndpointsRoleAssignRoleRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: undefined, context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (groupId === null || groupId === undefined) {
throw new Error('Required parameter groupId was null or undefined when calling assignRoleEndpoint.');
}
if (userId === null || userId === undefined) {
throw new Error('Required parameter userId was null or undefined when calling assignRoleEndpoint.');
}
if (knotsEndpointsRoleAssignRoleRequest === null || knotsEndpointsRoleAssignRoleRequest === undefined) {
throw new Error('Required parameter knotsEndpointsRoleAssignRoleRequest was null or undefined when calling assignRoleEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}
const localVarHttpContext: HttpContext = options?.context ?? new HttpContext();
const localVarTransferCache: boolean = options?.transferCache ?? true;
// to determine the Content-Type header
const consumes: string[] = [
'application/json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
}
let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}
let localVarPath = `/API/groups/${this.configuration.encodeParam({name: "groupId", value: groupId, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}/members/${this.configuration.encodeParam({name: "userId", value: userId, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}/role`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<any>('post', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: knotsEndpointsRoleAssignRoleRequest,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
observe: observe,
...(localVarTransferCache !== undefined ? { transferCache: localVarTransferCache } : {}),
reportProgress: reportProgress
}
);
}
/**
* @endpoint post /API/groups
* @param knotsDTOGroupCreateGroupDto
+17 -12
View File
@@ -19,9 +19,11 @@ import { OpenApiHttpParams, QueryParamStyle } from '../query.params';
// @ts-ignore
import { FastEndpointsErrorResponse } from '../model/fast-endpoints-error-response';
// @ts-ignore
import { KnotsDTORoleCreateRoleDto } from '../model/knots-dto-role-create-role-dto';
// @ts-ignore
import { KnotsDTORoleDeleteRoleDto } from '../model/knots-dto-role-delete-role-dto';
// @ts-ignore
import { KnotsEndpointsRoleCreateRoleRequest } from '../model/knots-endpoints-role-create-role-request';
// @ts-ignore
import { KnotsEndpointsRoleRoleDto } from '../model/knots-endpoints-role-role-dto';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
@@ -41,23 +43,26 @@ export class RolesService extends BaseService {
/**
* @endpoint post /API/roles
* @param knotsDTORoleCreateRoleDto
* @param knotsEndpointsRoleCreateRoleRequest
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
* @param options additional options
*/
public createRoleEndpoint(knotsDTORoleCreateRoleDto: KnotsDTORoleCreateRoleDto, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/problem+json', context?: HttpContext, transferCache?: boolean}): Observable<any>;
public createRoleEndpoint(knotsDTORoleCreateRoleDto: KnotsDTORoleCreateRoleDto, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/problem+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<any>>;
public createRoleEndpoint(knotsDTORoleCreateRoleDto: KnotsDTORoleCreateRoleDto, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/problem+json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<any>>;
public createRoleEndpoint(knotsDTORoleCreateRoleDto: KnotsDTORoleCreateRoleDto, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/problem+json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (knotsDTORoleCreateRoleDto === null || knotsDTORoleCreateRoleDto === undefined) {
throw new Error('Required parameter knotsDTORoleCreateRoleDto was null or undefined when calling createRoleEndpoint.');
public createRoleEndpoint(knotsEndpointsRoleCreateRoleRequest: KnotsEndpointsRoleCreateRoleRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<KnotsEndpointsRoleRoleDto>;
public createRoleEndpoint(knotsEndpointsRoleCreateRoleRequest: KnotsEndpointsRoleCreateRoleRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<KnotsEndpointsRoleRoleDto>>;
public createRoleEndpoint(knotsEndpointsRoleCreateRoleRequest: KnotsEndpointsRoleCreateRoleRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<KnotsEndpointsRoleRoleDto>>;
public createRoleEndpoint(knotsEndpointsRoleCreateRoleRequest: KnotsEndpointsRoleCreateRoleRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
if (knotsEndpointsRoleCreateRoleRequest === null || knotsEndpointsRoleCreateRoleRequest === undefined) {
throw new Error('Required parameter knotsEndpointsRoleCreateRoleRequest was null or undefined when calling createRoleEndpoint.');
}
let localVarHeaders = this.defaultHeaders;
// authentication (JWTBearerAuth) required
localVarHeaders = this.configuration.addCredentialToHeaders('JWTBearerAuth', 'Authorization', localVarHeaders, 'Bearer ');
const localVarHttpHeaderAcceptSelected: string | undefined = options?.httpHeaderAccept ?? this.configuration.selectHeaderAccept([
'application/problem+json'
'application/json'
]);
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
@@ -90,10 +95,10 @@ export class RolesService extends BaseService {
let localVarPath = `/API/roles`;
const { basePath, withCredentials } = this.configuration;
return this.httpClient.request<any>('post', `${basePath}${localVarPath}`,
return this.httpClient.request<KnotsEndpointsRoleRoleDto>('post', `${basePath}${localVarPath}`,
{
context: localVarHttpContext,
body: knotsDTORoleCreateRoleDto,
body: knotsEndpointsRoleCreateRoleRequest,
responseType: <any>responseType_,
...(withCredentials ? { withCredentials } : {}),
headers: localVarHeaders,
@@ -14,7 +14,7 @@ export interface KnotsDTOMessageGetMessageDetailsDto {
contenu?: string | null;
date?: string;
type?: boolean;
authorId?: number;
userId?: number;
authorName?: string;
}
@@ -0,0 +1,16 @@
/**
* Knots
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface KnotsEndpointsDiscussionCreateGroupDiscussionRequest {
groupName?: string;
usernames?: Array<string>;
}
@@ -0,0 +1,15 @@
/**
* Knots
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface KnotsEndpointsDiscussionCreatePrivateDiscussionRequest {
username?: string;
}
@@ -0,0 +1,18 @@
/**
* Knots
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface KnotsEndpointsDiscussionMemberWithRoleDto {
userId?: number;
username?: string;
roleId?: number | null;
roleLibelle?: string | null;
}
@@ -9,7 +9,7 @@
*/
export interface KnotsDTORoleCreateRoleDto {
libelle: string;
export interface KnotsEndpointsRoleAssignRoleRequest {
roleId?: number;
}
@@ -0,0 +1,15 @@
/**
* Knots
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface KnotsEndpointsRoleCreateRoleRequest {
libelle?: string;
}
@@ -0,0 +1,16 @@
/**
* Knots
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface KnotsEndpointsRoleRoleDto {
id?: number;
libelle?: string;
}
+6 -1
View File
@@ -11,7 +11,6 @@ export * from './knots-dto-key-delete-key-dto';
export * from './knots-dto-message-create-message-dto';
export * from './knots-dto-message-delete-message-dto';
export * from './knots-dto-message-get-message-details-dto';
export * from './knots-dto-role-create-role-dto';
export * from './knots-dto-role-delete-role-dto';
export * from './knots-dto-user-create-user-dto';
export * from './knots-dto-user-delete-user-dto';
@@ -23,3 +22,9 @@ export * from './knots-dto-user-update-user-description-dto';
export * from './knots-dto-user-update-user-password-dto';
export * from './knots-dto-user-update-user-profile-picture-dto';
export * from './knots-dto-user-update-username-dto';
export * from './knots-endpoints-discussion-create-group-discussion-request';
export * from './knots-endpoints-discussion-create-private-discussion-request';
export * from './knots-endpoints-discussion-member-with-role-dto';
export * from './knots-endpoints-role-assign-role-request';
export * from './knots-endpoints-role-create-role-request';
export * from './knots-endpoints-role-role-dto';