aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.html21
-rw-r--r--src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.ts125
-rw-r--r--src/DevHive.Angular/src/app/components/profile/profile.component.ts42
-rw-r--r--src/DevHive.Angular/src/app/services/language.service.ts40
-rw-r--r--src/DevHive.Angular/src/app/services/technology.service.ts41
-rw-r--r--src/DevHive.Angular/src/app/services/user.service.ts5
6 files changed, 238 insertions, 36 deletions
diff --git a/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.html b/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.html
index 8da7f86..16b537c 100644
--- a/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.html
+++ b/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.html
@@ -58,6 +58,27 @@
<label *ngIf="updateUserFormGroup.get('password')?.errors?.pattern" class="error">*At least 1 number</label>
</div>
</div>
+ <button type="button" (click)="toggleLanguages()">Edit Languages</button>
+ <div *ngIf="showLanguages">
+ Type in your desired languages, separated by a space.
+ <input type="text" class="input-field" formControlName="languageInput" required>
+ Available languages:
+ <div *ngFor="let lang of availableLanguages">
+ {{ lang.name }}
+ </div>
+ </div>
+
+ <button type="button" (click)="toggleTechnologies()">Edit Technologies</button>
+ <div *ngIf="showTechnologies">
+ Type in your desired technologies, separated by a space.
+ <input type="text" class="input-field" formControlName="technologyInput" required>
+ Available technologies:
+ <div *ngFor="let tech of availableTechnologies">
+ {{ tech.name }}
+ </div>
+ </div>
+
+
<button class="submit-btn" type="submit">Update profile</button>
<app-success-bar></app-success-bar>
<app-error-bar></app-error-bar>
diff --git a/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.ts b/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.ts
index 0ea5ea2..5be160e 100644
--- a/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.ts
+++ b/src/DevHive.Angular/src/app/components/profile-settings/profile-settings.component.ts
@@ -4,8 +4,10 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router';
import {AppConstants} from 'src/app/app-constants.module';
+import {LanguageService} from 'src/app/services/language.service';
import {UserService} from 'src/app/services/user.service';
-import {User} from 'src/models/identity/user';
+import {TechnologyService} from 'src/app/services/technology.service';
+import {Language, Technology, User} from 'src/models/identity/user';
import {ErrorBarComponent} from '../error-bar/error-bar.component';
import {SuccessBarComponent} from '../success-bar/success-bar.component';
@@ -22,12 +24,16 @@ export class ProfileSettingsComponent implements OnInit {
public dataArrived = false;
public user: User;
public deleteAccountConfirm = false;
+ public showLanguages = false;
+ public availableLanguages: Language[] = [];
+ public showTechnologies = false;
+ public availableTechnologies: Technology[] = [];
- constructor(private _router: Router, private _userService: UserService, private _fb: FormBuilder, private _location: Location)
+ constructor(private _router: Router, private _userService: UserService, private _languageService: LanguageService, private _technologyService: TechnologyService, private _fb: FormBuilder, private _location: Location)
{ }
ngOnInit(): void {
- this._urlUsername = this._router.url.substring(9)
+ this._urlUsername = this._router.url.substring(9);
this._urlUsername = this._urlUsername.substring(0, this._urlUsername.length - 9);
this.user = this._userService.getDefaultUser();
@@ -35,6 +41,17 @@ export class ProfileSettingsComponent implements OnInit {
(res: object) => this.finishUserLoading(res),
(err: HttpErrorResponse) => { this._router.navigate(['/not-found']); }
);
+
+ this._languageService.getAllLanguagesWithSessionStorageRequest().subscribe(
+ (result: object) => {
+ this.availableLanguages = result as Language[];
+ }
+ );
+ this._technologyService.getAllTechnologiesWithSessionStorageRequest().subscribe(
+ (result: object) => {
+ this.availableTechnologies = result as Technology[];
+ }
+ );
}
private finishUserLoading(res: object): void {
@@ -89,14 +106,51 @@ export class ProfileSettingsComponent implements OnInit {
Validators.minLength(3),
Validators.pattern('.*[0-9].*') // Check if password contains atleast one number
]),
+
+ // For language we have two different controls,
+ // the first one is used for input, the other one for sending data
+ // because if we edit the control for input,
+ // we're also gonna change the input field in the HTML
+ languageInput: new FormControl(''), // The one for input
+ languages: new FormControl(''), // The one that is sent
+
+ // For technologies it's the same as it is with languages
+ technologyInput: new FormControl(''),
+ technologies: new FormControl('')
});
+ this.getLanguagesForShowing()
+ .then(value => this.updateUserFormGroup.patchValue({ languageInput : value }));
+
+ this.getTechnologiesForShowing()
+ .then(value => this.updateUserFormGroup.patchValue({ technologyInput : value }));
+
this.updateUserFormGroup.valueChanges.subscribe(() => {
this._successBar.hideMsg();
this._errorBar.hideError();
});
}
+ private getLanguagesForShowing(): Promise<string> {
+ return new Promise(resolve =>
+ this._languageService.getFullLanguagesFromIncomplete(this.user.languages)
+ .then(value => {
+ this.user.languages = value;
+ resolve(value.map(x => x.name).join(' '));
+ })
+ );
+ }
+
+ private getTechnologiesForShowing(): Promise<string> {
+ return new Promise(resolve =>
+ this._technologyService.getFullTechnologiesFromIncomplete(this.user.technologies)
+ .then(value => {
+ this.user.technologies = value;
+ resolve(value.map(x => x.name).join(' '));
+ })
+ );
+ }
+
private bailOnBadToken(): void {
this._userService.logoutUserFromSessionStorage();
this._router.navigate(['/login']);
@@ -105,12 +159,69 @@ export class ProfileSettingsComponent implements OnInit {
onSubmit(): void {
this._successBar.hideMsg();
this._errorBar.hideError();
+
+ this.patchLanguagesControl();
+ this.patchTechnologiesControl();
+
this._userService.putUserFromSessionStorageRequest(this.updateUserFormGroup).subscribe(
res => this._successBar.showMsg('Profile updated successfully!'),
(err: HttpErrorResponse) => this._errorBar.showError(err)
);
}
+ private patchLanguagesControl(): void {
+ // Get user input
+ const langControl = this.updateUserFormGroup.get('languageInput')?.value as string ?? '';
+
+ if (langControl === '') {
+ // Add the data to the form (to the value that is going to be sent)
+ this.updateUserFormGroup.patchValue({
+ languages : []
+ });
+ }
+ else {
+ const names = langControl.split(' ');
+
+ // Transfer user input to objects of type { "name": "value" }
+ const actualLanguages = [];
+ for (const lName of names) {
+ actualLanguages.push({ name : lName });
+ }
+
+ // Add the data to the form (to the value that is going to be sent)
+ this.updateUserFormGroup.patchValue({
+ languages : actualLanguages
+ });
+ }
+ }
+
+ private patchTechnologiesControl(): void {
+ // Get user input
+ const techControl = this.updateUserFormGroup.get('technologyInput')?.value as string ?? '';
+
+ if (techControl === '') {
+ // Add the data to the form (to the value that is going to be sent)
+ this.updateUserFormGroup.patchValue({
+ technologies : []
+ });
+ }
+ else {
+ const names = techControl.split(' ');
+
+ // Transfer user input to objects of type { "name": "value" }
+ const actualTechnologies = [];
+ for (const tName of names) {
+ actualTechnologies.push({ name : tName });
+ }
+
+ // Add the data to the form (to the value that is going to be sent)
+ this.updateUserFormGroup.patchValue({
+ technologies : actualTechnologies
+ });
+ }
+ }
+
+
goToProfile(): void {
this._router.navigate([this._router.url.substring(0, this._router.url.length - 9)]);
}
@@ -128,6 +239,14 @@ export class ProfileSettingsComponent implements OnInit {
this.goToProfile();
}
+ toggleLanguages(): void {
+ this.showLanguages = !this.showLanguages;
+ }
+
+ toggleTechnologies(): void {
+ this.showTechnologies = !this.showTechnologies;
+ }
+
deleteAccount(): void {
if (this.deleteAccountConfirm) {
this._userService.deleteUserFromSessionStorageRequest().subscribe(
diff --git a/src/DevHive.Angular/src/app/components/profile/profile.component.ts b/src/DevHive.Angular/src/app/components/profile/profile.component.ts
index 5bc1976..69d7e72 100644
--- a/src/DevHive.Angular/src/app/components/profile/profile.component.ts
+++ b/src/DevHive.Angular/src/app/components/profile/profile.component.ts
@@ -42,21 +42,12 @@ export class ProfileComponent implements OnInit {
Object.assign(this.user, res);
if (this.user.languages.length > 0) {
- // For each language in the user, request it's name and assign it,
- // when you finally finish with them, start loading technologies
- const lastGuid = this.user.languages[this.user.languages.length - 1].id;
- for (const lang of this.user.languages) {
- this._languageService.getLanguageRequest(lang.id).subscribe(
- (result: object) => {
- // this only assigns the response "name" property to language
- Object.assign(lang, result);
-
- if (lastGuid === lang.id) {
- this.loadTechnologies();
- }
- }
- );
- }
+ // When user has languages, get their names and load technologies
+ this._languageService.getFullLanguagesFromIncomplete(this.user.languages)
+ .then(value => {
+ this.user.languages = value;
+ this.loadTechnologies();
+ });
}
else {
this.showNoLangMsg = true;
@@ -66,21 +57,12 @@ export class ProfileComponent implements OnInit {
private loadTechnologies(): void {
if (this.user.technologies.length > 0) {
- // For each language in the user, request it's name and assign it,
- // when you finish with them, finally finish user loading
- const lastGuid = this.user.technologies[this.user.technologies.length - 1].id;
- for (const tech of this.user.technologies) {
- this._technologyService.getTechnologyRequest(tech.id).subscribe(
- (result: object) => {
- // this only assigns the response "name" property to technology
- Object.assign(tech, result);
-
- if (lastGuid === tech.id) {
- this.finishUserLoading();
- }
- }
- );
- }
+ // When user has technologies, get their names and finally finish loading
+ this._technologyService.getFullTechnologiesFromIncomplete(this.user.technologies)
+ .then(value => {
+ this.user.technologies = value;
+ this.finishUserLoading();
+ });
}
else {
this.showNoTechMsg = true;
diff --git a/src/DevHive.Angular/src/app/services/language.service.ts b/src/DevHive.Angular/src/app/services/language.service.ts
index 8613a65..d85f178 100644
--- a/src/DevHive.Angular/src/app/services/language.service.ts
+++ b/src/DevHive.Angular/src/app/services/language.service.ts
@@ -2,6 +2,7 @@ import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Guid} from 'guid-typescript';
import {Observable} from 'rxjs';
+import {Language} from 'src/models/identity/user';
import {AppConstants} from '../app-constants.module';
@Injectable({
@@ -16,4 +17,43 @@ export class LanguageService {
};
return this.http.get(AppConstants.API_LANGUAGE_URL, options);
}
+
+ getAllLanguagesWithSessionStorageRequest(): Observable<object> {
+ const token = sessionStorage.getItem('UserCred') ?? '';
+ return this.getAllLanguagesRequest(token);
+ }
+
+ getAllLanguagesRequest(authToken: string): Observable<object> {
+ const options = {
+ headers: new HttpHeaders().set('Authorization', 'Bearer ' + authToken)
+ };
+ return this.http.get(AppConstants.API_LANGUAGE_URL + '/GetLanguages', options);
+ }
+
+ getFullLanguagesFromIncomplete(givenLanguages: Language[]): Promise<Language[]> {
+ if (givenLanguages.length === 0) {
+ return new Promise(resolve => resolve(givenLanguages));
+ }
+
+ // This accepts language array with incomplete languages, meaning
+ // languages that only have an id, but no name
+ return new Promise(resolve => {
+ const lastGuid = givenLanguages[givenLanguages.length - 1].id;
+
+ // For each language, request his name and assign it
+ for (const lang of givenLanguages) {
+ this.getLanguageRequest(lang.id).subscribe(
+ (result: object) => {
+ // this only assigns the "name" property to the language,
+ // because only the name is returned from the request
+ Object.assign(lang, result);
+
+ if (lastGuid === lang.id) {
+ resolve(givenLanguages);
+ }
+ }
+ );
+ }
+ });
+ }
}
diff --git a/src/DevHive.Angular/src/app/services/technology.service.ts b/src/DevHive.Angular/src/app/services/technology.service.ts
index 4df0412..207303f 100644
--- a/src/DevHive.Angular/src/app/services/technology.service.ts
+++ b/src/DevHive.Angular/src/app/services/technology.service.ts
@@ -2,6 +2,7 @@ import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Guid} from 'guid-typescript';
import {Observable} from 'rxjs';
+import {Technology} from 'src/models/identity/user';
import {AppConstants} from '../app-constants.module';
@Injectable({
@@ -16,4 +17,44 @@ export class TechnologyService {
};
return this.http.get(AppConstants.API_TECHNOLOGY_URL, options);
}
+
+ getAllTechnologiesWithSessionStorageRequest(): Observable<object> {
+ const token = sessionStorage.getItem('UserCred') ?? '';
+ return this.getAllTechnologiesRequest(token);
+ }
+
+ getAllTechnologiesRequest(authToken: string): Observable<object> {
+ const options = {
+ headers: new HttpHeaders().set('Authorization', 'Bearer ' + authToken)
+ };
+ return this.http.get(AppConstants.API_TECHNOLOGY_URL + '/GetTechnologies', options);
+ }
+
+ getFullTechnologiesFromIncomplete(givenTechnologies: Technology[]): Promise<Technology[]> {
+ if (givenTechnologies.length === 0) {
+ return new Promise(resolve => resolve(givenTechnologies));
+ }
+
+ // This accepts language array with incomplete languages, meaning
+ // languages that only have an id, but no name
+ return new Promise(resolve => {
+ const lastGuid = givenTechnologies[givenTechnologies.length - 1].id;
+
+ // For each language, request his name and assign it
+ for (const tech of givenTechnologies) {
+ this.getTechnologyRequest(tech.id).subscribe(
+ (result: object) => {
+ // this only assigns the "name" property to the language,
+ // because only the name is returned from the request
+ Object.assign(tech, result);
+
+ if (lastGuid === tech.id) {
+ resolve(givenTechnologies);
+ }
+ }
+ );
+ }
+ });
+ }
+
}
diff --git a/src/DevHive.Angular/src/app/services/user.service.ts b/src/DevHive.Angular/src/app/services/user.service.ts
index 5b4b63c..6badf94 100644
--- a/src/DevHive.Angular/src/app/services/user.service.ts
+++ b/src/DevHive.Angular/src/app/services/user.service.ts
@@ -94,7 +94,6 @@ export class UserService {
}
putUserRequest(userId: Guid, authToken: string, updateUserFormGroup: FormGroup): Observable<object> {
- // TODO?: add a check for form data validity
const body = {
UserName: updateUserFormGroup.get('username')?.value,
Email: updateUserFormGroup.get('email')?.value,
@@ -104,8 +103,8 @@ export class UserService {
// TODO: make the following fields dynamically selectable
Roles: [ { Name: 'User' } ],
Friends: [],
- Languages: [],
- Technologies: []
+ Languages: updateUserFormGroup.get('languages')?.value,
+ Technologies: updateUserFormGroup.get('technologies')?.value
};
const options = {
params: new HttpParams().set('Id', userId.toString()),