Skip to content

Commit c08facf

Browse files
committed
chore(react): enhance user profile handling by adding path support and integrating getMeProfile after updates
1 parent 11c198e commit c08facf

File tree

3 files changed

+46
-18
lines changed

3 files changed

+46
-18
lines changed

packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ import {withVendorCSSClassPrefix} from '@asgardeo/browser';
2727
import clsx from 'clsx';
2828
import getMappedUserProfileValue from '../../../utils/getMappedUserProfileValue';
2929

30-
interface Schema {
31-
id?: string;
30+
interface ExtendedFlatSchema {
31+
schemaId?: string;
32+
path?: string;
33+
}
34+
35+
interface Schema extends ExtendedFlatSchema {
3236
caseExact?: boolean;
3337
description?: string;
3438
displayName?: string;
@@ -109,25 +113,40 @@ const BaseUserProfile: FC<BaseUserProfileProps> = ({
109113
}));
110114
}, []);
111115

116+
function set(obj: Record<string, any>, path: string, value: any): void {
117+
const keys = path.split('.');
118+
let current = obj;
119+
120+
for (let i = 0; i < keys.length; i++) {
121+
const key = keys[i];
122+
123+
// If last key, set the value
124+
if (i === keys.length - 1) {
125+
current[key] = value;
126+
} else {
127+
// If the next level does not exist or is not an object, create an object
128+
if (!current[key] || typeof current[key] !== 'object') {
129+
current[key] = {};
130+
}
131+
current = current[key];
132+
}
133+
}
134+
}
135+
112136
const handleFieldSave = useCallback(
113137
(schema: Schema) => {
114138
let payload = {};
139+
const fieldName = schema.name;
140+
const fieldValue =
141+
editedUser && fieldName && editedUser[fieldName] !== undefined ? editedUser[fieldName] : schema.value;
115142

116-
if (schema.multiValued) {
117-
payload = {
118-
[schema.id]: {
119-
[schema.name]: schema.value,
120-
},
121-
};
122-
} else {
123-
payload = {
124-
[schema.name]: schema.value,
125-
};
126-
}
143+
set(payload, schema.path, fieldValue);
127144

128145
onUpdate(payload);
146+
// Optionally, exit edit mode for this field after save
147+
toggleFieldEdit(fieldName!);
129148
},
130-
[onChange, onSubmit, editedUser, toggleFieldEdit],
149+
[editedUser, onUpdate, toggleFieldEdit],
131150
);
132151

133152
const handleFieldCancel = useCallback(

packages/react/src/components/presentation/UserProfile/UserProfile.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {FC, ReactElement} from 'react';
2020
import useAsgardeo from '../../../hooks/useAsgardeo';
2121
import BaseUserProfile, {BaseUserProfileProps} from './BaseUserProfile';
2222
import updateMeProfile from 'packages/react/src/api/scim2/updateMeProfile';
23+
import getMeProfile from 'packages/react/src/api/scim2/getMeProfile';
2324

2425
/**
2526
* Props for the UserProfile component.
@@ -54,7 +55,8 @@ const UserProfile: FC<UserProfileProps> = ({...rest}: UserProfileProps): ReactEl
5455
const {user, baseUrl} = useAsgardeo();
5556

5657
const handleProfileUpdate = async (payload: any): Promise<void> => {
57-
updateMeProfile({url: `${baseUrl}/scim2/Me`, payload});
58+
await updateMeProfile({url: `${baseUrl}/scim2/Me`, payload});
59+
await getMeProfile({url: `${baseUrl}/scim2/Me` });
5860
};
5961

6062
return <BaseUserProfile user={user} onUpdate={handleProfileUpdate} {...rest} />;

packages/react/src/utils/getUserProfile.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,23 @@ const getUserProfile = async ({baseUrl}): Promise<any> => {
7171
const source = schemaId.startsWith('urn:ietf:params:scim:schemas:core:2.0') ? profile : profile[schemaId] ?? {};
7272

7373
for (const attr of schema.attributes || []) {
74-
const {name, type, subAttributes, multiValued} = attr;
74+
const {name, type, subAttributes, multiValued, caseExact, returned} = attr;
7575

7676
if (type === 'COMPLEX' && subAttributes?.length && typeof source[name] === 'object') {
7777
// For complex attributes with subAttributes, create an entry for each subAttribute
7878
const complexValue = source[name];
7979
for (const subAttr of subAttributes) {
8080
if (complexValue[subAttr.name] !== undefined) {
81+
const {subAttributes, ...attrWithoutSubAttrs} = attr;
82+
8183
result.push({
82-
id: schemaId,
84+
schemaId,
8385
...subAttr,
8486
value: complexValue[subAttr.name],
87+
parent: {
88+
...attrWithoutSubAttrs,
89+
},
90+
path: `${name}.${subAttr.name}`,
8591
});
8692
}
8793
}
@@ -90,9 +96,10 @@ const getUserProfile = async ({baseUrl}): Promise<any> => {
9096
// Only include if value exists
9197
if (value !== undefined) {
9298
result.push({
93-
id: schemaId,
99+
schemaId,
94100
...attr,
95101
value,
102+
path: name,
96103
});
97104
}
98105
}

0 commit comments

Comments
 (0)