From be1000ad205473b7a789aa730167d00e4d5f223e Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Fri, 18 Aug 2023 15:05:26 +1000 Subject: [PATCH 01/32] HOTFIX - Force RESTRICT_TALENT_SEARCH to false because it somehow got reset in prod --- src/config/environments/default.env.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config/environments/default.env.ts b/src/config/environments/default.env.ts index 078849971..362fc9c83 100644 --- a/src/config/environments/default.env.ts +++ b/src/config/environments/default.env.ts @@ -70,5 +70,7 @@ export const DICE_VERIFY_URL = get({ qa: 'https://accounts-auth0.topcoder-qa.com', }, ENV, 'https://accounts-auth0.topcoder.com') -export const RESTRICT_TALENT_SEARCH = getReactEnv('RESTRICT_TALENT_SEARCH', false) +// TODO: Revert this. This was done because prod was restricting this and no one was available to fix the config +// export const RESTRICT_TALENT_SEARCH = getReactEnv('RESTRICT_TALENT_SEARCH', false) +export const RESTRICT_TALENT_SEARCH = false export const SEGMENT_ANALYTICS_KEY = getReactEnv('SEGMENT_ANALYTICS_KEY', undefined) From 5439ea70f1d58e5af0b77843ddad738bd7dd82e9 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Thu, 5 Oct 2023 16:51:57 +0300 Subject: [PATCH 02/32] Revert "Revert "Merge pull request #916 from topcoder-platform/TAL-84_emsi-skill-update"" This reverts commit f9f6f14ae593df9446da46e9b71336250b3aa8e4. --- .../lib/components/skill-tags/SkillTags.tsx | 8 +-- .../src/lib/components/skill/SkillLabel.tsx | 4 +- .../courses-provider/learn-course.model.ts | 4 +- .../tca-certifications-provider/index.ts | 2 +- .../tca-certification.model.ts | 4 +- ...a-emsi-skill-type.ts => tca-skill-type.ts} | 2 +- .../cert-card/TCCertCard.tsx | 4 +- src/apps/onboarding/src/models/MemberInfo.ts | 5 +- .../onboarding/src/pages/skills/index.tsx | 6 +- .../member-profile/MemberProfile.context.tsx | 4 +- .../skills/MemberSkillsInfo.tsx | 24 ++++---- .../ModifySkillsModal/ModifySkillsModal.tsx | 6 +- .../popular-skills/PopularSkills.tsx | 38 ++++++------- .../ProfileSkillsMatch.tsx | 17 +++--- .../components/search-input/SearchInput.tsx | 18 +++--- .../src/components/talent-card/TalentCard.tsx | 2 +- .../talent-search/src/lib/models/Member.ts | 5 +- .../src/lib/models/MemberEmsiSkill.ts | 9 --- .../talent-search/src/lib/models/index.ts | 1 - .../lib/services/use-fetch-talent-matches.ts | 2 +- .../src/lib/utils/search-query.tsx | 6 +- .../src/lib/utils/skills.utils.tsx | 8 +-- .../src/routes/talent-page/TalentPage.tsx | 4 +- .../core/lib/profile/data-providers/index.ts | 1 - .../profile/data-providers/useMemberSkills.ts | 18 ------ .../profile-functions/rating.functions.ts | 6 -- .../core/lib/profile/user-profile.model.ts | 4 +- src/libs/core/lib/profile/user-skill.model.ts | 24 +++----- .../InputSkillSelector.tsx | 12 ++-- .../use-member-skill-editor.tsx | 56 +++++++++---------- .../lib/services/emsi-skills/skill.model.ts | 16 ------ .../lib/services/emsi-skills/skills.utils.ts | 5 -- src/libs/shared/lib/services/index.ts | 2 +- .../{emsi-skills => standard-skills}/index.ts | 2 +- .../services/standard-skills/skill.model.ts | 2 + .../services/standard-skills/skills.utils.ts | 5 ++ .../standard-skills.service.ts} | 12 ++-- 37 files changed, 147 insertions(+), 201 deletions(-) rename src/apps/learn/src/lib/data-providers/tca-certifications-provider/{tca-emsi-skill-type.ts => tca-skill-type.ts} (75%) delete mode 100644 src/apps/talent-search/src/lib/models/MemberEmsiSkill.ts delete mode 100644 src/libs/core/lib/profile/data-providers/useMemberSkills.ts delete mode 100644 src/libs/shared/lib/services/emsi-skills/skill.model.ts delete mode 100644 src/libs/shared/lib/services/emsi-skills/skills.utils.ts rename src/libs/shared/lib/services/{emsi-skills => standard-skills}/index.ts (59%) create mode 100644 src/libs/shared/lib/services/standard-skills/skill.model.ts create mode 100644 src/libs/shared/lib/services/standard-skills/skills.utils.ts rename src/libs/shared/lib/services/{emsi-skills/emsi-skills.service.ts => standard-skills/standard-skills.service.ts} (73%) diff --git a/src/apps/learn/src/lib/components/skill-tags/SkillTags.tsx b/src/apps/learn/src/lib/components/skill-tags/SkillTags.tsx index a869762f1..cbc54de95 100644 --- a/src/apps/learn/src/lib/components/skill-tags/SkillTags.tsx +++ b/src/apps/learn/src/lib/components/skill-tags/SkillTags.tsx @@ -5,7 +5,7 @@ import { Tooltip } from '~/libs/ui' import { EnvironmentConfig } from '~/config' import { SkillLabel } from '..' -import { TCAEMSISkillType } from '../../data-providers' +import { TCASkillType } from '../../data-providers' import styles from './SkillTags.module.scss' @@ -15,7 +15,7 @@ interface SkillTagsProps { label?: string theme?: 'white' | 'gray' | undefined skills?: Array | null | undefined - emsiSkills?: TCAEMSISkillType[] + emsiSkills?: TCASkillType[] } const SkillTags: FC = (props: SkillTagsProps) => { @@ -24,7 +24,7 @@ const SkillTags: FC = (props: SkillTagsProps) => { const label: string = props.label ?? 'skills taught' const tcaEMSIEnabled: boolean = EnvironmentConfig.ENABLE_EMSI_SKILLS || false - const skills: string[] | TCAEMSISkillType[] = tcaEMSIEnabled ? (props.emsiSkills || []) : (props.skills || []) + const skills: string[] | TCASkillType[] = tcaEMSIEnabled ? (props.emsiSkills || []) : (props.skills || []) return (
@@ -32,7 +32,7 @@ const SkillTags: FC = (props: SkillTagsProps) => { {label} )} {skills?.slice(0, expandCount) - .map((skill: string | TCAEMSISkillType) => ( + .map((skill: string | TCASkillType) => ( - emsiSkills: Array + emsiSkills: Array estimatedCompletionTimeValue: number estimatedCompletionTimeUnits: string fccCourseUuid: string diff --git a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/index.ts b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/index.ts index 13e3b668f..db94899b4 100644 --- a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/index.ts +++ b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/index.ts @@ -17,4 +17,4 @@ export * from './tca-certification-progress' export * from './tca-certification-enrollment-base.model' export * from './tca-certification-validation' export * from './tca-certification-enrollment' -export * from './tca-emsi-skill-type' +export * from './tca-skill-type' diff --git a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-certification.model.ts b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-certification.model.ts index 0661d69f6..ef6e9d0ae 100644 --- a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-certification.model.ts +++ b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-certification.model.ts @@ -5,7 +5,7 @@ import { TCACertificationCompletionTimeRange } from './tca-certification-complet import { TCACertificationProvider } from './tca-certification-provider.model' import { TCACertificationProviderBase } from './tca-certification-provider.model-base' import { TCACertificationResource } from './tca-certification-resource.model' -import { TCAEMSISkillType } from './tca-emsi-skill-type' +import { TCASkillType } from './tca-skill-type' export interface TCACertification { certificationCategory: TCACertificationCategory @@ -16,7 +16,7 @@ export interface TCACertification { createdAt: Date dashedName: string description: string - emsiSkills: Array + emsiSkills: Array id: number introText: string learnerLevel: TCACertificationLearnLevel diff --git a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-emsi-skill-type.ts b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-skill-type.ts similarity index 75% rename from src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-emsi-skill-type.ts rename to src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-skill-type.ts index 12b67f1c3..4f331194a 100644 --- a/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-emsi-skill-type.ts +++ b/src/apps/learn/src/lib/data-providers/tca-certifications-provider/tca-skill-type.ts @@ -1,4 +1,4 @@ -export type TCAEMSISkillType = { +export type TCASkillType = { assessed: boolean confidence: number emsiId: string diff --git a/src/apps/learn/src/welcome/tc-certifications/cert-card/TCCertCard.tsx b/src/apps/learn/src/welcome/tc-certifications/cert-card/TCCertCard.tsx index 014058619..e2b38ecd9 100644 --- a/src/apps/learn/src/welcome/tc-certifications/cert-card/TCCertCard.tsx +++ b/src/apps/learn/src/welcome/tc-certifications/cert-card/TCCertCard.tsx @@ -19,7 +19,7 @@ import { TCACertification, TCACertificationProgress, TCACertificationProviderBase, - TCAEMSISkillType, + TCASkillType, } from '../../../lib' import styles from './TCCertCard.module.scss' @@ -43,7 +43,7 @@ const TCCertCard: FC = (props: TCCertCardProps) => { skills: string[], providers: Array, dashedName: string - emsiSkills: TCAEMSISkillType[] + emsiSkills: TCASkillType[] } = props.certification const isEnrolled: boolean = props.progress?.status === 'enrolled' diff --git a/src/apps/onboarding/src/models/MemberInfo.ts b/src/apps/onboarding/src/models/MemberInfo.ts index 8de57ff6d..41e301d5e 100644 --- a/src/apps/onboarding/src/models/MemberInfo.ts +++ b/src/apps/onboarding/src/models/MemberInfo.ts @@ -1,5 +1,6 @@ -import { MemberEmsiSkill, MemberMaxRating } from '~/apps/talent-search/src/lib/models' +import { MemberMaxRating } from '~/apps/talent-search/src/lib/models' import { MemberStats } from '~/libs/core' +import { Skill } from '~/libs/shared' import MemberAddress from './MemberAddress' @@ -13,7 +14,7 @@ export default interface MemberInfo { email: string accountAge: number maxRating: MemberMaxRating - emsiSkills: Array + emsiSkills: Array stats: Array addresses?: MemberAddress[] country: string diff --git a/src/apps/onboarding/src/pages/skills/index.tsx b/src/apps/onboarding/src/pages/skills/index.tsx index 8d931d7b3..064e02cc7 100644 --- a/src/apps/onboarding/src/pages/skills/index.tsx +++ b/src/apps/onboarding/src/pages/skills/index.tsx @@ -16,12 +16,12 @@ export const PageSkillsContent: FC<{ }> = props => { const navigate: any = useNavigate() const [loading, setLoading] = useState(false) - const { formInput: emsiFormInput, saveSkills: saveEmsiSkills }: MemberSkillEditor = useMemberSkillEditor() + const editor: MemberSkillEditor = useMemberSkillEditor() async function saveSkills(): Promise { setLoading(true) try { - await saveEmsiSkills() + await editor.saveSkills() } catch (error) { } @@ -46,7 +46,7 @@ export const PageSkillsContent: FC<{ Understanding your skills will allow us to connect you to the right opportunities.
- {emsiFormInput} + {editor.formInput}
diff --git a/src/apps/profiles/src/member-profile/MemberProfile.context.tsx b/src/apps/profiles/src/member-profile/MemberProfile.context.tsx index 052f3562b..a27f799d0 100644 --- a/src/apps/profiles/src/member-profile/MemberProfile.context.tsx +++ b/src/apps/profiles/src/member-profile/MemberProfile.context.tsx @@ -1,11 +1,11 @@ import { createContext, FC, ReactNode, useContext, useMemo } from 'react' -import { UserEMSISkill } from '~/libs/core' +import { Skill } from '~/libs/shared' export interface MemberProfileContextValue { isTalentSearch?: boolean skillsRenderer?: ( - skills: Pick[] + skills: Pick[] ) => ReactNode } diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index 015f2feec..cb70e6251 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -2,7 +2,7 @@ import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from 'reac import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' -import { UserEMSISkill, UserProfile } from '~/libs/core' +import { UserProfile } from '~/libs/core' import { ExpandableList, HowSkillsWorkModal, isSkillVerified, Skill, SkillPill } from '~/libs/shared' import { Button } from '~/libs/ui' @@ -27,11 +27,11 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp const { skillsRenderer, isTalentSearch }: MemberProfileContextValue = useMemberProfileContext() - const memberEMSISkills: UserEMSISkill[] = useMemo(() => orderBy( + const memberSkills: Skill[] = useMemo(() => orderBy( props.profile.emsiSkills ?? [], [isSkillVerified, 'name'], ['desc', 'asc'], - ) as UserEMSISkill[], [props.profile.emsiSkills]) + ) as Skill[], [props.profile.emsiSkills]) const [isEditMode, setIsEditMode]: [boolean, Dispatch>] = useState(false) @@ -76,7 +76,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp

Skills

{ - canEdit && memberEMSISkills.length > 0 && ( + canEdit && memberSkills.length > 0 && ( @@ -92,22 +92,22 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp
- {skillsRenderer && memberEMSISkills.length > 0 && skillsRenderer(memberEMSISkills)} - {!skillsRenderer && memberEMSISkills.length > 0 && ( + {skillsRenderer && memberSkills.length > 0 && skillsRenderer(memberSkills)} + {!skillsRenderer && memberSkills.length > 0 && ( { - memberEMSISkills - .map(memberEMSISkill => ( + memberSkills + .map(memberSkill => ( )) } )} - {!memberEMSISkills.length && ( + {!memberSkills.length && ( = (props: MemberSkillsInfoProp )}
- {canEdit && !memberEMSISkills.length && ( + {canEdit && !memberSkills.length && ( = (props: ModifySkillsModalP const [isSaving, setIsSaving]: [boolean, Dispatch>] = useState(false) - const { formInput: emsiFormInput, saveSkills: saveEmsiSkills }: MemberSkillEditor = useMemberSkillEditor() + const editor: MemberSkillEditor = useMemberSkillEditor() function handleModifySkillsSave(): void { setIsSaving(true) - saveEmsiSkills() + editor.saveSkills() .then(() => { toast.success('Skills updated successfully.', { position: toast.POSITION.BOTTOM_RIGHT }) props.onSave() @@ -63,7 +63,7 @@ const ModifySkillsModal: FC = (props: ModifySkillsModalP Understanding your skills will allow us to connect you to the right opportunities.

- {emsiFormInput} + {editor.formInput}
diff --git a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx index fdd256287..039cc6a4d 100644 --- a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx +++ b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx @@ -9,22 +9,22 @@ import styles from './PopularSkills.module.scss' // TODO: Make this configurable, or read from a service. We need to discuss // how we want to handle this. const popularSkills: Skill[] = [ - { emsiId: 'KS120076FGP5WGWYMP0F', name: 'Java (Programming Language)' }, - { emsiId: 'KS126QY605N7YVHFYCTW', name: 'MySQL' }, - { emsiId: 'KS127296VDYS7ZFWVC46', name: 'Node.js' }, - { emsiId: 'KS121F45VPV8C9W3QFYH', name: 'Cascading Style Sheets (CSS)' }, - { emsiId: 'KS1200771D9CR9LB4MWW', name: 'JavaScript (Programming Language)' }, - { emsiId: 'KS1261Z68KSKR1X31KS3', name: 'Machine Learning' }, - { emsiId: 'KS120SX72T8B5VLXS1VN', name: 'Unit Testing' }, - { emsiId: 'KS120H6772VQ0MQ5RLVD', name: 'Angular (Web Framework)' }, - { emsiId: 'KS1200B62W5ZF38RJ7TD', name: '.NET Framework' }, - { emsiId: 'KS125LS6N7WP4S6SFTCK', name: 'Python (Programming Language)' }, - { emsiId: 'KS120GZ5YXC6YVM1NGPR', name: 'Android (Operating System)' }, - { emsiId: 'ES5269FD2583B0B9875C', name: 'Figma (Design Software)' }, - { emsiId: 'KS120V86MZWV9Z9LKQY3', name: 'Microsoft Azure' }, - { emsiId: 'KS1206V6K46N1SDVJGBD', name: 'Adobe Illustrator' }, - { emsiId: 'KSY4WFI1S164RQUBSPCC', name: 'Docker (Software)' }, - { emsiId: 'KSDJCA4E89LB98JAZ7LZ', name: 'React.js' }, + { id: 'f81d2a78-ff52-4c77-8cdb-8863601b87c7', name: 'Java (Programming Language)' }, + { id: '1aabc882-c28d-4b56-8546-5e961b53bf5d', name: 'MySQL' }, + { id: 'b3181231-af8f-4a44-aff2-97fe00c57d76', name: 'Node.js' }, + { id: '4328c534-ba51-4589-a3e7-7b5ba76d2b55', name: 'Cascading Style Sheets (CSS)' }, + { id: 'e3b2b1f1-6bbf-4989-b53d-d8531a10ea5d', name: 'JavaScript (Programming Language)' }, + { id: '41ffc4d5-2e43-45e1-af36-ae7a23b47c21', name: 'Machine Learning' }, + { id: '047203fc-8c85-4be0-be0b-0e2fe11c3a16', name: 'Unit Testing' }, + { id: '8c6703bd-63dd-4f6d-9cf0-5b411e531a9f', name: 'Angular (Web Framework)' }, + { id: '34ec4bf0-0b44-4d04-9f11-e3daa2c045ce', name: '.NET Framework' }, + { id: 'a9bb69aa-edc2-4d5f-8141-de33a139f119', name: 'Python (Programming Language)' }, + { id: '67c623db-09e4-499d-800b-24868b1eb85b', name: 'Android (Operating System)' }, + { id: '36292f61-c359-42a4-89b9-95245ee494ea', name: 'Figma (Design Software)' }, + { id: 'cf39f07c-0e7a-48a2-acec-21834900c437', name: 'Microsoft Azure' }, + { id: 'b33f8342-8015-4244-afea-5fd089bf52a6', name: 'Adobe Illustrator' }, + { id: 'f21aecd2-5c67-4783-97a4-a77c67cf4f67', name: 'Docker (Software)' }, + { id: '43baf79e-3632-4b04-889a-7202cbf62a6c', name: 'React.js' }, ] interface PopularSkillsProps { @@ -41,7 +41,7 @@ const PopularSkills: FC = props => { // Either delete the value from the list, if we're toggling one that's already in the list // Or add the new item to the list props.selectedSkills.forEach(filterSkill => { - if (filterSkill.emsiId === skill.emsiId) { + if (filterSkill.id === skill.id) { deleted = true } else { newFilter.push(filterSkill) @@ -59,7 +59,7 @@ const PopularSkills: FC = props => { }, [props.onChange, props.selectedSkills]) function isSelected(skill: Skill): boolean { - return !!props.selectedSkills.find(s => s.emsiId === skill.emsiId) + return !!props.selectedSkills.find(s => s.id === skill.id) } return ( @@ -69,7 +69,7 @@ const PopularSkills: FC = props => {
{popularSkills.map(skill => ( [] + profileSkills: Pick[] queriedSkills: Skill[] } const ProfileSkillsMatch: FC = props => { const isMatchingSkill = useIsMatchingSkill(props.queriedSkills) - const matchedSkills = (props.profileSkills as unknown as EmsiSkill[]).filter(isMatchingSkill) - const unMatchedSkills = (props.profileSkills as unknown as EmsiSkill[]).filter(s => !isMatchingSkill(s)) + const matchedSkills = props.profileSkills.filter(isMatchingSkill) + const unMatchedSkills = props.profileSkills.filter(s => !isMatchingSkill(s)) const provenMatched = matchedSkills.filter(isSkillVerified) const selfSkillmatched = matchedSkills.filter(s => !isSkillVerified(s)) - const missingSkills = props.queriedSkills.filter(qs => !matchedSkills.find(ms => ms.skillId === qs.emsiId)) + const missingSkills = props.queriedSkills.filter(qs => !matchedSkills.find(ms => ms.id === qs.id)) return (
@@ -41,7 +40,7 @@ const ProfileSkillsMatch: FC = props => {
{provenMatched.map(skill => ( - + ))}
@@ -54,7 +53,7 @@ const ProfileSkillsMatch: FC = props => {
{selfSkillmatched.map(skill => ( - + ))}
@@ -82,7 +81,7 @@ const ProfileSkillsMatch: FC = props => {
{unMatchedSkills.map(skill => ( - + ))}
diff --git a/src/apps/talent-search/src/components/search-input/SearchInput.tsx b/src/apps/talent-search/src/components/search-input/SearchInput.tsx index 6dd084542..e1dcae54e 100644 --- a/src/apps/talent-search/src/components/search-input/SearchInput.tsx +++ b/src/apps/talent-search/src/components/search-input/SearchInput.tsx @@ -2,7 +2,7 @@ import { FC, MouseEvent, Ref, useMemo } from 'react' import classNames from 'classnames' import { IconOutline, InputMultiselectOption } from '~/libs/ui' -import { EmsiSkill, EmsiSkillSources, InputSkillSelector, Skill } from '~/libs/shared' +import { InputSkillSelector, Skill, SkillSources } from '~/libs/shared' import { SKILL_SEARCH_LIMIT } from '../../config' @@ -18,16 +18,16 @@ interface SearchInputProps { } const SearchInput: FC = props => { - const emsiSkills: EmsiSkill[] = useMemo(() => props.skills.map(s => ({ + const skills: Skill[] = useMemo(() => props.skills.map(s => ({ + id: s.id, name: s.name, - skillId: s.emsiId, - skillSources: [EmsiSkillSources.selfPicked], + skillSources: [SkillSources.selfPicked], })), [props.skills]) function onChange(ev: any): void { const options = (ev.target.value as unknown) as InputMultiselectOption[] props.onChange(options.map(v => ({ - emsiId: v.value, + id: v.value, name: v.label as string, }))) } @@ -41,13 +41,13 @@ const SearchInput: FC = props => { const searchIcon = useMemo(() => (
- ), [props.onSearch, emsiSkills]) + ), [props.onSearch, skills]) return (
@@ -58,13 +58,13 @@ const SearchInput: FC = props => { useWrapper={false} theme='clear' dropdownIcon={searchIcon} - value={emsiSkills} + value={skills} onChange={onChange} onSubmit={props.onSearch} inputRef={props.inputRef} limit={SKILL_SEARCH_LIMIT} /> - {emsiSkills.length >= SKILL_SEARCH_LIMIT && ( + {skills.length >= SKILL_SEARCH_LIMIT && (
{`You can only search up to ${SKILL_SEARCH_LIMIT} skills at one time`}
diff --git a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx index f5feac5bb..0ff6a0fee 100644 --- a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx +++ b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx @@ -129,7 +129,7 @@ const TalentCard: FC = props => {
+0 more matched skill
{matchedSkills.length > 0 && matchedSkills.map(skill => ( diff --git a/src/apps/talent-search/src/lib/models/Member.ts b/src/apps/talent-search/src/lib/models/Member.ts index 793e5e1a6..5798a4da3 100644 --- a/src/apps/talent-search/src/lib/models/Member.ts +++ b/src/apps/talent-search/src/lib/models/Member.ts @@ -1,6 +1,7 @@ +import { Skill } from '~/libs/shared' + import { MemberDisplayName } from './MemberDisplayName' import MemberAddress from './MemberAddress' -import MemberEmsiSkill from './MemberEmsiSkill' import MemberMaxRating from './MemberMaxRating' import MemberStats from './MemberStats' @@ -12,7 +13,7 @@ export default interface Member { createdAt: number; description: string; email: string; - emsiSkills: Array ; + emsiSkills: Array ; firstName: string; handle: string; homeCountryCode: string; diff --git a/src/apps/talent-search/src/lib/models/MemberEmsiSkill.ts b/src/apps/talent-search/src/lib/models/MemberEmsiSkill.ts deleted file mode 100644 index df133b182..000000000 --- a/src/apps/talent-search/src/lib/models/MemberEmsiSkill.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { EmsiSkillSources } from '~/libs/shared' - -export default interface MemberEmsiSkill { - skillSources: EmsiSkillSources[]; - skillSubcategory: EmsiSkillSources; - skillId: string - name: string; - category: string; -} diff --git a/src/apps/talent-search/src/lib/models/index.ts b/src/apps/talent-search/src/lib/models/index.ts index f244db5b4..4179a1aca 100644 --- a/src/apps/talent-search/src/lib/models/index.ts +++ b/src/apps/talent-search/src/lib/models/index.ts @@ -1,5 +1,4 @@ export type { default as Member } from './Member' -export type { default as MemberEmsiSkill } from './MemberEmsiSkill' export type { default as MemberMaxRating } from './MemberMaxRating' export type { default as MemberStats } from './MemberStats' export { MemberDisplayName } from './MemberDisplayName' diff --git a/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts b/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts index a91ed3a8e..4d6f4fe13 100644 --- a/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts +++ b/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts @@ -23,7 +23,7 @@ export function useFetchTalentMatches( pageSize: number, ): TalentMatchesResponse { const searchParams = [ - ...skills.map(s => `skillId=${s.emsiId}`), + ...skills.map(s => `id=${s.id}`), 'sortBy=skillScore', 'includeStats=false', `page=${page}`, diff --git a/src/apps/talent-search/src/lib/utils/search-query.tsx b/src/apps/talent-search/src/lib/utils/search-query.tsx index 237d9b0f1..f93bd9eab 100644 --- a/src/apps/talent-search/src/lib/utils/search-query.tsx +++ b/src/apps/talent-search/src/lib/utils/search-query.tsx @@ -5,14 +5,14 @@ import { Skill } from '~/libs/shared' export const encodeUrlQuerySearch = (skills: Skill[]): string => ( skills - .map(s => `q=${encodeURIComponent(`${s.name}::${s.emsiId}`)}`) + .map(s => `q=${encodeURIComponent(`${s.name}::${s.id}`)}`) .join('&') ) export const parseUrlQuerySearch = (params: string[]): Skill[] => ( params.map(p => { - const [name, emsiId] = p.split('::') - return { emsiId, name } + const [name, id] = p.split('::') + return { id, name } }) ) diff --git a/src/apps/talent-search/src/lib/utils/skills.utils.tsx b/src/apps/talent-search/src/lib/utils/skills.utils.tsx index 25b373f46..772749cff 100644 --- a/src/apps/talent-search/src/lib/utils/skills.utils.tsx +++ b/src/apps/talent-search/src/lib/utils/skills.utils.tsx @@ -1,12 +1,12 @@ import { useCallback } from 'react' -import { EmsiSkill, Skill } from '~/libs/shared' +import { Skill } from '~/libs/shared' -export type IsMatchingSkillFn = (skill: EmsiSkill) => boolean +export type IsMatchingSkillFn = (skill: Pick) => boolean export const useIsMatchingSkill = (skills: Skill[]): IsMatchingSkillFn => { - const isMatchingSkill = useCallback((skill: EmsiSkill) => ( - !!skills.find(s => skill.skillId === s.emsiId) + const isMatchingSkill = useCallback((skill: Pick) => ( + !!skills.find(s => skill.id === s.id) ), [skills]) return isMatchingSkill diff --git a/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx b/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx index b077a0bfe..4bd1d2eb6 100644 --- a/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx +++ b/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx @@ -2,14 +2,14 @@ import { FC, ReactNode } from 'react' import { Location, useLocation } from 'react-router-dom' import { MemberProfileContext, MemberProfilePage } from '@profiles/member-profile' -import { UserEMSISkill } from '~/libs/core' +import { Skill } from '~/libs/shared' import { ProfileSkillsMatch } from '../../components/profile-skills-match' const TalentPage: FC = () => { const { state }: Location = useLocation() - function skillsRenderer(profileSkills: Pick[]): ReactNode { + function skillsRenderer(profileSkills: Pick[]): ReactNode { return ( ({ id: skillKey, ...data.skills[skillKey] })) - // sort by challenge verified first - .sort((a, b) => b.sources.indexOf('CHALLENGE') - a.sources.indexOf('CHALLENGE')) : undefined - - return skills -} diff --git a/src/libs/core/lib/profile/profile-functions/rating.functions.ts b/src/libs/core/lib/profile/profile-functions/rating.functions.ts index 4ee00920f..05d1c6620 100644 --- a/src/libs/core/lib/profile/profile-functions/rating.functions.ts +++ b/src/libs/core/lib/profile/profile-functions/rating.functions.ts @@ -1,7 +1,5 @@ import { CSSProperties } from 'react' -import { EMSISkillSources } from '../user-skill.model' - export const TC_RATING_COLORS: Array<{ color: string, limit: number }> = [{ color: '#555555' /* Grey */, limit: 900, @@ -32,7 +30,3 @@ export function ratingToCSScolor(rating: number): CSSProperties { color, } } - -export function isVerifiedSkill(skillOriginSources: EMSISkillSources[]): boolean { - return skillOriginSources.includes('TCACertified') || skillOriginSources.includes('ChallengeWin') -} diff --git a/src/libs/core/lib/profile/user-profile.model.ts b/src/libs/core/lib/profile/user-profile.model.ts index 63db0e186..f5ccd0e9b 100644 --- a/src/libs/core/lib/profile/user-profile.model.ts +++ b/src/libs/core/lib/profile/user-profile.model.ts @@ -1,4 +1,4 @@ -import { UserEMSISkill } from './user-skill.model' +import { UserSkill } from './user-skill.model' export type TC_TRACKS = 'DEVELOP' | 'DESIGN' | 'DATA_SCIENCE' @@ -15,7 +15,7 @@ export interface UserProfile { description: string diceEnabled: boolean email: string - emsiSkills: Array + emsiSkills: Array firstName: string handle: string handleLower: string diff --git a/src/libs/core/lib/profile/user-skill.model.ts b/src/libs/core/lib/profile/user-skill.model.ts index 2ad685542..9d454b519 100644 --- a/src/libs/core/lib/profile/user-skill.model.ts +++ b/src/libs/core/lib/profile/user-skill.model.ts @@ -1,25 +1,19 @@ -export type skillSources = 'USER_ENTERED' | 'CHALLENGE' - -export type UserSkill = { - id: number - hidden: boolean - score: number - sources: skillSources[] - tagName: string +export enum SkillSources { + selfPicked = 'SelfPicked', + challengeWin = 'ChallengeWin', + tcaCertified = 'TCACertified', } -export type EMSISkillSources = 'TCACertified' | 'SelfPicked' | 'ChallengeWin' - -export type UserEMSISkill = { +export type UserSkill = { id: string name: string - skillCategory: { + skillCategory?: { name: string id: number } - skillId: string - skillSources: Array - skillSubcategory: { + skillId?: string + skillSources?: SkillSources[] + skillSubcategory?: { name: string id: number } diff --git a/src/libs/shared/lib/components/input-skill-selector/InputSkillSelector.tsx b/src/libs/shared/lib/components/input-skill-selector/InputSkillSelector.tsx index 20f539681..a9683575d 100644 --- a/src/libs/shared/lib/components/input-skill-selector/InputSkillSelector.tsx +++ b/src/libs/shared/lib/components/input-skill-selector/InputSkillSelector.tsx @@ -3,12 +3,12 @@ import { noop } from 'lodash' import { InputMultiselect, InputMultiselectOption, InputMultiselectThemes } from '~/libs/ui' -import { autoCompleteSkills, EmsiSkill, isSkillVerified } from '../../services/emsi-skills' +import { autoCompleteSkills, isSkillVerified, Skill } from '../../services/standard-skills' -const mapEmsiSkillToInputOption = (skill: EmsiSkill): InputMultiselectOption => ({ +const mapSkillToInputOption = (skill: Skill): InputMultiselectOption => ({ ...skill, label: skill.name, - value: skill.skillId, + value: skill.id, verified: isSkillVerified(skill), }) @@ -22,7 +22,7 @@ const fetchSkills = (queryTerm: string): Promise => ( .then(skills => ( skills.map(skill => ({ label: skill.name, - value: skill.emsiId, + value: skill.id, })) )) ) @@ -35,7 +35,7 @@ interface InputSkillSelectorProps { readonly loading?: boolean readonly onChange?: (event: ChangeEvent) => void readonly placeholder?: string - readonly value?: EmsiSkill[] + readonly value?: Skill[] readonly theme?: InputMultiselectThemes readonly useWrapper?: boolean readonly dropdownIcon?: ReactNode @@ -54,7 +54,7 @@ const InputSkillSelector: FC = props => ( onFetchOptions={fetchSkills} name='skills' onChange={props.onChange ?? noop} - value={props.value?.map(mapEmsiSkillToInputOption)} + value={props.value?.map(mapSkillToInputOption)} loading={props.loading} theme={props.theme} useWrapper={props.useWrapper} diff --git a/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx b/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx index 22279a336..613683028 100644 --- a/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx +++ b/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx @@ -4,13 +4,13 @@ import { differenceWith } from 'lodash' import { profileContext, ProfileContextData } from '~/libs/core' import { - createMemberEmsiSkills, - EmsiSkill, - EmsiSkillSources, + createMemberSkills, fetchMemberSkills, isSkillVerified, - updateMemberEmsiSkills, -} from '../../services/emsi-skills' + Skill, + SkillSources, + updateMemberSkills, +} from '../../services/standard-skills' import { InputSkillSelector } from '../input-skill-selector' export interface MemberSkillEditor { @@ -22,11 +22,11 @@ export interface MemberSkillEditor { * Hook to provide functionality for using the member skill editor * Usage example: * ``` - * const { formInput: emsiFormInput, saveSkills: saveEmsiSkills }: MemberSkillEditor = useMemberSkillEditor() + * const editor: MemberSkillEditor = useMemberSkillEditor() * ... * <> - * {emsiFormInput} - * + * {editor.formInput} + * * * ``` * @returns @@ -36,31 +36,31 @@ export const useMemberSkillEditor = ({ limit, }: {limit?: number} = {}): MemberSkillEditor => { const { profile }: ProfileContextData = useContext(profileContext) - const [isEmsiInitialized, setIsEmsiInitialized] = useState(false) - const [skills, setSkills] = useState([]) + const [isInitialized, setIsInitialized] = useState(false) + const [skills, setSkills] = useState([]) const [loading, setLoading] = useState(true) const [, setError] = useState() - // Function that saves the updated emsi skills, will be called from outside + // Function that saves the updated skills, will be called from outside const saveSkills = useCallback(async () => { if (!profile?.userId) { return } - const emsiSkills = skills.map(s => ({ emsiId: s.skillId, name: s.name, sources: s.skillSources })) - if (!isEmsiInitialized) { - await createMemberEmsiSkills(profile.userId, emsiSkills) - setIsEmsiInitialized(true) + const memberSkills = skills.map(s => ({ id: s.id, name: s.name, sources: s.skillSources })) + if (!isInitialized) { + await createMemberSkills(profile.userId, memberSkills) + setIsInitialized(true) return } - await updateMemberEmsiSkills(profile.userId, emsiSkills) - }, [isEmsiInitialized, profile?.userId, skills]) + await updateMemberSkills(profile.userId, memberSkills) + }, [isInitialized, profile?.userId, skills]) // Handle user changes const handleRemoveSkill = useCallback((skillId: string): void => { - const skill = skills.find(s => s.skillId === skillId) + const skill = skills.find(s => s.id === skillId) if (!skill) { return } @@ -69,25 +69,25 @@ export const useMemberSkillEditor = ({ return } - setSkills(skills.filter(s => s.skillId !== skillId)) + setSkills(skills.filter(s => s.id !== skillId)) }, [skills]) const handleAddSkill = useCallback((skillData: any): void => { - if (skills.find(s => s.skillId === skillData.value)) { + if (skills.find(s => s.id === skillData.value)) { return } setSkills([...skills, { + id: skillData.value, name: skillData.label, - skillId: skillData.value, - skillSources: [EmsiSkillSources.selfPicked], + skillSources: [SkillSources.selfPicked], }]) }, [skills]) const handleOnChange = useCallback(({ target: { value } }: any): void => { - const removed = differenceWith(skills, value, (s, v: any) => s.skillId === v.value) + const removed = differenceWith(skills, value, (s, v: any) => s.id === v.value) if (removed.length) { - removed.map(s => handleRemoveSkill(s.skillId)) + removed.map(s => handleRemoveSkill(s.id)) } const added = differenceWith(value, skills, (v: any, s: any) => v.value === s.skillId) @@ -96,7 +96,7 @@ export const useMemberSkillEditor = ({ } }, [handleAddSkill, handleRemoveSkill, skills]) - // Load member's emsi skills, set loading state & isEmsiInitialized + // Load member's skills, set loading state & isInitialized useEffect(() => { if (!profile?.userId) { return undefined @@ -108,13 +108,13 @@ export const useMemberSkillEditor = ({ setError(e?.message ?? e) return [] }) - .then(emsiSkills => { + .then(savedSkills => { if (!mounted) { return } - setIsEmsiInitialized(emsiSkills?.length > 0) - setSkills(emsiSkills) + setIsInitialized(savedSkills?.length > 0) + setSkills(savedSkills) setLoading(false) }) diff --git a/src/libs/shared/lib/services/emsi-skills/skill.model.ts b/src/libs/shared/lib/services/emsi-skills/skill.model.ts deleted file mode 100644 index c221cb8b0..000000000 --- a/src/libs/shared/lib/services/emsi-skills/skill.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -export enum EmsiSkillSources { - selfPicked = 'SelfPicked', - challengeWin = 'ChallengeWin', -} - -export interface Skill { - name: string; - emsiId: string; - skillSources?: EmsiSkillSources[]; -} - -export interface EmsiSkill { - name: string; - skillId: string; - skillSources: EmsiSkillSources[] -} diff --git a/src/libs/shared/lib/services/emsi-skills/skills.utils.ts b/src/libs/shared/lib/services/emsi-skills/skills.utils.ts deleted file mode 100644 index 8a54ee068..000000000 --- a/src/libs/shared/lib/services/emsi-skills/skills.utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { EmsiSkill, EmsiSkillSources } from './skill.model' - -export const isSkillVerified = (skill: Pick): boolean => ( - !!skill.skillSources?.includes(EmsiSkillSources.challengeWin) -) diff --git a/src/libs/shared/lib/services/index.ts b/src/libs/shared/lib/services/index.ts index ef94db4f5..b7999a344 100644 --- a/src/libs/shared/lib/services/index.ts +++ b/src/libs/shared/lib/services/index.ts @@ -1 +1 @@ -export * from './emsi-skills' +export * from './standard-skills' diff --git a/src/libs/shared/lib/services/emsi-skills/index.ts b/src/libs/shared/lib/services/standard-skills/index.ts similarity index 59% rename from src/libs/shared/lib/services/emsi-skills/index.ts rename to src/libs/shared/lib/services/standard-skills/index.ts index a80550778..97cfcafe3 100644 --- a/src/libs/shared/lib/services/emsi-skills/index.ts +++ b/src/libs/shared/lib/services/standard-skills/index.ts @@ -1,3 +1,3 @@ export * from './skill.model' -export * from './emsi-skills.service' +export * from './standard-skills.service' export * from './skills.utils' diff --git a/src/libs/shared/lib/services/standard-skills/skill.model.ts b/src/libs/shared/lib/services/standard-skills/skill.model.ts new file mode 100644 index 000000000..e70eba5e1 --- /dev/null +++ b/src/libs/shared/lib/services/standard-skills/skill.model.ts @@ -0,0 +1,2 @@ +export { SkillSources } from '~/libs/core' +export type { UserSkill as Skill } from '~/libs/core' diff --git a/src/libs/shared/lib/services/standard-skills/skills.utils.ts b/src/libs/shared/lib/services/standard-skills/skills.utils.ts new file mode 100644 index 000000000..f64e15054 --- /dev/null +++ b/src/libs/shared/lib/services/standard-skills/skills.utils.ts @@ -0,0 +1,5 @@ +import { Skill, SkillSources } from './skill.model' + +export const isSkillVerified = (skill: Pick): boolean => ( + !!skill.skillSources?.includes(SkillSources.challengeWin) +) diff --git a/src/libs/shared/lib/services/emsi-skills/emsi-skills.service.ts b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts similarity index 73% rename from src/libs/shared/lib/services/emsi-skills/emsi-skills.service.ts rename to src/libs/shared/lib/services/standard-skills/standard-skills.service.ts index 067cab1c4..a1bf91e85 100644 --- a/src/libs/shared/lib/services/emsi-skills/emsi-skills.service.ts +++ b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts @@ -1,7 +1,7 @@ import { EnvironmentConfig } from '~/config' import { xhrGetAsync, xhrPostAsync, xhrPutAsync } from '~/libs/core' -import { EmsiSkill, Skill } from './skill.model' +import { Skill } from './skill.model' const baseUrl = `${EnvironmentConfig.API.V5}/emsi-skills/member-emsi-skills` @@ -20,20 +20,20 @@ export type FetchMemberSkillsConfig = { export async function fetchMemberSkills( userId: string | number | undefined, config: FetchMemberSkillsConfig, -): Promise { +): Promise { const url = `${baseUrl}/${userId}?pageFlag=${!config.skipPagination}` return xhrGetAsync(url) } -export async function createMemberEmsiSkills(userId: number, skills: Skill[]): Promise { +export async function createMemberSkills(userId: number, skills: Skill[]): Promise { return xhrPostAsync(baseUrl, { - emsiSkills: skills, + skills, userId, }) } -export async function updateMemberEmsiSkills(userId: string | number, skills: Skill[]): Promise { +export async function updateMemberSkills(userId: string | number, skills: Skill[]): Promise { return xhrPutAsync(`${baseUrl}/${userId}`, { - emsiSkills: skills, + skills, }) } From 079bce46b68014108e0d7599a34063903c8a8a05 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 11 Oct 2023 10:23:12 +0300 Subject: [PATCH 03/32] TSJR-111 implement skills category UI --- .../skills/MemberSkillsInfo.module.scss | 29 +++------ .../skills/MemberSkillsInfo.tsx | 46 ++++++++++---- .../skill-pill/SkillPill.module.scss | 6 ++ .../lib/components/skill-pill/SkillPill.tsx | 5 +- .../CollapsibleSkillsList.module.scss | 63 +++++++++++++++++++ .../CollapsibleSkillsList.tsx | 46 ++++++++++++++ .../collapsible-skills-list/index.ts | 1 + src/libs/ui/lib/components/index.ts | 1 + 8 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss create mode 100644 src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx create mode 100644 src/libs/ui/lib/components/collapsible-skills-list/index.ts diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss index 761f7b188..9122b2814 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss @@ -31,25 +31,16 @@ column-gap: $sp-1; row-gap: $sp-2; - .skillItem { - border: 1px solid $black-20; - font-size: 14px; - line-height: 16px; - white-space: nowrap; - padding: $sp-2 $sp-3; - border-radius: 24px; - display: flex; - align-items: center; - - &.verifiedSkillItem { - border: 2px solid $turq-120; - - svg { - margin-left: $sp-1; - width: 16px; - height: 16px; - color: $turq-120; - } + .skillsCategories { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: $sp-4; + flex: 1; + + @include ltemd { + grid-template-columns: 1fr; + gap: 0; + row-gap: $sp-4; } } } diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index 015f2feec..bca3b9e1e 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -3,8 +3,8 @@ import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' import { UserEMSISkill, UserProfile } from '~/libs/core' -import { ExpandableList, HowSkillsWorkModal, isSkillVerified, Skill, SkillPill } from '~/libs/shared' -import { Button } from '~/libs/ui' +import { HowSkillsWorkModal, isSkillVerified, Skill, SkillPill } from '~/libs/shared' +import { Button, CollapsibleSkillsList } from '~/libs/ui' import { AddButton, EditMemberPropertyBtn, EmptySection } from '../../components' import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config' @@ -33,6 +33,20 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp ['desc', 'asc'], ) as UserEMSISkill[], [props.profile.emsiSkills]) + const groupedSkillsByCategory: { [key: string]: UserEMSISkill[] } = useMemo(() => { + const grouped: { [key: string]: UserEMSISkill[] } = {} + + memberEMSISkills.forEach((skill: UserEMSISkill) => { + if (grouped[skill.skillCategory.name]) { + grouped[skill.skillCategory.name].push(skill) + } else { + grouped[skill.skillCategory.name] = [skill] + } + }) + + return grouped + }, [memberEMSISkills]) + const [isEditMode, setIsEditMode]: [boolean, Dispatch>] = useState(false) @@ -94,18 +108,28 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp
{skillsRenderer && memberEMSISkills.length > 0 && skillsRenderer(memberEMSISkills)} {!skillsRenderer && memberEMSISkills.length > 0 && ( - +
{ - memberEMSISkills - .map(memberEMSISkill => ( - + Object.keys(groupedSkillsByCategory) + .map((categoryName: string) => ( + + { + groupedSkillsByCategory[categoryName] + .map((skill: UserEMSISkill) => ( + + )) + } + )) } - +
)} {!memberEMSISkills.length && ( void selected?: boolean skill: Pick - theme?: 'dark' | 'verified' | 'presentation' | 'etc' + theme?: 'dark' | 'verified' | 'presentation' | 'etc' | 'catList' } const SkillPill: FC = props => { @@ -24,7 +24,8 @@ const SkillPill: FC = props => { styles.pill, props.onClick && styles.interactive, props.selected && styles.selected, - styles[`theme-${isVerified ? 'verified' : (props.theme ?? 'presentation')}`], + styles[`theme-${isVerified ? 'verified' : ''}`], + styles[`theme-${props.theme ?? ''}`], ) const handleClick = useCallback(() => props.onClick?.call(undefined, props.skill as Skill), [ diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss new file mode 100644 index 000000000..a42260371 --- /dev/null +++ b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss @@ -0,0 +1,63 @@ +@import '@libs/ui/styles/includes'; + +.container { + display: flex; + flex-direction: column; + background-color: $tc-white; + border-radius: 8px; + + &.collapsed { + .title { + font-weight: 400 !important; + } + + .content { + max-height: 0; + overflow: hidden; + padding: 0; + margin-top: 0; + opacity: 0; + } + } + + .header { + display: flex; + justify-content: flex-start; + align-items: center; + cursor: pointer; + + .title { + font-weight: 700; + font-size: 14px; + } + + .btn { + padding-left: 0; + padding-right: $sp-2; + color: $turq-120; + + svg { + flex: 0 0 auto; + color: $turq-120; + @include icon-size(16); + } + } + + .badgeCount { + background-color: $black-10; + border-radius: 50%; + padding: 0 $sp-2; + font-weight: 700; + font-size: 14px; + margin-left: $sp-2; + } + } + + .content { + transition: all 0.3s ease-in-out; + max-height: auto; + opacity: 1; + padding-left: $sp-8; + margin-top: $sp-1; + } +} \ No newline at end of file diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx new file mode 100644 index 000000000..75350f8f2 --- /dev/null +++ b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx @@ -0,0 +1,46 @@ +import { Dispatch, FC, ReactNode, SetStateAction, useState } from 'react' +import classNames from 'classnames' + +import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline' + +import { Button } from '../button' + +import styles from './CollapsibleSkillsList.module.scss' + +interface CollapsibleSkillsListProps { + children?: ReactNode[] + header?: ReactNode + containerClass?: string + headerClass?: string + contentClass?: string +} + +const CollapsibleSkillsList: FC = (props: CollapsibleSkillsListProps) => { + const [isCollapsed, setIsCollapsed]: [boolean, Dispatch>] = useState(true) + + function toggleCollapse(): void { + setIsCollapsed(!isCollapsed) + } + + return ( +
+
+ { + !isCollapsed + ?
+ +
+ {props.children} +
+
+ ) +} + +export default CollapsibleSkillsList diff --git a/src/libs/ui/lib/components/collapsible-skills-list/index.ts b/src/libs/ui/lib/components/collapsible-skills-list/index.ts new file mode 100644 index 000000000..8e5ba427d --- /dev/null +++ b/src/libs/ui/lib/components/collapsible-skills-list/index.ts @@ -0,0 +1 @@ +export { default as CollapsibleSkillsList } from './CollapsibleSkillsList' diff --git a/src/libs/ui/lib/components/index.ts b/src/libs/ui/lib/components/index.ts index 306c469d6..b2a0bbb5d 100644 --- a/src/libs/ui/lib/components/index.ts +++ b/src/libs/ui/lib/components/index.ts @@ -17,3 +17,4 @@ export * from './tooltip' export * from './button' export * from './collapsible' export * from './verified-member-badge' +export * from './collapsible-skills-list' From 8e5b9189e2d4d84e0bdf06d5656ef1e4224133a1 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 11 Oct 2023 10:26:57 +0300 Subject: [PATCH 04/32] ci: on dev --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a74a8ad7..32f33ca58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -262,6 +262,7 @@ workflows: - justin_fixes - talent_search_fixes - PROD-4398_integrate-userflow-remove-sprig + - TSJR-111 - deployQa: context: org-global From 138f279ddfb8a5c10db10744face828acc8aa17c Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Thu, 12 Oct 2023 11:47:57 +0300 Subject: [PATCH 05/32] TSJR-111 responsive skills UI --- package.json | 2 + .../skills/MemberSkillsInfo.module.scss | 34 ++++---- .../skills/MemberSkillsInfo.tsx | 83 ++++++++++--------- .../ProfileSkillsMatch.tsx | 2 +- .../skill-pill/SkillPill.module.scss | 1 + .../CollapsibleSkillsList.module.scss | 9 +- .../CollapsibleSkillsList.tsx | 10 ++- .../GroupedSkillsUI.module.scss | 5 ++ .../grouped-skills-ui/GroupedSkillsUI.tsx | 47 +++++++++++ .../lib/components/grouped-skills-ui/index.ts | 1 + src/libs/ui/lib/components/index.ts | 1 + yarn.lock | 12 +++ 12 files changed, 150 insertions(+), 57 deletions(-) create mode 100644 src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss create mode 100644 src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx create mode 100644 src/libs/ui/lib/components/grouped-skills-ui/index.ts diff --git a/package.json b/package.json index 2ef92fbc4..32742bd9b 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "react-redux": "^8.0.4", "react-redux-toastr": "^7.6.10", "react-responsive": "^9.0.0-beta.5", + "react-responsive-masonry": "^2.1.7", "react-responsive-modal": "^6.2.0", "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", @@ -159,6 +160,7 @@ "@types/react-gtm-module": "^2.0.1", "@types/react-helmet": "^6.1.6", "@types/react-redux-toastr": "^7.6.2", + "@types/react-responsive-masonry": "^2.1.1", "@types/react-router-dom": "^5.3.3", "@types/redux-actions": "2.6.2", "@types/redux-logger": "^3.0.9", diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss index 9122b2814..32162ff66 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss @@ -3,7 +3,6 @@ .container { display: flex; flex-direction: column; - margin-bottom: $sp-6; .headerWrap { display: flex; @@ -22,7 +21,25 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: $sp-4; + margin-bottom: $sp-6; + + .skillActions { + display: flex; + align-items: center; + + @include ltemd { + flex-direction: column; + align-items: flex-end; + } + + > button:nth-child(2) { + margin-left: $sp-4; + + @include ltemd { + margin-left: 0; + } + } + } } .skillsWrap { @@ -30,18 +47,5 @@ flex-wrap: wrap; column-gap: $sp-1; row-gap: $sp-2; - - .skillsCategories { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: $sp-4; - flex: 1; - - @include ltemd { - grid-template-columns: 1fr; - gap: 0; - row-gap: $sp-4; - } - } } } diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index bca3b9e1e..c756e1bb6 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -3,8 +3,8 @@ import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' import { UserEMSISkill, UserProfile } from '~/libs/core' -import { HowSkillsWorkModal, isSkillVerified, Skill, SkillPill } from '~/libs/shared' -import { Button, CollapsibleSkillsList } from '~/libs/ui' +import { HowSkillsWorkModal, isSkillVerified } from '~/libs/shared' +import { Button, GroupedSkillsUI } from '~/libs/ui' import { AddButton, EditMemberPropertyBtn, EmptySection } from '../../components' import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config' @@ -47,6 +47,9 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp return grouped }, [memberEMSISkills]) + const [skillsCatsCollapsed, setSkillsCatsCollapsed]: [boolean, Dispatch>] + = useState(true) + const [isEditMode, setIsEditMode]: [boolean, Dispatch>] = useState(false) @@ -84,8 +87,19 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp setHowSkillsWorkVisible(false) } + function handleExpandAllClick(): void { + setSkillsCatsCollapsed(!skillsCatsCollapsed) + } + return (
+ { + skillsRenderer && memberEMSISkills.length > 0 && ( +
+ {skillsRenderer(memberEMSISkills)} +
+ ) + }

Skills

@@ -97,39 +111,32 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp ) }
-
- {skillsRenderer && memberEMSISkills.length > 0 && skillsRenderer(memberEMSISkills)} {!skillsRenderer && memberEMSISkills.length > 0 && ( -
- { - Object.keys(groupedSkillsByCategory) - .map((categoryName: string) => ( - - { - groupedSkillsByCategory[categoryName] - .map((skill: UserEMSISkill) => ( - - )) - } - - )) - } -
+ )} {!memberEMSISkills.length && ( = (props: MemberSkillsInfoProp )}
- {canEdit && !memberEMSISkills.length && ( - - )} + { + canEdit && !memberEMSISkills.length && ( + + ) + } { isEditMode && ( diff --git a/src/apps/talent-search/src/components/profile-skills-match/ProfileSkillsMatch.tsx b/src/apps/talent-search/src/components/profile-skills-match/ProfileSkillsMatch.tsx index c58bd3724..476ad0d2b 100644 --- a/src/apps/talent-search/src/components/profile-skills-match/ProfileSkillsMatch.tsx +++ b/src/apps/talent-search/src/components/profile-skills-match/ProfileSkillsMatch.tsx @@ -50,7 +50,7 @@ const ProfileSkillsMatch: FC = props => { <>
{selfSkillmatched.length} - {` matched self selected skill${selfSkillmatched.length > 1 ? 's' : ''}`} + {` matched self proclaimed skill${selfSkillmatched.length > 1 ? 's' : ''}`}
{selfSkillmatched.map(skill => ( diff --git a/src/libs/shared/lib/components/skill-pill/SkillPill.module.scss b/src/libs/shared/lib/components/skill-pill/SkillPill.module.scss index 735230791..9740c7b27 100644 --- a/src/libs/shared/lib/components/skill-pill/SkillPill.module.scss +++ b/src/libs/shared/lib/components/skill-pill/SkillPill.module.scss @@ -66,5 +66,6 @@ border: none; color: $black-100; padding: $sp-2 0; + align-items: flex-start; } } diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss index a42260371..b5bacf1c0 100644 --- a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss +++ b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss @@ -5,6 +5,7 @@ flex-direction: column; background-color: $tc-white; border-radius: 8px; + margin-bottom: $sp-4; &.collapsed { .title { @@ -23,7 +24,7 @@ .header { display: flex; justify-content: flex-start; - align-items: center; + align-items: flex-start; cursor: pointer; .title { @@ -54,10 +55,14 @@ } .content { - transition: all 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; max-height: auto; opacity: 1; padding-left: $sp-8; margin-top: $sp-1; + + @include ltemd { + padding-left: $sp-4; + } } } \ No newline at end of file diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx index 75350f8f2..0ad691a75 100644 --- a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx +++ b/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx @@ -1,4 +1,4 @@ -import { Dispatch, FC, ReactNode, SetStateAction, useState } from 'react' +import { Dispatch, FC, ReactNode, SetStateAction, useEffect, useState } from 'react' import classNames from 'classnames' import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline' @@ -13,10 +13,16 @@ interface CollapsibleSkillsListProps { containerClass?: string headerClass?: string contentClass?: string + isCollapsed: boolean } const CollapsibleSkillsList: FC = (props: CollapsibleSkillsListProps) => { - const [isCollapsed, setIsCollapsed]: [boolean, Dispatch>] = useState(true) + const [isCollapsed, setIsCollapsed]: [boolean, Dispatch>] + = useState(props.isCollapsed) + + useEffect(() => { + setIsCollapsed(props.isCollapsed) + }, [props.isCollapsed]) function toggleCollapse(): void { setIsCollapsed(!isCollapsed) diff --git a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss new file mode 100644 index 000000000..ccf913e1b --- /dev/null +++ b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss @@ -0,0 +1,5 @@ +@import '@libs/ui/styles/includes'; + +.skillsCategories { + flex: 1; +} \ No newline at end of file diff --git a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx new file mode 100644 index 000000000..2ebabf02f --- /dev/null +++ b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx @@ -0,0 +1,47 @@ +import { FC } from 'react' +import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry' + +import { UserEMSISkill } from '~/libs/core' +import { Skill, SkillPill } from '~/libs/shared' + +import { CollapsibleSkillsList } from '../collapsible-skills-list' + +import styles from './GroupedSkillsUI.module.scss' + +interface GroupedSkillsUIProps { + groupedSkillsByCategory: { [key: string]: UserEMSISkill[] } + skillsCatsCollapsed: boolean +} +const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) => ( + + + { + Object.keys(props.groupedSkillsByCategory) + .map((categoryName: string) => ( + + + { + props.groupedSkillsByCategory[categoryName] + .map((skill: UserEMSISkill) => ( + + )) + } + + )) + } + + +) + +export default GroupedSkillsUI diff --git a/src/libs/ui/lib/components/grouped-skills-ui/index.ts b/src/libs/ui/lib/components/grouped-skills-ui/index.ts new file mode 100644 index 000000000..700ccb085 --- /dev/null +++ b/src/libs/ui/lib/components/grouped-skills-ui/index.ts @@ -0,0 +1 @@ +export { default as GroupedSkillsUI } from './GroupedSkillsUI' diff --git a/src/libs/ui/lib/components/index.ts b/src/libs/ui/lib/components/index.ts index b2a0bbb5d..72b7cb2c6 100644 --- a/src/libs/ui/lib/components/index.ts +++ b/src/libs/ui/lib/components/index.ts @@ -18,3 +18,4 @@ export * from './button' export * from './collapsible' export * from './verified-member-badge' export * from './collapsible-skills-list' +export * from './grouped-skills-ui' diff --git a/yarn.lock b/yarn.lock index 8954e2c9d..6a6a6f881 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5402,6 +5402,13 @@ "@types/react" "*" redux "^3.6.0 || ^4.0.0" +"@types/react-responsive-masonry@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@types/react-responsive-masonry/-/react-responsive-masonry-2.1.1.tgz#694fc86964f37b991c3b85ac99a253a04ecb8f6b" + integrity sha512-sFzNsxYugWO8G4d3ObhpcJCiqiYthWp9Udr9phDzy5BYxW78uMF8yK2IJ8+7bQLbmQz2xaIey1ZogbW3ATIo+A== + dependencies: + "@types/react" "*" + "@types/react-router-dom@^5.3.3": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" @@ -16328,6 +16335,11 @@ react-refresh@^0.11.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== +react-responsive-masonry@^2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/react-responsive-masonry/-/react-responsive-masonry-2.1.7.tgz#9b4a8d63b296a6265bea720c9d7da89754548346" + integrity sha512-/jOqnTVNtO8zRJMTl6ZXBex7EFYEIFBLVlkIFjiCT7omfm0CgNF2z4ST8RIr0v2ut15NWAQs7Q3kJJPhMoe3Ew== + react-responsive-modal@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/react-responsive-modal/-/react-responsive-modal-6.2.0.tgz#339226b911d8ffaba4e0afce83387a65221b8e29" From f58720574dc5eccefcf756d630744a0143fc36e7 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Thu, 12 Oct 2023 16:25:32 +0300 Subject: [PATCH 06/32] TSJR-111 clean up talent-search view --- .../member-profile/skills/MemberSkillsInfo.tsx | 3 ++- .../ProfileSkillsMatch.module.scss | 5 +++++ .../ProfileSkillsMatch.tsx | 18 +----------------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index c756e1bb6..e07414ab3 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -100,6 +100,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp
) } +

Skills

@@ -132,7 +133,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp
- {!skillsRenderer && memberEMSISkills.length > 0 && ( + {memberEMSISkills.length > 0 && ( = props => { const isMatchingSkill = useIsMatchingSkill(props.queriedSkills) const matchedSkills = (props.profileSkills as unknown as EmsiSkill[]).filter(isMatchingSkill) - const unMatchedSkills = (props.profileSkills as unknown as EmsiSkill[]).filter(s => !isMatchingSkill(s)) const provenMatched = matchedSkills.filter(isSkillVerified) const selfSkillmatched = matchedSkills.filter(s => !isSkillVerified(s)) const missingSkills = props.queriedSkills.filter(qs => !matchedSkills.find(ms => ms.skillId === qs.emsiId)) @@ -73,21 +72,6 @@ const ProfileSkillsMatch: FC = props => { )}
- {unMatchedSkills.length > 0 && ( -
-
- Additional Skills -
- -
- - {unMatchedSkills.map(skill => ( - - ))} - -
-
- )}
) } From bba03bcf0cc80609544b019c51876773e8b4c17e Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Thu, 12 Oct 2023 23:14:57 +0300 Subject: [PATCH 07/32] update circleci --- .circleci/config.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a74a8ad7..6a8a8d974 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -234,7 +234,6 @@ workflows: ignore: - master - qa - - profiles-app - build-qa: context: org-global @@ -242,7 +241,6 @@ workflows: branches: only: - qa - - profiles-app - build-prod: context: org-global @@ -261,7 +259,7 @@ workflows: - dev - justin_fixes - talent_search_fixes - - PROD-4398_integrate-userflow-remove-sprig + - feature/standardized-skills - deployQa: context: org-global From 2e23333260a7ded0a0e38e37b908adc98042d57f Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 16 Oct 2023 10:54:36 +0300 Subject: [PATCH 08/32] TSJR-111 add new skills model & clean uplegacy --- .../core/lib/profile/data-providers/index.ts | 1 - .../profile/data-providers/useMemberSkills.ts | 18 ---------- .../core/lib/profile/user-profile.model.ts | 4 ++- src/libs/core/lib/profile/user-skill.model.ts | 35 +++++++++++++------ 4 files changed, 28 insertions(+), 30 deletions(-) delete mode 100644 src/libs/core/lib/profile/data-providers/useMemberSkills.ts diff --git a/src/libs/core/lib/profile/data-providers/index.ts b/src/libs/core/lib/profile/data-providers/index.ts index 01b1aa71a..57c56fcfa 100644 --- a/src/libs/core/lib/profile/data-providers/index.ts +++ b/src/libs/core/lib/profile/data-providers/index.ts @@ -1,5 +1,4 @@ export * from './useCountry' -export * from './useMemberSkills' export * from './useMemberStats' export * from './useMemberBadges' export * from './useUserCompletedCertifications' diff --git a/src/libs/core/lib/profile/data-providers/useMemberSkills.ts b/src/libs/core/lib/profile/data-providers/useMemberSkills.ts deleted file mode 100644 index 717978ac6..000000000 --- a/src/libs/core/lib/profile/data-providers/useMemberSkills.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { keys } from 'lodash' -import useSWR, { SWRResponse } from 'swr' - -import { UserSkill } from '../user-skill.model' -import { getProfileUrl } from '../profile-functions' - -// This is currently providing legacy TC skills, not EMSI! -export function useMemberSkills(handle?: string): UserSkill[] | undefined { - const { data }: SWRResponse = useSWR(handle ? `${getProfileUrl(handle)}/skills` : undefined) - - const skills: UserSkill[] | undefined - = data?.skills ? keys(data.skills) - .map(skillKey => ({ id: skillKey, ...data.skills[skillKey] })) - // sort by challenge verified first - .sort((a, b) => b.sources.indexOf('CHALLENGE') - a.sources.indexOf('CHALLENGE')) : undefined - - return skills -} diff --git a/src/libs/core/lib/profile/user-profile.model.ts b/src/libs/core/lib/profile/user-profile.model.ts index 63db0e186..0d798d0e7 100644 --- a/src/libs/core/lib/profile/user-profile.model.ts +++ b/src/libs/core/lib/profile/user-profile.model.ts @@ -1,4 +1,4 @@ -import { UserEMSISkill } from './user-skill.model' +import { UserEMSISkill, UserSkill } from './user-skill.model' export type TC_TRACKS = 'DEVELOP' | 'DESIGN' | 'DATA_SCIENCE' @@ -15,6 +15,7 @@ export interface UserProfile { description: string diceEnabled: boolean email: string + // TODO: clean up the type when transition to TC skills is done emsiSkills: Array firstName: string handle: string @@ -29,6 +30,7 @@ export interface UserProfile { } photoURL?: string roles: Array + skills: Array status: string tracks?: Array updatedAt: number diff --git a/src/libs/core/lib/profile/user-skill.model.ts b/src/libs/core/lib/profile/user-skill.model.ts index 2ad685542..0e84c956b 100644 --- a/src/libs/core/lib/profile/user-skill.model.ts +++ b/src/libs/core/lib/profile/user-skill.model.ts @@ -1,13 +1,3 @@ -export type skillSources = 'USER_ENTERED' | 'CHALLENGE' - -export type UserSkill = { - id: number - hidden: boolean - score: number - sources: skillSources[] - tagName: string -} - export type EMSISkillSources = 'TCACertified' | 'SelfPicked' | 'ChallengeWin' export type UserEMSISkill = { @@ -24,3 +14,28 @@ export type UserEMSISkill = { id: number } } + +export type UserSkillCategory = { + id: number + name: string +} + +// keep this in sync with the backend +// https://github.com/topcoder-platform/standardized-skills-api/blob/develop/src/config/constants.ts#L23 +export enum UserSkillLevelTypes { + selfDeclared = 'self-declared', + verified = 'verified', +} + +export type UserSkillLevel = { + id: number + name: UserSkillLevelTypes + description: string +} + +export type UserSkill = { + id: string + name: string + category: UserSkillCategory + levels: Array +} From 71d7676e2cdb66c2de97d176b81a4bcca0c6d369 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 16 Oct 2023 11:06:56 +0300 Subject: [PATCH 09/32] TSJR-111 clen up EMSIskill definitions --- .../member-profile/MemberProfile.context.tsx | 4 +-- .../skills/MemberSkillsInfo.tsx | 36 +++++++++---------- .../ProfileSkillsMatch.tsx | 4 +-- .../src/routes/talent-page/TalentPage.tsx | 4 +-- .../profile-functions/rating.functions.ts | 6 ---- .../core/lib/profile/user-profile.model.ts | 4 +-- src/libs/core/lib/profile/user-skill.model.ts | 17 --------- .../grouped-skills-ui/GroupedSkillsUI.tsx | 6 ++-- 8 files changed, 28 insertions(+), 53 deletions(-) diff --git a/src/apps/profiles/src/member-profile/MemberProfile.context.tsx b/src/apps/profiles/src/member-profile/MemberProfile.context.tsx index 052f3562b..19bcd1325 100644 --- a/src/apps/profiles/src/member-profile/MemberProfile.context.tsx +++ b/src/apps/profiles/src/member-profile/MemberProfile.context.tsx @@ -1,11 +1,11 @@ import { createContext, FC, ReactNode, useContext, useMemo } from 'react' -import { UserEMSISkill } from '~/libs/core' +import { UserSkill } from '~/libs/core' export interface MemberProfileContextValue { isTalentSearch?: boolean skillsRenderer?: ( - skills: Pick[] + skills: Pick[] ) => ReactNode } diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index e07414ab3..d2b42b99c 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -2,7 +2,7 @@ import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from 'reac import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' -import { UserEMSISkill, UserProfile } from '~/libs/core' +import { UserProfile, UserSkill } from '~/libs/core' import { HowSkillsWorkModal, isSkillVerified } from '~/libs/shared' import { Button, GroupedSkillsUI } from '~/libs/ui' @@ -27,25 +27,25 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp const { skillsRenderer, isTalentSearch }: MemberProfileContextValue = useMemberProfileContext() - const memberEMSISkills: UserEMSISkill[] = useMemo(() => orderBy( - props.profile.emsiSkills ?? [], + const memberSkills: UserSkill[] = useMemo(() => orderBy( + props.profile.skills ?? [], [isSkillVerified, 'name'], ['desc', 'asc'], - ) as UserEMSISkill[], [props.profile.emsiSkills]) + ) as UserSkill[], [props.profile.skills]) - const groupedSkillsByCategory: { [key: string]: UserEMSISkill[] } = useMemo(() => { - const grouped: { [key: string]: UserEMSISkill[] } = {} + const groupedSkillsByCategory: { [key: string]: UserSkill[] } = useMemo(() => { + const grouped: { [key: string]: UserSkill[] } = {} - memberEMSISkills.forEach((skill: UserEMSISkill) => { - if (grouped[skill.skillCategory.name]) { - grouped[skill.skillCategory.name].push(skill) + memberSkills.forEach((skill: UserSkill) => { + if (grouped[skill.category.name]) { + grouped[skill.category.name].push(skill) } else { - grouped[skill.skillCategory.name] = [skill] + grouped[skill.category.name] = [skill] } }) return grouped - }, [memberEMSISkills]) + }, [memberSkills]) const [skillsCatsCollapsed, setSkillsCatsCollapsed]: [boolean, Dispatch>] = useState(true) @@ -94,9 +94,9 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp return (
{ - skillsRenderer && memberEMSISkills.length > 0 && ( + skillsRenderer && memberSkills.length > 0 && (
- {skillsRenderer(memberEMSISkills)} + {skillsRenderer(memberSkills)}
) } @@ -105,7 +105,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp

Skills

{ - canEdit && memberEMSISkills.length > 0 && ( + canEdit && memberSkills.length > 0 && ( @@ -120,7 +120,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp variant='linkblue' /> { - memberEMSISkills.length > 0 && ( + memberSkills.length > 0 && (
- {memberEMSISkills.length > 0 && ( + {memberSkills.length > 0 && ( )} - {!memberEMSISkills.length && ( + {!memberSkills.length && ( = (props: MemberSkillsInfoProp )}
{ - canEdit && !memberEMSISkills.length && ( + canEdit && !memberSkills.length && ( [] + profileSkills: Pick[] queriedSkills: Skill[] } diff --git a/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx b/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx index b077a0bfe..d93dae09f 100644 --- a/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx +++ b/src/apps/talent-search/src/routes/talent-page/TalentPage.tsx @@ -2,14 +2,14 @@ import { FC, ReactNode } from 'react' import { Location, useLocation } from 'react-router-dom' import { MemberProfileContext, MemberProfilePage } from '@profiles/member-profile' -import { UserEMSISkill } from '~/libs/core' +import { UserSkill } from '~/libs/core' import { ProfileSkillsMatch } from '../../components/profile-skills-match' const TalentPage: FC = () => { const { state }: Location = useLocation() - function skillsRenderer(profileSkills: Pick[]): ReactNode { + function skillsRenderer(profileSkills: Pick[]): ReactNode { return ( = [{ color: '#555555' /* Grey */, limit: 900, @@ -32,7 +30,3 @@ export function ratingToCSScolor(rating: number): CSSProperties { color, } } - -export function isVerifiedSkill(skillOriginSources: EMSISkillSources[]): boolean { - return skillOriginSources.includes('TCACertified') || skillOriginSources.includes('ChallengeWin') -} diff --git a/src/libs/core/lib/profile/user-profile.model.ts b/src/libs/core/lib/profile/user-profile.model.ts index 0d798d0e7..7b22bca31 100644 --- a/src/libs/core/lib/profile/user-profile.model.ts +++ b/src/libs/core/lib/profile/user-profile.model.ts @@ -1,4 +1,4 @@ -import { UserEMSISkill, UserSkill } from './user-skill.model' +import { UserSkill } from './user-skill.model' export type TC_TRACKS = 'DEVELOP' | 'DESIGN' | 'DATA_SCIENCE' @@ -15,8 +15,6 @@ export interface UserProfile { description: string diceEnabled: boolean email: string - // TODO: clean up the type when transition to TC skills is done - emsiSkills: Array firstName: string handle: string handleLower: string diff --git a/src/libs/core/lib/profile/user-skill.model.ts b/src/libs/core/lib/profile/user-skill.model.ts index 0e84c956b..53419f584 100644 --- a/src/libs/core/lib/profile/user-skill.model.ts +++ b/src/libs/core/lib/profile/user-skill.model.ts @@ -1,20 +1,3 @@ -export type EMSISkillSources = 'TCACertified' | 'SelfPicked' | 'ChallengeWin' - -export type UserEMSISkill = { - id: string - name: string - skillCategory: { - name: string - id: number - } - skillId: string - skillSources: Array - skillSubcategory: { - name: string - id: number - } -} - export type UserSkillCategory = { id: number name: string diff --git a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx index 2ebabf02f..eb5314a46 100644 --- a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx +++ b/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx @@ -1,7 +1,7 @@ import { FC } from 'react' import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry' -import { UserEMSISkill } from '~/libs/core' +import { UserSkill } from '~/libs/core' import { Skill, SkillPill } from '~/libs/shared' import { CollapsibleSkillsList } from '../collapsible-skills-list' @@ -9,7 +9,7 @@ import { CollapsibleSkillsList } from '../collapsible-skills-list' import styles from './GroupedSkillsUI.module.scss' interface GroupedSkillsUIProps { - groupedSkillsByCategory: { [key: string]: UserEMSISkill[] } + groupedSkillsByCategory: { [key: string]: UserSkill[] } skillsCatsCollapsed: boolean } const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) => ( @@ -29,7 +29,7 @@ const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) > { props.groupedSkillsByCategory[categoryName] - .map((skill: UserEMSISkill) => ( + .map((skill: UserSkill) => ( Date: Mon, 16 Oct 2023 12:52:48 +0300 Subject: [PATCH 10/32] TSJR-111 move skill components to shared --- .../profiles/src/member-profile/skills/MemberSkillsInfo.tsx | 4 ++-- .../collapsible-skills-list/CollapsibleSkillsList.module.scss | 0 .../collapsible-skills-list/CollapsibleSkillsList.tsx | 3 +-- .../lib/components/collapsible-skills-list/index.ts | 0 .../components/grouped-skills-ui/GroupedSkillsUI.module.scss | 0 .../lib/components/grouped-skills-ui/GroupedSkillsUI.tsx | 0 .../{ui => shared}/lib/components/grouped-skills-ui/index.ts | 0 src/libs/shared/lib/components/index.ts | 2 ++ src/libs/ui/lib/components/index.ts | 2 -- 9 files changed, 5 insertions(+), 6 deletions(-) rename src/libs/{ui => shared}/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss (100%) rename src/libs/{ui => shared}/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx (97%) rename src/libs/{ui => shared}/lib/components/collapsible-skills-list/index.ts (100%) rename src/libs/{ui => shared}/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss (100%) rename src/libs/{ui => shared}/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx (100%) rename src/libs/{ui => shared}/lib/components/grouped-skills-ui/index.ts (100%) diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index d2b42b99c..10bd07516 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -3,8 +3,8 @@ import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' import { UserProfile, UserSkill } from '~/libs/core' -import { HowSkillsWorkModal, isSkillVerified } from '~/libs/shared' -import { Button, GroupedSkillsUI } from '~/libs/ui' +import { GroupedSkillsUI, HowSkillsWorkModal, isSkillVerified } from '~/libs/shared' +import { Button } from '~/libs/ui' import { AddButton, EditMemberPropertyBtn, EmptySection } from '../../components' import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config' diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss similarity index 100% rename from src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss rename to src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss diff --git a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx similarity index 97% rename from src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx rename to src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx index 0ad691a75..e51149905 100644 --- a/src/libs/ui/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx +++ b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx @@ -2,8 +2,7 @@ import { Dispatch, FC, ReactNode, SetStateAction, useEffect, useState } from 're import classNames from 'classnames' import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline' - -import { Button } from '../button' +import { Button } from '~/libs/ui' import styles from './CollapsibleSkillsList.module.scss' diff --git a/src/libs/ui/lib/components/collapsible-skills-list/index.ts b/src/libs/shared/lib/components/collapsible-skills-list/index.ts similarity index 100% rename from src/libs/ui/lib/components/collapsible-skills-list/index.ts rename to src/libs/shared/lib/components/collapsible-skills-list/index.ts diff --git a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss similarity index 100% rename from src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss rename to src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.module.scss diff --git a/src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx similarity index 100% rename from src/libs/ui/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx rename to src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx diff --git a/src/libs/ui/lib/components/grouped-skills-ui/index.ts b/src/libs/shared/lib/components/grouped-skills-ui/index.ts similarity index 100% rename from src/libs/ui/lib/components/grouped-skills-ui/index.ts rename to src/libs/shared/lib/components/grouped-skills-ui/index.ts diff --git a/src/libs/shared/lib/components/index.ts b/src/libs/shared/lib/components/index.ts index 82cde8c0f..016d36443 100644 --- a/src/libs/shared/lib/components/index.ts +++ b/src/libs/shared/lib/components/index.ts @@ -5,3 +5,5 @@ export * from './input-skill-selector' export * from './member-skill-editor' export * from './skill-pill' export * from './expandable-list' +export * from './grouped-skills-ui' +export * from './collapsible-skills-list' diff --git a/src/libs/ui/lib/components/index.ts b/src/libs/ui/lib/components/index.ts index 72b7cb2c6..306c469d6 100644 --- a/src/libs/ui/lib/components/index.ts +++ b/src/libs/ui/lib/components/index.ts @@ -17,5 +17,3 @@ export * from './tooltip' export * from './button' export * from './collapsible' export * from './verified-member-badge' -export * from './collapsible-skills-list' -export * from './grouped-skills-ui' From 040ce2b7f2133e108c8d26843fc5cebb19900279 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 16 Oct 2023 13:59:31 +0300 Subject: [PATCH 11/32] Resolve merge conflicts 2 --- src/apps/onboarding/src/models/MemberInfo.ts | 5 ++--- .../src/components/talent-card/TalentCard.tsx | 9 +++++---- src/apps/talent-search/src/lib/models/Member.ts | 6 +++--- .../src/lib/services/use-fetch-talent-matches.ts | 7 +++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/apps/onboarding/src/models/MemberInfo.ts b/src/apps/onboarding/src/models/MemberInfo.ts index 41e301d5e..34181f86b 100644 --- a/src/apps/onboarding/src/models/MemberInfo.ts +++ b/src/apps/onboarding/src/models/MemberInfo.ts @@ -1,6 +1,5 @@ import { MemberMaxRating } from '~/apps/talent-search/src/lib/models' -import { MemberStats } from '~/libs/core' -import { Skill } from '~/libs/shared' +import { MemberStats, UserSkill } from '~/libs/core' import MemberAddress from './MemberAddress' @@ -14,7 +13,7 @@ export default interface MemberInfo { email: string accountAge: number maxRating: MemberMaxRating - emsiSkills: Array + skills: Array stats: Array addresses?: MemberAddress[] country: string diff --git a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx index 0ff6a0fee..bf0df7e12 100644 --- a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx +++ b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx @@ -5,7 +5,8 @@ import classNames from 'classnames' import codes from 'country-calling-code' import { IconSolid } from '~/libs/ui' -import { isSkillVerified, ProfilePicture, Skill, SkillPill } from '~/libs/shared' +import { isSkillVerified, ProfilePicture, SkillPill } from '~/libs/shared' +import { UserSkill } from '~/libs/core' import { ProfileMatch } from '../profile-match' import { Member, MemberDisplayName } from '../../lib/models' @@ -30,7 +31,7 @@ function isOverflow(el: HTMLElement): boolean { } interface TalentCardProps { - queriedSkills: Skill[] + queriedSkills: UserSkill[] member: Member match?: number } @@ -44,12 +45,12 @@ const TalentCard: FC = props => { const matchedSkills = useMemo(() => ( orderBy( - props.member.emsiSkills, + props.member.skills, [isSkillVerified, a => a.name], ['desc', 'asc'], ) .filter(isMatchingSkill) - ), [isMatchingSkill, props.member.emsiSkills]) + ), [isMatchingSkill, props.member.skills]) const matchState = useMemo(() => ({ matchValue: props.match, diff --git a/src/apps/talent-search/src/lib/models/Member.ts b/src/apps/talent-search/src/lib/models/Member.ts index 5798a4da3..f1aab22d8 100644 --- a/src/apps/talent-search/src/lib/models/Member.ts +++ b/src/apps/talent-search/src/lib/models/Member.ts @@ -1,4 +1,4 @@ -import { Skill } from '~/libs/shared' +import { UserSkill } from '~/libs/core' import { MemberDisplayName } from './MemberDisplayName' import MemberAddress from './MemberAddress' @@ -13,7 +13,7 @@ export default interface Member { createdAt: number; description: string; email: string; - emsiSkills: Array ; + skills: Array; firstName: string; handle: string; homeCountryCode: string; @@ -24,7 +24,7 @@ export default interface Member { numberOfChallengesWon: number; photoURL: string; skillScore: number; - stats: Array ; + stats: Array; status: string; userId: number; verified: string; diff --git a/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts b/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts index 4d6f4fe13..348505f4e 100644 --- a/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts +++ b/src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts @@ -3,8 +3,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import useSWR, { SWRResponse } from 'swr' import { EnvironmentConfig } from '~/config' -import { PaginatedResponse, xhrGetPaginatedAsync } from '~/libs/core' -import { Skill } from '~/libs/shared' +import { PaginatedResponse, UserSkill, xhrGetPaginatedAsync } from '~/libs/core' import Member from '@talentSearch/lib/models/Member' export interface TalentMatchesResponse { @@ -18,7 +17,7 @@ export interface TalentMatchesResponse { } export function useFetchTalentMatches( - skills: ReadonlyArray, + skills: ReadonlyArray, page: number, pageSize: number, ): TalentMatchesResponse { @@ -61,7 +60,7 @@ export interface InfiniteTalentMatchesResposne { } export function useInfiniteTalentMatches( - skills: ReadonlyArray, + skills: ReadonlyArray, pageSize: number = 10, ): InfiniteTalentMatchesResposne { const [matches, setMatches] = useState([] as Member[]) From 4226cca22713d377bf8e2774e8eb2bc6f4ae1ba6 Mon Sep 17 00:00:00 2001 From: eisbilir Date: Mon, 16 Oct 2023 14:29:53 +0300 Subject: [PATCH 12/32] feat: update dice connection api --- package.json | 4 ++ .../ConnectionHandler.module.scss | 5 ++ .../ConnectionHandler/index.tsx | 51 +++++++++++++++++++ .../dice-setup-modal/DiceSetupModal.tsx | 51 +++---------------- .../data-providers/useDiceIdConnection.ts | 16 ++---- 5 files changed, 73 insertions(+), 54 deletions(-) create mode 100644 src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss create mode 100644 src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx diff --git a/package.json b/package.json index 2ef92fbc4..584a7f6a9 100644 --- a/package.json +++ b/package.json @@ -246,5 +246,9 @@ } } ] + }, + "volta": { + "node": "16.15.0", + "yarn": "1.22.19" } } diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss new file mode 100644 index 000000000..6b696efa6 --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss @@ -0,0 +1,5 @@ +@import '@libs/ui/styles/includes'; + +.qrCode { + margin: auto; +} \ No newline at end of file diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx new file mode 100644 index 000000000..f56ca93fd --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx @@ -0,0 +1,51 @@ +import { FC, useEffect } from 'react' +import { QRCodeSVG } from 'qrcode.react' + +import { DiceConnectionStatus, useDiceIdConnection } from '~/libs/core' + +import styles from './ConnectionHandler.module.scss' + +interface ConnectionHandlerProps { + onComplete: () => void; + userId: number; +} + +export const ConnectionHandler: FC = ( + props: ConnectionHandlerProps, +) => { + const diceConnection: DiceConnectionStatus | undefined = useDiceIdConnection(props.userId) + + useEffect(() => { + if (diceConnection && diceConnection.accepted) { + props.onComplete() + } + }, [diceConnection, props]) + + return ( + <> +

+ Scan the following DICE ID QR Code in your DICE ID + mobile application. +

+ {diceConnection && diceConnection.connection ? ( + + ) : ( +

Loading...

+ )} +

+ Once the connection is established, the service will + offer you a Verifiable Credential. +
+ Press the ACCEPT button in your DICE ID App. +
+ If you DECLINE the invitation, please try again after 5 + minutes. +

+ + ) +} diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx index 6f3d6a2e9..a26925a2d 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx @@ -1,4 +1,4 @@ -import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' +import { Dispatch, FC, SetStateAction, useState } from 'react' import { QRCodeSVG } from 'qrcode.react' import { get, isUndefined, lowerCase } from 'lodash' import { toast } from 'react-toastify' @@ -12,9 +12,10 @@ import { googlePlay, UnSuccessfullDiceVerificationIcon, } from '~/apps/accounts/src/lib' -import { DiceConnectionStatus, updateMemberMFAStatusAsync, useDiceIdConnection, UserProfile } from '~/libs/core' +import { updateMemberMFAStatusAsync, UserProfile } from '~/libs/core' import { EnvironmentConfig } from '~/config' +import { ConnectionHandler } from './ConnectionHandler' import { VerificationListener } from './VerificationListener' import styles from './DiceSetupModal.module.scss' @@ -29,25 +30,9 @@ interface DiceSetupModalProps { const DiceSetupModal: FC = (props: DiceSetupModalProps) => { const [step, setStep]: [number, Dispatch>] = useState(1) - const [diceConnectionId, setDiceConnectionId]: [ - number | undefined, - Dispatch> - ] = useState() - - const diceConnection: DiceConnectionStatus | undefined = useDiceIdConnection(props.profile.userId, diceConnectionId) - const [isVerificationProcessing, setIsVerificationProcessing]: [boolean, Dispatch>] = useState(false) - useEffect(() => { - if (diceConnection && !diceConnectionId) { - setDiceConnectionId(diceConnection.id) - } - }, [ - diceConnection, - diceConnectionId, - ]) - function handleSecondaryButtonClick(): void { switch (step) { case 2: return setStep(step - 1) @@ -117,12 +102,11 @@ const DiceSetupModal: FC = (props: DiceSetupModalProps) => onClick={handleSecondaryButtonClick} /> { - step !== 3 && ( + step !== 2 && step !== 3 && (
From 1410318687e003fecc5836e3a1ece0811d895e30 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Tue, 17 Oct 2023 11:21:11 +0300 Subject: [PATCH 14/32] TSJR-14 - update api endpoints for skills --- .../standard-skills/standard-skills.service.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts index f0acd5ea6..616b13cc2 100644 --- a/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts +++ b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts @@ -1,7 +1,7 @@ import { EnvironmentConfig } from '~/config' import { UserSkill, xhrGetAsync, xhrPostAsync, xhrPutAsync } from '~/libs/core' -const baseUrl = `${EnvironmentConfig.API.V5}/emsi-skills/member-emsi-skills` +const baseUrl = `${EnvironmentConfig.API.V5}/standardized-skills` export async function autoCompleteSkills(queryTerm: string): Promise { if (!queryTerm) { @@ -9,7 +9,7 @@ export async function autoCompleteSkills(queryTerm: string): Promise { - const url = `${baseUrl}/${userId}?pageFlag=${!config.skipPagination}` + const url = `${baseUrl}/user-skills/${userId}?disablePagination=${config.skipPagination}` return xhrGetAsync(url) } export async function createMemberSkills(userId: number, skills: UserSkill[]): Promise { - return xhrPostAsync(baseUrl, { + return xhrPostAsync(`${baseUrl}/user-skills/${userId}`, { skills, - userId, }) } export async function updateMemberSkills(userId: string | number, skills: UserSkill[]): Promise { - return xhrPutAsync(`${baseUrl}/${userId}`, { + return xhrPutAsync(`${baseUrl}/user-skills/${userId}`, { skills, }) } From 3baa835863d1793f4454fcc2d43e06a6adf84b7e Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 17 Oct 2023 20:33:16 +1100 Subject: [PATCH 15/32] Fix popular skill IDs for new database --- .../popular-skills/PopularSkills.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx index f76593ecf..0e3d47b11 100644 --- a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx +++ b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx @@ -16,7 +16,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'f81d2a78-ff52-4c77-8cdb-8863601b87c7', + id: '63bb7cfc-b0d4-4584-820a-18c503b4b0fe', levels: [], name: 'Java (Programming Language)', }, @@ -25,7 +25,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '1aabc882-c28d-4b56-8546-5e961b53bf5d', + id: '0d86f8cb-e509-4ca8-b9f8-e65d909cc6eb', levels: [], name: 'MySQL', }, @@ -34,7 +34,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'b3181231-af8f-4a44-aff2-97fe00c57d76', + id: '1bad43a3-ee9c-4be2-9f82-b09fab18b36c', levels: [], name: 'Node.js', }, @@ -43,7 +43,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '4328c534-ba51-4589-a3e7-7b5ba76d2b55', + id: '9c42c728-47ff-4b20-916c-560739bad1ee', levels: [], name: 'Cascading Style Sheets (CSS)', }, @@ -52,7 +52,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'e3b2b1f1-6bbf-4989-b53d-d8531a10ea5d', + id: '16ee1403-8e73-497d-a766-623eefd3c806', levels: [], name: 'JavaScript (Programming Language)', }, @@ -61,7 +61,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '41ffc4d5-2e43-45e1-af36-ae7a23b47c21', + id: '99e5fc45-5fc0-4794-a578-f42dfabcbf74', levels: [], name: 'Machine Learning', }, @@ -70,7 +70,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '047203fc-8c85-4be0-be0b-0e2fe11c3a16', + id: 'a0da6acf-2cf8-48f0-ba4a-30d18bc75052', levels: [], name: 'Unit Testing', }, @@ -79,7 +79,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '8c6703bd-63dd-4f6d-9cf0-5b411e531a9f', + id: '7e8641e5-e5c1-4ab6-a8f4-1fd6a8686dbe', levels: [], name: 'Angular (Web Framework)', }, @@ -88,7 +88,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '34ec4bf0-0b44-4d04-9f11-e3daa2c045ce', + id: 'f0597e53-9a6d-40d6-8639-4d5a9ead190f', levels: [], name: '.NET Framework', }, @@ -97,7 +97,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'a9bb69aa-edc2-4d5f-8141-de33a139f119', + id: 'fcbac194-35ab-4a31-aa7c-a2867fff9c4b', levels: [], name: 'Python (Programming Language)', }, @@ -106,7 +106,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '67c623db-09e4-499d-800b-24868b1eb85b', + id: 'adf9d7b9-d639-4a73-8772-673b3d4f41b0', levels: [], name: 'Android (Operating System)', }, @@ -115,7 +115,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '36292f61-c359-42a4-89b9-95245ee494ea', + id: '130323ce-7d88-4141-9e2b-904994f026a1', levels: [], name: 'Figma (Design Software)', }, @@ -124,7 +124,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'cf39f07c-0e7a-48a2-acec-21834900c437', + id: '9eaf6049-402a-481c-ac82-87a0826128c7', levels: [], name: 'Microsoft Azure', }, @@ -133,7 +133,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'b33f8342-8015-4244-afea-5fd089bf52a6', + id: 'ced0b36c-6057-48e1-a263-2588fb91296b', levels: [], name: 'Adobe Illustrator', }, @@ -142,7 +142,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'f21aecd2-5c67-4783-97a4-a77c67cf4f67', + id: 'be85b096-b841-45b4-a5cb-1d3ee7ce1126', levels: [], name: 'Docker (Software)', }, @@ -151,7 +151,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '43baf79e-3632-4b04-889a-7202cbf62a6c', + id: 'ceef6c18-8786-4ade-9f3e-1f79453a588c', levels: [], name: 'React.js', }, From 1a8cb245bd55215a1aeb5eeeaa2521c61de3791b Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Tue, 17 Oct 2023 15:30:48 +0300 Subject: [PATCH 16/32] TSJR-14 - update calls to standardized skills api to send correct payload --- .../member-skill-editor/use-member-skill-editor.tsx | 8 +++++--- .../standard-skills/standard-skills.service.ts | 12 ++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx b/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx index 1f49c4e5f..87e2ceda2 100644 --- a/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx +++ b/src/libs/shared/lib/components/member-skill-editor/use-member-skill-editor.tsx @@ -1,5 +1,5 @@ import { ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react' -import { differenceWith } from 'lodash' +import { differenceWith, pick } from 'lodash' import { profileContext, ProfileContextData, UserSkill } from '~/libs/core' @@ -45,13 +45,15 @@ export const useMemberSkillEditor = ({ return } + const skillIds = skills.map(skill => pick(skill, 'id')) + if (!isInitialized) { - await createMemberSkills(profile.userId, skills) + await createMemberSkills(profile.userId, skillIds) setIsInitialized(true) return } - await updateMemberSkills(profile.userId, skills) + await updateMemberSkills(profile.userId, skillIds) }, [isInitialized, profile?.userId, skills]) // Handle user changes diff --git a/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts index 616b13cc2..1eb55874a 100644 --- a/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts +++ b/src/libs/shared/lib/services/standard-skills/standard-skills.service.ts @@ -3,6 +3,11 @@ import { UserSkill, xhrGetAsync, xhrPostAsync, xhrPutAsync } from '~/libs/core' const baseUrl = `${EnvironmentConfig.API.V5}/standardized-skills` +export interface UpdateUserSkillDTO { + id: string + levelId?: string +} + export async function autoCompleteSkills(queryTerm: string): Promise { if (!queryTerm) { return Promise.resolve([]) @@ -23,13 +28,16 @@ export async function fetchMemberSkills( return xhrGetAsync(url) } -export async function createMemberSkills(userId: number, skills: UserSkill[]): Promise { +export async function createMemberSkills(userId: number, skills: UpdateUserSkillDTO[]): Promise { return xhrPostAsync(`${baseUrl}/user-skills/${userId}`, { skills, }) } -export async function updateMemberSkills(userId: string | number, skills: UserSkill[]): Promise { +export async function updateMemberSkills( + userId: string | number, + skills: UpdateUserSkillDTO[], +): Promise { return xhrPutAsync(`${baseUrl}/user-skills/${userId}`, { skills, }) From 519ed3f4518c35eb5c6acfd502569a826887c8c1 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Wed, 18 Oct 2023 06:44:52 +1100 Subject: [PATCH 17/32] Update to use non-deleted IDs --- .../src/components/popular-skills/PopularSkills.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx index 0e3d47b11..3af231ba5 100644 --- a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx +++ b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx @@ -34,7 +34,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: '1bad43a3-ee9c-4be2-9f82-b09fab18b36c', + id: '32899253-5989-4c33-9948-cad29c9e0ab0', levels: [], name: 'Node.js', }, @@ -151,7 +151,7 @@ const popularSkills: UserSkill[] = [ id: '481b5ebc-2fe6-45ed-a90c-736936d458d7', name: 'Programming and Development', }, - id: 'ceef6c18-8786-4ade-9f3e-1f79453a588c', + id: '4458454c-9a97-4332-a545-6546e240dab6', levels: [], name: 'React.js', }, From 36b790ffa6758ec2367b897db41b881c14a4c2c0 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Wed, 18 Oct 2023 09:09:26 +1100 Subject: [PATCH 18/32] Fix names --- .../src/components/popular-skills/PopularSkills.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx index 3af231ba5..ec3320621 100644 --- a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx +++ b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx @@ -36,7 +36,7 @@ const popularSkills: UserSkill[] = [ }, id: '32899253-5989-4c33-9948-cad29c9e0ab0', levels: [], - name: 'Node.js', + name: 'Node.js (Javascript Library)', }, { category: { @@ -153,7 +153,7 @@ const popularSkills: UserSkill[] = [ }, id: '4458454c-9a97-4332-a545-6546e240dab6', levels: [], - name: 'React.js', + name: 'React.js (Javascript Library)', }, ] From bc11f31a99ef43e79e06d8c2caf2412b1ae4eccb Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 18 Oct 2023 19:24:43 +0300 Subject: [PATCH 19/32] TSJR-159rbetter mobile responsive --- .../shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx | 2 +- src/libs/shared/lib/components/skill-pill/SkillPill.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx index e9a6d87bf..8b1d5f069 100644 --- a/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx +++ b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx @@ -15,7 +15,7 @@ interface GroupedSkillsUIProps { const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) => ( { diff --git a/src/libs/shared/lib/components/skill-pill/SkillPill.tsx b/src/libs/shared/lib/components/skill-pill/SkillPill.tsx index 725b06373..2800850f9 100644 --- a/src/libs/shared/lib/components/skill-pill/SkillPill.tsx +++ b/src/libs/shared/lib/components/skill-pill/SkillPill.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames' import { IconOutline } from '~/libs/ui' import { UserSkill } from '~/libs/core' -import { isSkillVerified } from '../../services' +import { isSkillVerified } from '../../services/standard-skills' import styles from './SkillPill.module.scss' From 126d369a72501eb2a35a283af1bfca5fd42bc82c Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 18 Oct 2023 22:59:46 +0300 Subject: [PATCH 20/32] TSJR-158 better collapse skills UI --- .../skills/MemberSkillsInfo.tsx | 11 ++ .../CollapsibleSkillsList.tsx | 6 +- .../grouped-skills-ui/GroupedSkillsUI.tsx | 100 ++++++++++++------ 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index 10bd07516..618ac252c 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -91,6 +91,16 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp setSkillsCatsCollapsed(!skillsCatsCollapsed) } + function toggleCollapseUIButton(collapsed: boolean): void { + if (collapsed === false && !!skillsCatsCollapsed) { + setSkillsCatsCollapsed(false) + } + + if (collapsed === true && skillsCatsCollapsed === false) { + setSkillsCatsCollapsed(true) + } + } + return (
{ @@ -137,6 +147,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp )} {!memberSkills.length && ( diff --git a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx index e51149905..7a4de9f40 100644 --- a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx +++ b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx @@ -13,6 +13,7 @@ interface CollapsibleSkillsListProps { headerClass?: string contentClass?: string isCollapsed: boolean + onDisplayChnage?: (isCollapsed: boolean) => void } const CollapsibleSkillsList: FC = (props: CollapsibleSkillsListProps) => { @@ -24,7 +25,10 @@ const CollapsibleSkillsList: FC = (props: Collapsibl }, [props.isCollapsed]) function toggleCollapse(): void { - setIsCollapsed(!isCollapsed) + const newIsCollapsed: boolean = !isCollapsed + + setIsCollapsed(newIsCollapsed) + if (props.onDisplayChnage) props.onDisplayChnage(newIsCollapsed) } return ( diff --git a/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx index 8b1d5f069..bf908097c 100644 --- a/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx +++ b/src/libs/shared/lib/components/grouped-skills-ui/GroupedSkillsUI.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react' +import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import Masonry, { ResponsiveMasonry } from 'react-responsive-masonry' import { UserSkill } from '~/libs/core' @@ -11,37 +11,73 @@ import styles from './GroupedSkillsUI.module.scss' interface GroupedSkillsUIProps { groupedSkillsByCategory: { [key: string]: UserSkill[] } skillsCatsCollapsed: boolean + onAllSkillsSameDisplayState: (collapsed: boolean) => void +} +const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) => { + const [collapsedMap, setCollapsedMap]: + [{ [key: string]: boolean }, Dispatch>] + = useState<{ [key: string]: boolean }>({}) + + useEffect(() => { + const newCollapsedMap: { [key: string]: boolean } = {} + + Object.keys(props.groupedSkillsByCategory) + .forEach((categoryName: string) => { + newCollapsedMap[categoryName] = props.skillsCatsCollapsed + }) + + setCollapsedMap(newCollapsedMap) + }, [props.groupedSkillsByCategory, props.skillsCatsCollapsed]) + + useEffect(() => { + const arr: boolean[] = Object.values(collapsedMap) + + if (arr.every(val => val === arr[0])) { + props.onAllSkillsSameDisplayState(arr[0]) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [collapsedMap]) + + function handleCollapseChange(categoryName: string, isCollapsed: boolean): void { + setCollapsedMap({ + ...collapsedMap, + [categoryName]: isCollapsed, + }) + } + + return ( + + + { + Object.keys(props.groupedSkillsByCategory) + .map((categoryName: string) => ( + + + { + props.groupedSkillsByCategory[categoryName] + .map((skill: UserSkill) => ( + + )) + } + + )) + } + + + ) } -const GroupedSkillsUI: FC = (props: GroupedSkillsUIProps) => ( - - - { - Object.keys(props.groupedSkillsByCategory) - .map((categoryName: string) => ( - - - { - props.groupedSkillsByCategory[categoryName] - .map((skill: UserSkill) => ( - - )) - } - - )) - } - - -) export default GroupedSkillsUI From 4b72b46669c9413e4afce857cc85efde6c36b892 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Thu, 19 Oct 2023 19:52:44 +0300 Subject: [PATCH 21/32] TSJR-111 updates --- .../skills/MemberSkillsInfo.module.scss | 18 ---- .../skills/MemberSkillsInfo.tsx | 38 ++----- .../CollapsibleSkillsList.module.scss | 13 --- .../CollapsibleSkillsList.tsx | 50 +++------ .../grouped-skills-ui/GroupedSkillsUI.tsx | 100 ++++++------------ 5 files changed, 51 insertions(+), 168 deletions(-) diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss index 32162ff66..30f8c665e 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.module.scss @@ -22,24 +22,6 @@ justify-content: space-between; align-items: center; margin-bottom: $sp-6; - - .skillActions { - display: flex; - align-items: center; - - @include ltemd { - flex-direction: column; - align-items: flex-end; - } - - > button:nth-child(2) { - margin-left: $sp-4; - - @include ltemd { - margin-left: 0; - } - } - } } .skillsWrap { diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index 618ac252c..622574f0d 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -35,6 +35,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp const groupedSkillsByCategory: { [key: string]: UserSkill[] } = useMemo(() => { const grouped: { [key: string]: UserSkill[] } = {} + const sortedGroupedSkillsByCategory: { [key: string]: UserSkill[] } = {} memberSkills.forEach((skill: UserSkill) => { if (grouped[skill.category.name]) { @@ -44,11 +45,14 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp } }) - return grouped - }, [memberSkills]) + Object.keys(grouped) + .sort() + .forEach(key => { + sortedGroupedSkillsByCategory[key] = grouped[key] + }) - const [skillsCatsCollapsed, setSkillsCatsCollapsed]: [boolean, Dispatch>] - = useState(true) + return sortedGroupedSkillsByCategory + }, [memberSkills]) const [isEditMode, setIsEditMode]: [boolean, Dispatch>] = useState(false) @@ -87,20 +91,6 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp setHowSkillsWorkVisible(false) } - function handleExpandAllClick(): void { - setSkillsCatsCollapsed(!skillsCatsCollapsed) - } - - function toggleCollapseUIButton(collapsed: boolean): void { - if (collapsed === false && !!skillsCatsCollapsed) { - setSkillsCatsCollapsed(false) - } - - if (collapsed === true && skillsCatsCollapsed === false) { - setSkillsCatsCollapsed(true) - } - } - return (
{ @@ -129,16 +119,6 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp onClick={handleHowSkillsWorkClick} variant='linkblue' /> - { - memberSkills.length > 0 && ( -
@@ -146,8 +126,6 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp {memberSkills.length > 0 && ( )} {!memberSkills.length && ( diff --git a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss index b5bacf1c0..13e2ab221 100644 --- a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss +++ b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss @@ -25,25 +25,12 @@ display: flex; justify-content: flex-start; align-items: flex-start; - cursor: pointer; .title { font-weight: 700; font-size: 14px; } - .btn { - padding-left: 0; - padding-right: $sp-2; - color: $turq-120; - - svg { - flex: 0 0 auto; - color: $turq-120; - @include icon-size(16); - } - } - .badgeCount { background-color: $black-10; border-radius: 50%; diff --git a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx index 7a4de9f40..8d2942145 100644 --- a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx +++ b/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx @@ -1,9 +1,6 @@ -import { Dispatch, FC, ReactNode, SetStateAction, useEffect, useState } from 'react' +import { FC, ReactNode } from 'react' import classNames from 'classnames' -import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline' -import { Button } from '~/libs/ui' - import styles from './CollapsibleSkillsList.module.scss' interface CollapsibleSkillsListProps { @@ -12,44 +9,21 @@ interface CollapsibleSkillsListProps { containerClass?: string headerClass?: string contentClass?: string - isCollapsed: boolean - onDisplayChnage?: (isCollapsed: boolean) => void } -const CollapsibleSkillsList: FC = (props: CollapsibleSkillsListProps) => { - const [isCollapsed, setIsCollapsed]: [boolean, Dispatch>] - = useState(props.isCollapsed) - - useEffect(() => { - setIsCollapsed(props.isCollapsed) - }, [props.isCollapsed]) - - function toggleCollapse(): void { - const newIsCollapsed: boolean = !isCollapsed - - setIsCollapsed(newIsCollapsed) - if (props.onDisplayChnage) props.onDisplayChnage(newIsCollapsed) - } - - return ( -
-
- { - !isCollapsed - ?
) export default GroupedSkillsUI diff --git a/src/libs/shared/lib/components/index.ts b/src/libs/shared/lib/components/index.ts index 016d36443..ac827849a 100644 --- a/src/libs/shared/lib/components/index.ts +++ b/src/libs/shared/lib/components/index.ts @@ -6,4 +6,4 @@ export * from './member-skill-editor' export * from './skill-pill' export * from './expandable-list' export * from './grouped-skills-ui' -export * from './collapsible-skills-list' +export * from './skills-list' diff --git a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss b/src/libs/shared/lib/components/skills-list/SkillsList.module.scss similarity index 94% rename from src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss rename to src/libs/shared/lib/components/skills-list/SkillsList.module.scss index 13e2ab221..251cafd2e 100644 --- a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.module.scss +++ b/src/libs/shared/lib/components/skills-list/SkillsList.module.scss @@ -45,11 +45,11 @@ transition: opacity 0.3s ease-in-out; max-height: auto; opacity: 1; - padding-left: $sp-8; + padding-left: $sp-4; margin-top: $sp-1; @include ltemd { - padding-left: $sp-4; + padding-left: $sp-2; } } } \ No newline at end of file diff --git a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx b/src/libs/shared/lib/components/skills-list/SkillsList.tsx similarity index 74% rename from src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx rename to src/libs/shared/lib/components/skills-list/SkillsList.tsx index 8d2942145..2a2f13971 100644 --- a/src/libs/shared/lib/components/collapsible-skills-list/CollapsibleSkillsList.tsx +++ b/src/libs/shared/lib/components/skills-list/SkillsList.tsx @@ -1,9 +1,9 @@ import { FC, ReactNode } from 'react' import classNames from 'classnames' -import styles from './CollapsibleSkillsList.module.scss' +import styles from './SkillsList.module.scss' -interface CollapsibleSkillsListProps { +interface SkillsListProps { children?: ReactNode[] header?: ReactNode containerClass?: string @@ -11,7 +11,7 @@ interface CollapsibleSkillsListProps { contentClass?: string } -const CollapsibleSkillsList: FC = (props: CollapsibleSkillsListProps) => ( +const SkillsList: FC = (props: SkillsListProps) => (
{props.header}
@@ -26,4 +26,4 @@ const CollapsibleSkillsList: FC = (props: Collapsibl
) -export default CollapsibleSkillsList +export default SkillsList diff --git a/src/libs/shared/lib/components/skills-list/index.ts b/src/libs/shared/lib/components/skills-list/index.ts new file mode 100644 index 000000000..ee1dfc41d --- /dev/null +++ b/src/libs/shared/lib/components/skills-list/index.ts @@ -0,0 +1 @@ +export { default as SkillsList } from './SkillsList' From c9a8d4a0b586ae77a96d31dfc8c6ea48752ad1cc Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Fri, 20 Oct 2023 11:16:54 +0300 Subject: [PATCH 23/32] remove react-responsive-masonry lib as not used --- package.json | 2 -- yarn.lock | 12 ------------ 2 files changed, 14 deletions(-) diff --git a/package.json b/package.json index 32742bd9b..2ef92fbc4 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,6 @@ "react-redux": "^8.0.4", "react-redux-toastr": "^7.6.10", "react-responsive": "^9.0.0-beta.5", - "react-responsive-masonry": "^2.1.7", "react-responsive-modal": "^6.2.0", "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", @@ -160,7 +159,6 @@ "@types/react-gtm-module": "^2.0.1", "@types/react-helmet": "^6.1.6", "@types/react-redux-toastr": "^7.6.2", - "@types/react-responsive-masonry": "^2.1.1", "@types/react-router-dom": "^5.3.3", "@types/redux-actions": "2.6.2", "@types/redux-logger": "^3.0.9", diff --git a/yarn.lock b/yarn.lock index 6a6a6f881..8954e2c9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5402,13 +5402,6 @@ "@types/react" "*" redux "^3.6.0 || ^4.0.0" -"@types/react-responsive-masonry@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@types/react-responsive-masonry/-/react-responsive-masonry-2.1.1.tgz#694fc86964f37b991c3b85ac99a253a04ecb8f6b" - integrity sha512-sFzNsxYugWO8G4d3ObhpcJCiqiYthWp9Udr9phDzy5BYxW78uMF8yK2IJ8+7bQLbmQz2xaIey1ZogbW3ATIo+A== - dependencies: - "@types/react" "*" - "@types/react-router-dom@^5.3.3": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" @@ -16335,11 +16328,6 @@ react-refresh@^0.11.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== -react-responsive-masonry@^2.1.7: - version "2.1.7" - resolved "https://registry.yarnpkg.com/react-responsive-masonry/-/react-responsive-masonry-2.1.7.tgz#9b4a8d63b296a6265bea720c9d7da89754548346" - integrity sha512-/jOqnTVNtO8zRJMTl6ZXBex7EFYEIFBLVlkIFjiCT7omfm0CgNF2z4ST8RIr0v2ut15NWAQs7Q3kJJPhMoe3Ew== - react-responsive-modal@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/react-responsive-modal/-/react-responsive-modal-6.2.0.tgz#339226b911d8ffaba4e0afce83387a65221b8e29" From 7ffe3bc2c10f08c78671300d183508b0ede21d97 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Thu, 26 Oct 2023 11:49:30 +1100 Subject: [PATCH 24/32] Removing parantheses from skill names (TSJR-192) --- .../components/popular-skills/PopularSkills.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx index ec3320621..1b3dc6f82 100644 --- a/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx +++ b/src/apps/talent-search/src/components/popular-skills/PopularSkills.tsx @@ -18,7 +18,7 @@ const popularSkills: UserSkill[] = [ }, id: '63bb7cfc-b0d4-4584-820a-18c503b4b0fe', levels: [], - name: 'Java (Programming Language)', + name: 'Java', }, { category: { @@ -36,7 +36,7 @@ const popularSkills: UserSkill[] = [ }, id: '32899253-5989-4c33-9948-cad29c9e0ab0', levels: [], - name: 'Node.js (Javascript Library)', + name: 'Node.js', }, { category: { @@ -54,7 +54,7 @@ const popularSkills: UserSkill[] = [ }, id: '16ee1403-8e73-497d-a766-623eefd3c806', levels: [], - name: 'JavaScript (Programming Language)', + name: 'JavaScript', }, { category: { @@ -81,7 +81,7 @@ const popularSkills: UserSkill[] = [ }, id: '7e8641e5-e5c1-4ab6-a8f4-1fd6a8686dbe', levels: [], - name: 'Angular (Web Framework)', + name: 'Angular', }, { category: { @@ -99,7 +99,7 @@ const popularSkills: UserSkill[] = [ }, id: 'fcbac194-35ab-4a31-aa7c-a2867fff9c4b', levels: [], - name: 'Python (Programming Language)', + name: 'Python', }, { category: { @@ -108,7 +108,7 @@ const popularSkills: UserSkill[] = [ }, id: 'adf9d7b9-d639-4a73-8772-673b3d4f41b0', levels: [], - name: 'Android (Operating System)', + name: 'Android', }, { category: { @@ -144,7 +144,7 @@ const popularSkills: UserSkill[] = [ }, id: 'be85b096-b841-45b4-a5cb-1d3ee7ce1126', levels: [], - name: 'Docker (Software)', + name: 'Docker', }, { category: { @@ -153,7 +153,7 @@ const popularSkills: UserSkill[] = [ }, id: '4458454c-9a97-4332-a545-6546e240dab6', levels: [], - name: 'React.js (Javascript Library)', + name: 'React.js', }, ] From 24a963521d17b25e61d4dc535367863a1f4299d5 Mon Sep 17 00:00:00 2001 From: eisbilir Date: Thu, 26 Oct 2023 13:33:29 +0300 Subject: [PATCH 25/32] allow to disable dice, remove verification step --- .../accounts/src/lib/assets/security/index.ts | 2 - .../tabs/account/security/Security.tsx | 46 ++++-- .../ConnectionHandler.module.scss | 5 - .../ConnectionHandler/index.tsx | 35 +---- .../dice-setup-modal/DiceSetupModal.tsx | 147 +++++++----------- .../VerificationListener/index.tsx | 29 ---- src/config/environments/default.env.ts | 6 - .../environments/global-config.model.ts | 1 - .../data-providers/useDiceIdConnection.ts | 3 +- .../core/lib/profile/modify-user-mfa.model.ts | 5 +- 10 files changed, 97 insertions(+), 182 deletions(-) delete mode 100644 src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss delete mode 100644 src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/VerificationListener/index.tsx diff --git a/src/apps/accounts/src/lib/assets/security/index.ts b/src/apps/accounts/src/lib/assets/security/index.ts index 8b87173a7..f6ae8f7f2 100644 --- a/src/apps/accounts/src/lib/assets/security/index.ts +++ b/src/apps/accounts/src/lib/assets/security/index.ts @@ -1,6 +1,5 @@ import { ReactComponent as MFAImage } from './mfa.svg' import { ReactComponent as AppleStore } from './apple-store.svg' -import { ReactComponent as UnSuccessfullDiceVerificationIcon } from './unsuccessful.svg' import diceIdLogo from './dicelogo.png' import diceIdLogoBig from './dicelogobig.png' import diceIdLogoSmall from './dicelogosmall.png' @@ -13,5 +12,4 @@ export { diceIdLogoSmall, googlePlay, MFAImage, - UnSuccessfullDiceVerificationIcon, } diff --git a/src/apps/accounts/src/settings/tabs/account/security/Security.tsx b/src/apps/accounts/src/settings/tabs/account/security/Security.tsx index f8a608d40..f521783bf 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/Security.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/Security.tsx @@ -1,9 +1,8 @@ import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import { toast } from 'react-toastify' import { KeyedMutator } from 'swr' -import { noop } from 'lodash' -import { Button, Collapsible, FormToggleSwitch, IconSolid, Tooltip } from '~/libs/ui' +import { Button, Collapsible, FormToggleSwitch } from '~/libs/ui' import { diceIdLogo, MFAImage, SettingSection, triggerSurvey } from '~/apps/accounts/src/lib' import { MemberMFAStatus, updateMemberMFAStatusAsync, useMemberMFAStatus, UserProfile } from '~/libs/core' @@ -23,10 +22,12 @@ const Security: FC = (props: SecurityProps) => { } = useMemberMFAStatus(props.profile.userId) const [mfaEnabled, setMFAEnabled]: [boolean, Dispatch>] = useState(false) + const [diceEnabled, setDiceEnabled]: [boolean, Dispatch>] = useState(false) useEffect(() => { if (mfaStatusData) { setMFAEnabled(mfaStatusData.mfaEnabled) + setDiceEnabled(mfaStatusData.diceEnabled) } }, [mfaStatusData]) @@ -36,8 +37,9 @@ const Security: FC = (props: SecurityProps) => { mfaEnabled: !mfaEnabled, }, }) - .then(() => { - setMFAEnabled(!mfaEnabled) + .then(response => { + setMFAEnabled(response.result.content.mfaEnabled) + setDiceEnabled(response.result.content.diceEnabled) toast.success('Your Multi Factor Authentication (MFA) status was updated.') triggerSurvey() }) @@ -46,6 +48,27 @@ const Security: FC = (props: SecurityProps) => { }) } + function handleUserDiceChange(): void { + if (!diceEnabled) { + return + } + + updateMemberMFAStatusAsync(props.profile.userId, { + param: { + diceEnabled: !diceEnabled, + }, + }) + .then(response => { + setMFAEnabled(response.result.content.mfaEnabled) + setDiceEnabled(response.result.content.diceEnabled) + toast.success('Your DICE credential was disabled.') + triggerSurvey() + }) + .catch(() => { + toast.error('Something went wrong. Please try again later.') + }) + } + function handleDiceModalStatus(): void { setSetupDiceModalOpen(!setupDiceModalOpen) } @@ -70,7 +93,6 @@ const Security: FC = (props: SecurityProps) => { name='mfaStatus' onChange={handleUserMFAChange} value={mfaEnabled} - disabled={mfaStatusData?.diceEnabled} /> )} /> @@ -86,12 +108,11 @@ const Security: FC = (props: SecurityProps) => { actionElement={(
{ - mfaStatusData?.diceEnabled ? ( + diceEnabled ? ( ) : (
)} /> diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss deleted file mode 100644 index 6b696efa6..000000000 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/ConnectionHandler.module.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import '@libs/ui/styles/includes'; - -.qrCode { - margin: auto; -} \ No newline at end of file diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx index f56ca93fd..07e3f7075 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx @@ -1,12 +1,9 @@ import { FC, useEffect } from 'react' -import { QRCodeSVG } from 'qrcode.react' import { DiceConnectionStatus, useDiceIdConnection } from '~/libs/core' -import styles from './ConnectionHandler.module.scss' - interface ConnectionHandlerProps { - onComplete: () => void; + onChange: (newStatus: DiceConnectionStatus) => void; userId: number; } @@ -16,36 +13,12 @@ export const ConnectionHandler: FC = ( const diceConnection: DiceConnectionStatus | undefined = useDiceIdConnection(props.userId) useEffect(() => { - if (diceConnection && diceConnection.accepted) { - props.onComplete() + if (diceConnection) { + props.onChange(diceConnection) } }, [diceConnection, props]) return ( - <> -

- Scan the following DICE ID QR Code in your DICE ID - mobile application. -

- {diceConnection && diceConnection.connection ? ( - - ) : ( -

Loading...

- )} -

- Once the connection is established, the service will - offer you a Verifiable Credential. -
- Press the ACCEPT button in your DICE ID App. -
- If you DECLINE the invitation, please try again after 5 - minutes. -

- + <> ) } diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx index a26925a2d..8bd4ca05a 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx @@ -1,6 +1,6 @@ +/* eslint-disable complexity */ import { Dispatch, FC, SetStateAction, useState } from 'react' import { QRCodeSVG } from 'qrcode.react' -import { get, isUndefined, lowerCase } from 'lodash' import { toast } from 'react-toastify' import { KeyedMutator } from 'swr' @@ -10,13 +10,10 @@ import { diceIdLogoBig, diceIdLogoSmall, googlePlay, - UnSuccessfullDiceVerificationIcon, } from '~/apps/accounts/src/lib' -import { updateMemberMFAStatusAsync, UserProfile } from '~/libs/core' -import { EnvironmentConfig } from '~/config' +import { DiceConnectionStatus, UserProfile } from '~/libs/core' import { ConnectionHandler } from './ConnectionHandler' -import { VerificationListener } from './VerificationListener' import styles from './DiceSetupModal.module.scss' const GooglePlayLink: string = 'https://play.google.com/store/apps/details?id=com.diwallet1' @@ -30,8 +27,7 @@ interface DiceSetupModalProps { const DiceSetupModal: FC = (props: DiceSetupModalProps) => { const [step, setStep]: [number, Dispatch>] = useState(1) - const [isVerificationProcessing, setIsVerificationProcessing]: [boolean, Dispatch>] - = useState(false) + const [diceConnectionUrl, setDiceConnectionUrl] = useState() function handleSecondaryButtonClick(): void { switch (step) { @@ -43,42 +39,25 @@ const DiceSetupModal: FC = (props: DiceSetupModalProps) => function handlePrimaryButtonClick(): void { switch (step) { case 1: - case 2: return setStep(step + 1) default: return props.onClose() } } - function verificationCallback(data: any): void { - if (data.success) { - const userEmail: string = get(data, 'user.profile.Email') - if (!isUndefined(userEmail) && lowerCase(userEmail) === lowerCase(props.profile.email)) { - updateMemberMFAStatusAsync(props.profile.userId, { - param: { - diceEnabled: true, - }, - }) - .then(() => { - props.mutateMFAData() - setStep(4) - // eslint-disable-next-line max-len - toast.success('Your credentials have been verified and you are all set for MFA using your decentralized identity (DICE ID).') - }) - .catch(() => { - toast.error('Something went wrong. Please try again later.') - }) - } else { - setStep(5) - } - } else { - setStep(5) + function handleDiceConnectionStatusChange(newStatus: DiceConnectionStatus): void { + if (newStatus.diceEnabled) { + setStep(4) + toast.success('Your credentials have been verified and you are all set for' + + ' MFA using your decentralized identity (DICE ID).') + props.mutateMFAData() + } else if (newStatus.accepted) { + setStep(3) + } else if (newStatus.connection) { + setDiceConnectionUrl(newStatus.connection) + setStep(2) } } - function onStartProcessing(): void { - setIsVerificationProcessing(true) - } - return ( = (props: DiceSetupModalProps) => onClick={handleSecondaryButtonClick} /> { - step !== 2 && step !== 3 && ( + (step === 1 || step === 4) && (