Skip to content

Commit c35d955

Browse files
committed
feat(profile): Implemented my-profile and user/:id pages
1 parent 4d52403 commit c35d955

16 files changed

Lines changed: 97 additions & 76 deletions

File tree

src/app/core/guards/is-project.guard.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { map, switchMap } from 'rxjs/operators';
55
import { inject } from '@angular/core';
66
import { CanMatchFn, Route, Router, UrlSegment } from '@angular/router';
77

8-
import { CurrentResourceType } from '../../shared/enums';
9-
import { CurrentResourceSelectors, GetResource } from '../../shared/stores';
8+
import { UserSelectors } from '@core/store/user';
9+
import { CurrentResourceType } from '@shared/enums';
10+
import { CurrentResourceSelectors, GetResource } from '@shared/stores';
1011

1112
export const isProjectGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => {
1213
const store = inject(Store);
@@ -19,8 +20,9 @@ export const isProjectGuard: CanMatchFn = (route: Route, segments: UrlSegment[])
1920
}
2021

2122
const currentResource = store.selectSnapshot(CurrentResourceSelectors.getCurrentResource);
23+
const currentUser = store.selectSnapshot(UserSelectors.getCurrentUser);
2224

23-
if (currentResource && currentResource.id === id) {
25+
if (currentResource && !id.startsWith(currentResource.id)) {
2426
if (currentResource.type === CurrentResourceType.Projects && currentResource.parentId) {
2527
router.navigate(['/', currentResource.parentId, 'files', id]);
2628
return true;
@@ -32,7 +34,11 @@ export const isProjectGuard: CanMatchFn = (route: Route, segments: UrlSegment[])
3234
}
3335

3436
if (currentResource.type === CurrentResourceType.Users) {
35-
router.navigate(['/profile', id]);
37+
if (currentUser && currentUser.id === currentResource.id) {
38+
router.navigate(['/profile']);
39+
} else {
40+
router.navigate(['/user', id]);
41+
}
3642
return false;
3743
}
3844

@@ -42,7 +48,7 @@ export const isProjectGuard: CanMatchFn = (route: Route, segments: UrlSegment[])
4248
return store.dispatch(new GetResource(id)).pipe(
4349
switchMap(() => store.select(CurrentResourceSelectors.getCurrentResource)),
4450
map((resource) => {
45-
if (!resource || resource.id !== id) {
51+
if (!resource || !id.startsWith(resource.id)) {
4652
return false;
4753
}
4854

@@ -57,7 +63,11 @@ export const isProjectGuard: CanMatchFn = (route: Route, segments: UrlSegment[])
5763
}
5864

5965
if (resource.type === CurrentResourceType.Users) {
60-
router.navigate(['/user', id]);
66+
if (currentUser && currentUser.id === resource.id) {
67+
router.navigate(['/profile']);
68+
} else {
69+
router.navigate(['/user', id]);
70+
}
6171
return false;
6272
}
6373

src/app/core/guards/is-registry.guard.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { map, switchMap } from 'rxjs/operators';
55
import { inject } from '@angular/core';
66
import { CanMatchFn, Route, Router, UrlSegment } from '@angular/router';
77

8-
import { CurrentResourceType } from '../../shared/enums';
9-
import { CurrentResourceSelectors, GetResource } from '../../shared/stores';
8+
import { UserSelectors } from '@core/store/user';
9+
import { CurrentResourceType } from '@shared/enums';
10+
import { CurrentResourceSelectors, GetResource } from '@shared/stores';
1011

1112
export const isRegistryGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => {
1213
const store = inject(Store);
@@ -19,8 +20,9 @@ export const isRegistryGuard: CanMatchFn = (route: Route, segments: UrlSegment[]
1920
}
2021

2122
const currentResource = store.selectSnapshot(CurrentResourceSelectors.getCurrentResource);
23+
const currentUser = store.selectSnapshot(UserSelectors.getCurrentUser);
2224

23-
if (currentResource && currentResource.id === id) {
25+
if (currentResource && !id.startsWith(currentResource.id)) {
2426
if (currentResource.type === CurrentResourceType.Registrations && currentResource.parentId) {
2527
router.navigate(['/', currentResource.parentId, 'files', id]);
2628
return true;
@@ -32,7 +34,11 @@ export const isRegistryGuard: CanMatchFn = (route: Route, segments: UrlSegment[]
3234
}
3335

3436
if (currentResource.type === CurrentResourceType.Users) {
35-
router.navigate(['/user', id]);
37+
if (currentUser && currentUser.id === currentResource.id) {
38+
router.navigate(['/profile']);
39+
} else {
40+
router.navigate(['/user', id]);
41+
}
3642
return false;
3743
}
3844

@@ -42,7 +48,7 @@ export const isRegistryGuard: CanMatchFn = (route: Route, segments: UrlSegment[]
4248
return store.dispatch(new GetResource(id)).pipe(
4349
switchMap(() => store.select(CurrentResourceSelectors.getCurrentResource)),
4450
map((resource) => {
45-
if (!resource || resource.id !== id) {
51+
if (!resource || !id.startsWith(resource.id)) {
4652
return false;
4753
}
4854

@@ -57,7 +63,11 @@ export const isRegistryGuard: CanMatchFn = (route: Route, segments: UrlSegment[]
5763
}
5864

5965
if (resource.type === CurrentResourceType.Users) {
60-
router.navigate(['/profile', id]);
66+
if (currentUser && currentUser.id === resource.id) {
67+
router.navigate(['/profile']);
68+
} else {
69+
router.navigate(['/user', id]);
70+
}
6171
return false;
6272
}
6373

src/app/core/services/user.service.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import {
99
ProfileSettingsUpdate,
1010
User,
1111
UserData,
12+
UserDataJsonApi,
1213
UserDataResponseJsonApi,
13-
UserGetResponse,
14+
UserResponseJsonApi,
1415
UserSettings,
1516
UserSettingsGetResponse,
1617
} from '@osf/shared/models';
17-
18-
import { JsonApiService } from '../../shared/services/json-api.service';
18+
import { JsonApiService } from '@shared/services';
1919

2020
import { environment } from 'src/environments/environment';
2121

@@ -25,6 +25,12 @@ import { environment } from 'src/environments/environment';
2525
export class UserService {
2626
jsonApiService = inject(JsonApiService);
2727

28+
getUserById(userId: string): Observable<User> {
29+
return this.jsonApiService
30+
.get<UserResponseJsonApi>(`${environment.apiUrl}/users/${userId}/`)
31+
.pipe(map((response) => UserMapper.fromUserGetResponse(response.data)));
32+
}
33+
2834
getCurrentUser(): Observable<UserData> {
2935
return this.jsonApiService
3036
.get<UserDataResponseJsonApi>(`${environment.apiUrl}/`)
@@ -49,7 +55,7 @@ export class UserService {
4955
const patchedData = key === ProfileSettingsKey.User ? data : { [key]: data };
5056

5157
return this.jsonApiService
52-
.patch<UserGetResponse>(`${environment.apiUrl}/users/${userId}/`, {
58+
.patch<UserDataJsonApi>(`${environment.apiUrl}/users/${userId}/`, {
5359
data: { type: 'users', id: userId, attributes: patchedData },
5460
})
5561
.pipe(map((response) => UserMapper.fromUserGetResponse(response)));

src/app/features/moderation/mappers/moderation.mapper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PaginatedData, ResponseJsonApi, UserGetResponse } from '@osf/shared/models';
1+
import { PaginatedData, ResponseJsonApi, UserDataJsonApi } from '@osf/shared/models';
22

33
import { AddModeratorType, ModeratorPermission } from '../enums';
44
import { ModeratorAddModel, ModeratorAddRequestModel, ModeratorDataJsonApi, ModeratorModel } from '../models';
@@ -16,7 +16,7 @@ export class ModerationMapper {
1616
}
1717

1818
static fromUsersWithPaginationGetResponse(
19-
response: ResponseJsonApi<UserGetResponse[]>
19+
response: ResponseJsonApi<UserDataJsonApi[]>
2020
): PaginatedData<ModeratorAddModel[]> {
2121
return {
2222
data: response.data.map(

src/app/features/moderation/models/moderator-json-api.model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ApiData, MetaJsonApi, PaginationLinksJsonApi, UserGetResponse } from '@osf/shared/models';
1+
import { ApiData, MetaJsonApi, PaginationLinksJsonApi, UserDataJsonApi } from '@osf/shared/models';
22

33
export interface ModeratorResponseJsonApi {
44
data: ModeratorDataJsonApi[];
@@ -15,7 +15,7 @@ interface ModeratorAttributesJsonApi {
1515

1616
interface ModeratorEmbedsJsonApi {
1717
user: {
18-
data: UserGetResponse;
18+
data: UserDataJsonApi;
1919
};
2020
}
2121

src/app/features/moderation/services/moderators.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { map, Observable } from 'rxjs';
33
import { inject, Injectable } from '@angular/core';
44

55
import { ResourceType } from '@osf/shared/enums';
6-
import { JsonApiResponse, PaginatedData, ResponseJsonApi, UserGetResponse } from '@osf/shared/models';
6+
import { JsonApiResponse, PaginatedData, ResponseJsonApi, UserDataJsonApi } from '@osf/shared/models';
77
import { JsonApiService } from '@osf/shared/services';
88

99
import { AddModeratorType } from '../enums';
@@ -62,7 +62,7 @@ export class ModeratorsService {
6262
const baseUrl = `${environment.apiUrl}/users/?filter[full_name]=${value}&page=${page}`;
6363

6464
return this.jsonApiService
65-
.get<ResponseJsonApi<UserGetResponse[]>>(baseUrl)
65+
.get<ResponseJsonApi<UserDataJsonApi[]>>(baseUrl)
6666
.pipe(map((response) => ModerationMapper.fromUsersWithPaginationGetResponse(response)));
6767
}
6868
}
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
<osf-profile-information
2-
[currentUser]="currentUser()"
3-
[showEdit]="true"
4-
(editProfile)="toProfileSettings()"
5-
></osf-profile-information>
1+
<osf-profile-information [currentUser]="currentUser()" [showEdit]="true" (editProfile)="toProfileSettings()" />
62

7-
<osf-profile-search [currentUser]="currentUser()"></osf-profile-search>
3+
@if (currentUser()) {
4+
<osf-profile-search />
5+
}
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { createDispatchMap, select } from '@ngxs/store';
22

3-
import { ChangeDetectionStrategy, Component, inject, OnDestroy } from '@angular/core';
3+
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
44
import { Router } from '@angular/router';
55

66
import { UserSelectors } from '@osf/core/store/user';
7-
8-
import { ProfileSearchComponent } from '../../components';
9-
import { ProfileInformationComponent } from '../../components/profile-information/profile-information.component';
10-
import { SetIsMyProfile } from '../../store';
7+
import { ProfileInformationComponent, ProfileSearchComponent } from '@osf/features/profile/components';
8+
import { SetUserProfile } from '@osf/features/profile/store';
119

1210
@Component({
1311
selector: 'osf-my-profile',
@@ -16,20 +14,22 @@ import { SetIsMyProfile } from '../../store';
1614
styleUrl: './my-profile.component.scss',
1715
changeDetection: ChangeDetectionStrategy.OnPush,
1816
})
19-
export class MyProfileComponent implements OnDestroy {
20-
private readonly router = inject(Router);
17+
export class MyProfileComponent implements OnInit {
18+
private router = inject(Router);
19+
private actions = createDispatchMap({
20+
setUserProfile: SetUserProfile,
21+
});
2122

2223
currentUser = select(UserSelectors.getCurrentUser);
2324

24-
readonly actions = createDispatchMap({
25-
setIsMyProfile: SetIsMyProfile,
26-
});
25+
ngOnInit(): void {
26+
const user = this.currentUser();
27+
if (user) {
28+
this.actions.setUserProfile(user);
29+
}
30+
}
2731

2832
toProfileSettings() {
2933
this.router.navigate(['settings/profile-settings']);
3034
}
31-
32-
ngOnDestroy(): void {
33-
this.actions.setIsMyProfile(false);
34-
}
3535
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
@if (isLoading()) {
1+
@if (isUserLoading()) {
22
} @else {
3-
<osf-profile-information [currentUser]="currentUser()"></osf-profile-information>
3+
<osf-profile-information [currentUser]="currentUser()" />
44

5-
<osf-profile-search [currentUser]="currentUser()"></osf-profile-search>
5+
@if (currentUser()) {
6+
<osf-profile-search />
7+
}
68
}
Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { createDispatchMap, select } from '@ngxs/store';
22

3-
import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit } from '@angular/core';
3+
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
44
import { ActivatedRoute } from '@angular/router';
55

6-
import { ProfileSearchComponent } from '../../components';
7-
import { ProfileInformationComponent } from '../../components/profile-information/profile-information.component';
8-
import { GetUserProfile, ProfileSelectors, SetIsMyProfile } from '../../store';
6+
import { ProfileInformationComponent, ProfileSearchComponent } from '@osf/features/profile/components';
7+
import { FetchUserProfile, ProfileSelectors } from '@osf/features/profile/store';
98

109
@Component({
1110
selector: 'osf-user-profile',
@@ -14,26 +13,20 @@ import { GetUserProfile, ProfileSelectors, SetIsMyProfile } from '../../store';
1413
styleUrl: './user-profile.component.scss',
1514
changeDetection: ChangeDetectionStrategy.OnPush,
1615
})
17-
export class UserProfileComponent implements OnInit, OnDestroy {
18-
private readonly route = inject(ActivatedRoute);
16+
export class UserProfileComponent implements OnInit {
17+
private route = inject(ActivatedRoute);
18+
private actions = createDispatchMap({
19+
fetchUserProfile: FetchUserProfile,
20+
});
1921

2022
currentUser = select(ProfileSelectors.getUserProfile);
21-
isLoading = select(ProfileSelectors.getIsUserProfile);
22-
23-
readonly actions = createDispatchMap({
24-
setIsMyProfile: SetIsMyProfile,
25-
getUserProfile: GetUserProfile,
26-
});
23+
isUserLoading = select(ProfileSelectors.isUserProfileLoading);
2724

2825
ngOnInit(): void {
2926
const userId = this.route.snapshot.params['id'];
3027

3128
if (userId) {
32-
this.actions.getUserProfile(userId);
29+
this.actions.fetchUserProfile(userId);
3330
}
3431
}
35-
36-
ngOnDestroy(): void {
37-
this.actions.setIsMyProfile(false);
38-
}
3932
}

0 commit comments

Comments
 (0)