169 lines
5.7 KiB
JavaScript
169 lines
5.7 KiB
JavaScript
import { ensureConfig, getConfig } from '@edx/frontend-platform';
|
|
import { getAuthenticatedHttpClient as getHttpClient } from '@edx/frontend-platform/auth';
|
|
import { logError } from '@edx/frontend-platform/logging';
|
|
import { camelCaseObject, convertKeyNames, snakeCaseObject } from '../utils';
|
|
import { FIELD_LABELS } from './constants';
|
|
|
|
ensureConfig(['LMS_BASE_URL'], 'Profile API service');
|
|
|
|
function processAccountData(data) {
|
|
const processedData = camelCaseObject(data);
|
|
return {
|
|
...processedData,
|
|
socialLinks: Array.isArray(processedData.socialLinks) ? processedData.socialLinks : [],
|
|
languageProficiencies: Array.isArray(processedData.languageProficiencies)
|
|
? processedData.languageProficiencies : [],
|
|
name: processedData.name || null,
|
|
bio: processedData.bio || null,
|
|
country: processedData.country || null,
|
|
levelOfEducation: processedData.levelOfEducation || null,
|
|
profileImage: processedData.profileImage || {},
|
|
yearOfBirth: processedData.yearOfBirth || null,
|
|
};
|
|
}
|
|
|
|
function processAndThrowError(error, errorDataProcessor) {
|
|
const processedError = Object.create(error);
|
|
if (error.response && error.response.data && typeof error.response.data === 'object') {
|
|
processedError.processedData = errorDataProcessor(error.response.data);
|
|
throw processedError;
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export async function getAccount(username) {
|
|
const { data } = await getHttpClient().get(`${getConfig().LMS_BASE_URL}/api/user/v1/accounts/${username}`);
|
|
|
|
return processAccountData(data);
|
|
}
|
|
|
|
export async function patchProfile(username, params) {
|
|
const processedParams = snakeCaseObject(params);
|
|
|
|
const { data } = await getHttpClient()
|
|
.patch(`${getConfig().LMS_BASE_URL}/api/user/v1/accounts/${username}`, processedParams, {
|
|
headers: {
|
|
'Content-Type': 'application/merge-patch+json',
|
|
},
|
|
})
|
|
.catch((error) => {
|
|
processAndThrowError(error, processAccountData);
|
|
});
|
|
|
|
return processAccountData(data);
|
|
}
|
|
|
|
export async function postProfilePhoto(username, formData) {
|
|
// eslint-disable-next-line no-unused-vars
|
|
const { data } = await getHttpClient().post(
|
|
`${getConfig().LMS_BASE_URL}/api/user/v1/accounts/${username}/image`,
|
|
formData,
|
|
{
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
},
|
|
).catch((error) => {
|
|
processAndThrowError(error, camelCaseObject);
|
|
});
|
|
|
|
// TODO: Someday in the future the POST photo endpoint
|
|
// will return the new values. At that time we should
|
|
// use the commented line below instead of the separate
|
|
// getAccount request that follows.
|
|
// return camelCaseObject(data);
|
|
const updatedData = await getAccount(username);
|
|
return updatedData.profileImage;
|
|
}
|
|
|
|
export async function deleteProfilePhoto(username) {
|
|
// eslint-disable-next-line no-unused-vars
|
|
const { data } = await getHttpClient().delete(`${getConfig().LMS_BASE_URL}/api/user/v1/accounts/${username}/image`);
|
|
|
|
// TODO: Someday in the future the POST photo endpoint
|
|
// will return the new values. At that time we should
|
|
// use the commented line below instead of the separate
|
|
// getAccount request that follows.
|
|
// return camelCaseObject(data);
|
|
const updatedData = await getAccount(username);
|
|
return updatedData.profileImage;
|
|
}
|
|
|
|
export async function getPreferences(username) {
|
|
const { data } = await getHttpClient().get(`${getConfig().LMS_BASE_URL}/api/user/v1/preferences/${username}`);
|
|
|
|
return camelCaseObject(data);
|
|
}
|
|
|
|
export async function patchPreferences(username, params) {
|
|
let processedParams = snakeCaseObject(params);
|
|
processedParams = convertKeyNames(processedParams, {
|
|
visibility_bio: 'visibility.bio',
|
|
visibility_course_certificates: 'visibility.course_certificates',
|
|
visibility_country: 'visibility.country',
|
|
visibility_date_joined: 'visibility.date_joined',
|
|
visibility_level_of_education: 'visibility.level_of_education',
|
|
visibility_language_proficiencies: 'visibility.language_proficiencies',
|
|
visibility_name: 'visibility.name',
|
|
visibility_social_links: 'visibility.social_links',
|
|
visibility_time_zone: 'visibility.time_zone',
|
|
});
|
|
|
|
await getHttpClient().patch(`${getConfig().LMS_BASE_URL}/api/user/v1/preferences/${username}`, processedParams, {
|
|
headers: { 'Content-Type': 'application/merge-patch+json' },
|
|
});
|
|
|
|
return params; // TODO: Once the server returns the updated preferences object, return that.
|
|
}
|
|
|
|
function transformCertificateData(data) {
|
|
const transformedData = [];
|
|
data.forEach((cert) => {
|
|
// download_url may be full url or absolute path.
|
|
// note: using the URL() api breaks in ie 11
|
|
const urlIsPath = typeof cert.download_url === 'string'
|
|
&& cert.download_url.search(/http[s]?:\/\//) !== 0;
|
|
|
|
const downloadUrl = urlIsPath
|
|
? `${getConfig().LMS_BASE_URL}${cert.download_url}`
|
|
: cert.download_url;
|
|
|
|
transformedData.push({
|
|
...camelCaseObject(cert),
|
|
certificateType: cert.certificate_type,
|
|
downloadUrl,
|
|
});
|
|
});
|
|
return transformedData;
|
|
}
|
|
|
|
export async function getCourseCertificates(username) {
|
|
const url = `${getConfig().LMS_BASE_URL}/api/certificates/v0/certificates/${username}/`;
|
|
try {
|
|
const { data } = await getHttpClient().get(url);
|
|
return transformCertificateData(data);
|
|
} catch (e) {
|
|
logError(e);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function extractCountryList(data) {
|
|
return data?.fields
|
|
.find(({ name }) => name === FIELD_LABELS.COUNTRY)
|
|
?.options?.map(({ value }) => (value)) || [];
|
|
}
|
|
|
|
export async function getCountryList() {
|
|
const url = `${getConfig().LMS_BASE_URL}/user_api/v1/account/registration/`;
|
|
|
|
try {
|
|
const { data } = await getHttpClient().get(url);
|
|
return extractCountryList(data);
|
|
} catch (e) {
|
|
logError(e);
|
|
return [];
|
|
}
|
|
}
|