Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Else, refer to the following sections.
| ------------------------------ | ------------------------------ |
| `dfx deploy frontend` | Deploy to a local DFX replica |
| `pnpm turbo start -F frontend` | Run a local development server |
| `pnpm turbo build -F frontend` | Create a prod build |
| `pnpm turbo test -F frontend` | Run unit tests |

### Docs
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/app/core/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './commit-review';
export * from './profile';
export * from './proposal';
export * from './review';
2 changes: 2 additions & 0 deletions src/frontend/src/app/core/api/profile/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './profile-api.model';
export * from './profile-api.service';
178 changes: 178 additions & 0 deletions src/frontend/src/app/core/api/profile/profile-api.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { Ok, toCandidOpt } from '../../utils';
import {
GetMyUserProfileResponse as GetMyUserProfileApiResponse,
UpdateMyUserProfileRequest as UpdateMyUserProfileApiRequest,
SocialLink as ApiSocialLink,
SocialLinkPlatform as ApiSocialLinkPlatform,
} from '@cg/backend';
import {
GetMyUserProfileResponse,
SocialMediaLink,
SocialMediaLinkType,
UpdateMyUserProfileRequest,
UserRole,
} from './profile-api.model';

export function mapGetMyUserProfileResponse(
res: Ok<GetMyUserProfileApiResponse>,
): GetMyUserProfileResponse {
if ('reviewer' in res.config) {
const config = res.config.reviewer;

return {
role: UserRole.Reviewer,
id: res.id,
username: res.username,
bio: config.bio,
neuronId: config.neuron_id,
walletAddress: config.wallet_address,
socialMedia: mapSocialLinksResponse(config.social_links),
};
} else if ('admin' in res.config) {
return {
role: UserRole.Admin,
id: res.id,
username: res.username,
bio: res.config.admin.bio,
};
} else {
return {
role: UserRole.Anonymous,
id: res.id,
username: res.username,
};
}
}

function mapSocialLinksResponse(
socialLinks: ApiSocialLink[],
): SocialMediaLink[] {
return socialLinks.map(link => ({
type: mapSocialLinkPlatformResponse(link.platform),
username: link.username,
}));
}

function mapSocialLinkPlatformResponse(
platform: ApiSocialLinkPlatform,
): SocialMediaLinkType {
if ('dscvr' in platform) {
return SocialMediaLinkType.DSCVR;
}

if ('openchat' in platform) {
return SocialMediaLinkType.OpenChat;
}

if ('taggr' in platform) {
return SocialMediaLinkType.Taggr;
}

if ('x' in platform) {
return SocialMediaLinkType.X;
}

if ('github' in platform) {
return SocialMediaLinkType.Github;
}

if ('dfinityforum' in platform) {
return SocialMediaLinkType.DfinityForum;
}

if ('discord' in platform) {
return SocialMediaLinkType.Discord;
}

if ('website' in platform) {
return SocialMediaLinkType.Website;
}

throw new Error(`Unknown social link platform: ${JSON.stringify(platform)}`);
}

export function mapUpdateMyUserProfileRequest(
req: UpdateMyUserProfileRequest,
): UpdateMyUserProfileApiRequest {
switch (req.role) {
case UserRole.Anonymous: {
return {
username: toCandidOpt(req.username),
config: toCandidOpt(),
};
}

case UserRole.Reviewer: {
return {
username: toCandidOpt(req.username),
config: toCandidOpt(
req.bio || req.socialMedia || req.walletAddress
? {
reviewer: {
bio: toCandidOpt(req.bio),
social_links: toCandidOpt(
mapSocialLinksRequest(req.socialMedia),
),
wallet_address: toCandidOpt(req.walletAddress),
},
}
: undefined,
),
};
}

case UserRole.Admin: {
return {
username: toCandidOpt(req.username),
config: toCandidOpt(
req.bio
? {
admin: {
bio: toCandidOpt(req.bio),
},
}
: undefined,
),
};
}
}
}

function mapSocialLinksRequest(
links?: SocialMediaLink[],
): ApiSocialLink[] | undefined {
return links?.map(link => ({
platform: mapSocialLinkPlatformRequest(link.type),
username: link.username,
}));
}

function mapSocialLinkPlatformRequest(
platform: SocialMediaLinkType,
): ApiSocialLinkPlatform {
switch (platform) {
case SocialMediaLinkType.DSCVR:
return { dscvr: null };

case SocialMediaLinkType.OpenChat:
return { openchat: null };

case SocialMediaLinkType.Taggr:
return { taggr: null };

case SocialMediaLinkType.X:
return { x: null };

case SocialMediaLinkType.Github:
return { github: null };

case SocialMediaLinkType.DfinityForum:
return { dfinityforum: null };

case SocialMediaLinkType.Discord:
return { discord: null };

case SocialMediaLinkType.Website:
return { website: null };
}
}
85 changes: 85 additions & 0 deletions src/frontend/src/app/core/api/profile/profile-api.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Generic types
*/

export enum UserRole {
Anonymous = 'Anonymous',
Reviewer = 'Reviewer',
Admin = 'Admin',
}

export enum SocialMediaLinkType {
DSCVR = 'DSCVR',
OpenChat = 'OpenChat',
Taggr = 'Taggr',
X = 'X',
Github = 'Github',
DfinityForum = 'DfinityForum',
Discord = 'Discord',
Website = 'Website',
}

export interface SocialMediaLink {
type: SocialMediaLinkType;
username: string;
}

/**
* GetMyUserProfile types
*/

export interface BaseGetMyUserProfileResponse<T extends UserRole> {
role: T;
id: string;
username: string;
}

export type AnonymousGetMyUserProfileResponse =
BaseGetMyUserProfileResponse<UserRole.Anonymous>;

export interface ReviewerGetMyUserProfileResponse
extends BaseGetMyUserProfileResponse<UserRole.Reviewer> {
neuronId: bigint;
walletAddress: string;
bio: string;
socialMedia: SocialMediaLink[];
}

export interface AdminGetMyUserProfileResponse
extends BaseGetMyUserProfileResponse<UserRole.Admin> {
bio: string;
}

export type GetMyUserProfileResponse =
| AnonymousGetMyUserProfileResponse
| ReviewerGetMyUserProfileResponse
| AdminGetMyUserProfileResponse;

/**
* UpdateMyUserProfile types
*/

export interface BaseUpdateMyUserProfileRequest<T extends UserRole> {
role: T;
username?: string;
}

export type AnonymousUpdateMyUserProfileRequest =
BaseUpdateMyUserProfileRequest<UserRole.Anonymous>;

export interface ReviewerUpdateMyUserProfileRequest
extends BaseUpdateMyUserProfileRequest<UserRole.Reviewer> {
bio?: string;
socialMedia?: SocialMediaLink[];
walletAddress?: string;
}

export interface AdminUpdateMyUserProfileRequest
extends BaseUpdateMyUserProfileRequest<UserRole.Admin> {
bio?: string;
}

export type UpdateMyUserProfileRequest =
| AnonymousUpdateMyUserProfileRequest
| ReviewerUpdateMyUserProfileRequest
| AdminUpdateMyUserProfileRequest;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ProfileApiService } from './profile-api.service';

export type ProfileApiServiceMock = jasmine.SpyObj<ProfileApiService>;

export function profileApiServiceMockFactory(): ProfileApiServiceMock {
return jasmine.createSpyObj<ProfileApiServiceMock>('ProfileApiService', [
'getMyUserProfile',
'updateMyUserProfile',
'createMyUserProfile',
]);
}
Loading
Loading