Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
11d225c
feat(user-settings): refactored user management, implemented fetching…
rrromchIk May 8, 2025
ba0796d
Merge branch 'refs/heads/main' into feat/114-notifications-api-integr…
rrromchIk May 9, 2025
b510044
Merge branch 'refs/heads/main' into feat/114-notifications-api-integr…
rrromchIk May 9, 2025
4b48001
feat(notifications): updating email preferences
rrromchIk May 9, 2025
8a27f05
Merge branch 'main' into feat/114-notifications-api-integration
rrromchIk May 16, 2025
1d00fa9
fix(app-component): removed unused field
rrromchIk May 16, 2025
d2aec97
feat(settings/notifications): added models, enums, service
rrromchIk May 16, 2025
ea3dd31
feat(notifications): added store
rrromchIk May 19, 2025
dae7b0a
refactor(notifications): update exports and splitted subscription enums
rrromchIk May 20, 2025
bd1aea1
feat(notifications): Implemented update notification subscription fun…
rrromchIk May 20, 2025
913a81d
Merge branch 'main' into feat/114-notifications-api-integration
rrromchIk May 20, 2025
b0ba4a8
Merge branch 'main' into feat/114-notifications-api-integration
rrromchIk May 20, 2025
54b1402
fix(notifications): Changed media query max width value
rrromchIk May 20, 2025
44b5b58
fix(notifications.spec): Fixed test to run
rrromchIk May 20, 2025
9eff271
feat(notifications): Refactored state models and selectors to use Asy…
rrromchIk May 20, 2025
df5af71
Merge branch 'main' into feat/114-notifications-api-integration
rrromchIk May 20, 2025
ead0893
refactor(user): consolidate user imports and restructure user service…
rrromchIk May 20, 2025
56ddc11
Merge branch 'main' into feat/114-notifications-api-integration
rrromchIk May 21, 2025
8951a72
fix(merge): Fixed merge issues
rrromchIk May 21, 2025
8ad71c7
refactor(notifications): replace dropdown with select component
rrromchIk May 21, 2025
30ba06a
refactor(styles): reformating
rrromchIk May 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/core/constants/ngxs-states.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AnalyticsState } from '@osf/features/project/analytics/store';
import { AccountSettingsState } from '@osf/features/settings/account-settings/store/account-settings.state';
import { AddonsState } from '@osf/features/settings/addons/store';
import { DeveloperAppsState } from '@osf/features/settings/developer-apps/store';
import { NotificationSubscriptionState } from '@osf/features/settings/notifications/store';
import { ProfileSettingsState } from '@osf/features/settings/profile-settings/profile-settings.state';
import { TokensState } from '@osf/features/settings/tokens/store';

Expand All @@ -20,4 +21,5 @@ export const STATES = [
DeveloperAppsState,
AccountSettingsState,
AnalyticsState,
NotificationSubscriptionState,
];

This file was deleted.

22 changes: 0 additions & 22 deletions src/app/core/services/mappers/users/users.mapper.ts

This file was deleted.

3 changes: 3 additions & 0 deletions src/app/core/services/user/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './user.mapper';
export * from './user.models';
export * from './user.service';
21 changes: 0 additions & 21 deletions src/app/core/services/user/user.entity.ts

This file was deleted.

49 changes: 49 additions & 0 deletions src/app/core/services/user/user.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
User,
UserGetResponse,
UserSettings,
UserSettingsGetResponse,
UserSettingsUpdateRequest,
} from '@core/services/user/user.models';

export class UserMapper {
static fromUserGetResponse(user: UserGetResponse): User {
return {
id: user.id,
fullName: user.attributes.full_name,
givenName: user.attributes.given_name,
middleNames: user.attributes.middle_names,
suffix: user.attributes.suffix,
familyName: user.attributes.family_name,
email: user.attributes.email,
dateRegistered: new Date(user.attributes.date_registered),
link: user.links.html,
education: user.attributes.education,
employment: user.attributes.employment,
iri: user.links.iri,
social: user.attributes.social,
defaultRegionId: user.relationships?.default_region?.data?.id,
allowIndexing: user.attributes?.allow_indexing,
};
}

static fromUserSettingsGetResponse(userSettingsResponse: UserSettingsGetResponse): UserSettings {
return {
subscribeOsfGeneralEmail: userSettingsResponse.attributes.subscribe_osf_general_email,
subscribeOsfHelpEmail: userSettingsResponse.attributes.subscribe_osf_help_email,
};
}

static toUpdateUserSettingsRequest(userId: string, userSettings: UserSettings): UserSettingsUpdateRequest {
return {
data: {
id: userId,
type: 'user_settings',
attributes: {
subscribe_osf_general_email: userSettings.subscribeOsfGeneralEmail,
subscribe_osf_help_email: userSettings.subscribeOsfHelpEmail,
},
},
};
}
}
78 changes: 78 additions & 0 deletions src/app/core/services/user/user.models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Education } from '@osf/features/settings/profile-settings/education/educations.entities';
import { Employment } from '@osf/features/settings/profile-settings/employment/employment.entities';
import { Social } from '@osf/features/settings/profile-settings/social/social.entities';

//Domain models
export interface User {
id: string;
fullName: string;
givenName: string;
familyName: string;
email?: string;
middleNames?: string;
suffix?: string;
education: Education[];
employment: Employment[];
social: Social;
dateRegistered: Date;
link?: string;
iri?: string;
defaultRegionId: string;
allowIndexing: boolean | undefined;
}

export interface UserSettings {
subscribeOsfGeneralEmail: boolean;
subscribeOsfHelpEmail: boolean;
}

// API Request/Response Models
export interface UserGetResponse {
id: string;
type: string;
attributes: {
full_name: string;
given_name: string;
family_name: string;
email?: string;
employment: Employment[];
education: Education[];
middle_names?: string;
suffix?: string;
social: Social;
date_registered: string;
allow_indexing?: boolean;
};
relationships: {
default_region: {
data: {
id: string;
};
};
};
links: {
html: string;
profile_image: string;
iri: string;
};
}

export interface UserSettingsGetResponse {
id: string;
type: 'user_settings';
attributes: {
subscribe_osf_general_email: boolean;
subscribe_osf_help_email: boolean;
};
}

export interface UserSettingsUpdateRequest {
data: {
id: string;
type: 'user_settings';
attributes: {
subscribe_osf_general_email: boolean;
subscribe_osf_help_email: boolean;
};
};
}
23 changes: 18 additions & 5 deletions src/app/core/services/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { inject, Injectable } from '@angular/core';

import { JsonApiResponse } from '@core/services/json-api/json-api.entity';
import { JsonApiService } from '@core/services/json-api/json-api.service';
import { UserUS } from '@core/services/json-api/underscore-entites/user/user-us.entity';
import { mapUserUStoUser } from '@core/services/mappers/users/users.mapper';
import { User } from '@core/services/user/user.entity';
import { UserMapper } from '@core/services/user/user.mapper';
import { User, UserGetResponse, UserSettings, UserSettingsGetResponse } from '@core/services/user/user.models';

@Injectable({
providedIn: 'root',
Expand All @@ -17,7 +16,21 @@ export class UserService {

getCurrentUser(): Observable<User> {
return this.jsonApiService
.get<JsonApiResponse<UserUS, null>>(this.baseUrl + 'users/me')
.pipe(map((user) => mapUserUStoUser(user.data)));
.get<JsonApiResponse<UserGetResponse, null>>(this.baseUrl + 'users/me/')
.pipe(map((user) => UserMapper.fromUserGetResponse(user.data)));
}

getCurrentUserSettings(): Observable<UserSettings> {
return this.jsonApiService
.get<JsonApiResponse<UserSettingsGetResponse, null>>(this.baseUrl + 'users/me/settings/')
.pipe(map((response) => UserMapper.fromUserSettingsGetResponse(response.data)));
}

updateUserSettings(userId: string, userSettings: UserSettings): Observable<UserSettings> {
const request = UserMapper.toUpdateUserSettingsRequest(userId, userSettings);

return this.jsonApiService
.patch<UserSettingsGetResponse>(this.baseUrl + `users/${userId}/settings/`, request)
.pipe(map((response) => UserMapper.fromUserSettingsGetResponse(response)));
}
}
3 changes: 2 additions & 1 deletion src/app/core/store/user/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './user.actions';
export * from './user.models';
export * from './user.model';
export * from './user.selectors';
export * from './user.state';
15 changes: 14 additions & 1 deletion src/app/core/store/user/user.actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { User } from '@core/services/user/user.entity';
import { User, UserSettings } from '@core/services/user';

export class GetCurrentUser {
static readonly type = '[User] Get Current User';
Expand All @@ -9,3 +9,16 @@ export class SetCurrentUser {

constructor(public user: User) {}
}

export class GetCurrentUserSettings {
static readonly type = '[User] Get Current User Settings';
}

export class UpdateUserSettings {
static readonly type = '[User] Update User Settings';

constructor(
public userId: string,
public updatedUserSettings: UserSettings
) {}
}
7 changes: 7 additions & 0 deletions src/app/core/store/user/user.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { User, UserSettings } from '@core/services/user';
import { AsyncStateModel } from '@shared/models/store';

export interface UserStateModel {
currentUser: User | null;
currentUserSettings: AsyncStateModel<UserSettings | null>;
}
5 changes: 0 additions & 5 deletions src/app/core/store/user/user.models.ts

This file was deleted.

20 changes: 17 additions & 3 deletions src/app/core/store/user/user.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Selector } from '@ngxs/store';

import { User } from '@core/services/user/user.entity';
import { UserStateModel } from '@core/store/user/user.models';
import { UserState } from '@core/store/user/user.state';
import { User, UserSettings } from '@core/services/user';
import { UserState, UserStateModel } from '@core/store/user';
import { ProfileSettingsStateModel } from '@osf/features/settings/profile-settings/profile-settings.entities';
import { Social } from '@osf/features/settings/profile-settings/social/social.entities';

Expand All @@ -29,4 +28,19 @@ export class UserSelectors {
},
} satisfies ProfileSettingsStateModel;
}

@Selector([UserState])
static getCurrentUserSettings(state: UserStateModel): UserSettings | null {
return state.currentUserSettings.data;
}

@Selector([UserState])
static isUserSettingsLoading(state: UserStateModel): boolean {
return state.currentUserSettings.isLoading;
}

@Selector([UserState])
static isUserSettingsSubmitting(state: UserStateModel): boolean {
return state.currentUserSettings.isSubmitting!;
}
}
Loading