Skip to content

Commit

Permalink
docs: Add TypeScript typings to LmsApiService group methods (#1426)
Browse files Browse the repository at this point in the history
docs: use AxiosResponse type

refactor: LmsApiService group methods convert response to camelCase

build: use @edx/typescript-config compilerOptions

build: move typescript-config to devDependencies

docs: separate pagination types and camelCase fields

build: add trailing comma to tsconfig
  • Loading branch information
marlonkeating authored Feb 19, 2025
1 parent 02cc629 commit d5fef09
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 40 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
},
"devDependencies": {
"@edx/browserslist-config": "1.5.0",
"@edx/typescript-config": "1.1.0",
"@faker-js/faker": "^7.6.0",
"@openedx/frontend-build": "14.2.2",
"@testing-library/dom": "9.3.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('useEnterpriseGroup', () => {
it('should fetch and return enterprise group', async () => {
jest.spyOn(LmsApiService, 'fetchEnterpriseGroup').mockResolvedValueOnce({
data: {
enterprise_customer: 'customer-uuid',
enterpriseCustomer: 'customer-uuid',
name: 'groupidy group',
uuid: 'group-uuid',
},
Expand All @@ -47,7 +47,7 @@ describe('useEnterpriseGroup', () => {
it('should return null if no group associations are listed', async () => {
jest.spyOn(LmsApiService, 'fetchEnterpriseGroup').mockResolvedValueOnce({
data: {
enterprise_customer: 'customer-uuid',
enterpriseCustomer: 'customer-uuid',
name: 'groupidy group',
uuid: 'group-uuid',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { camelCaseObject } from '@edx/frontend-platform/utils';
import isEmpty from 'lodash/isEmpty';

import { learnerCreditManagementQueryKeys } from '../constants';
Expand All @@ -16,8 +15,7 @@ const getEnterpriseGroup = async ({ subsidyAccessPolicy }) => {
return null;
}
const response = await LmsApiService.fetchEnterpriseGroup(subsidyAccessPolicy.groupAssociations[0]);
const enterpriseGroup = camelCaseObject(response.data);
return enterpriseGroup;
return response.data;
};

const useEnterpriseGroup = (subsidyAccessPolicy, { queryOptions } = {}) => useQuery({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { camelCaseObject } from '@edx/frontend-platform/utils';
import type { AxiosResponse } from 'axios';

import { configuration } from '../../config';
import generateFormattedStatusUrl from './apiServiceUtils';
import { EnterpriseGroup, PaginatedCurrentPage } from '../../types';

export type CreateEnterpriseGroupArgs = {
/* The name of the group to create */
groupName: string,
/* The uuid of the new group's enterprise customer */
enterpriseUUID: string
};

export type UpdateEnterpriseGroupArgs = {
/* The updated name of the group */
name: string,
};

export type EnterpriseGroupResponse = Promise<AxiosResponse<EnterpriseGroup>>;
export type EnterpriseGroupListResponse = Promise<AxiosResponse<PaginatedCurrentPage<EnterpriseGroup>>>;

class LmsApiService {
static apiClient = getAuthenticatedHttpClient;
Expand Down Expand Up @@ -49,14 +66,14 @@ class LmsApiService {

static enterpriseLearnerUrl = `${LmsApiService.baseUrl}/enterprise/api/v1/enterprise-learner/`;

static createEnterpriseGroup(options) {
static createEnterpriseGroup({ groupName, enterpriseUUID }: CreateEnterpriseGroupArgs): EnterpriseGroup {
const postParams = {
name: options.groupName,
enterprise_customer: options.enterpriseUUID,
name: groupName,
enterprise_customer: enterpriseUUID,
members: [],
};
const createEnterpriseGroupUrl = `${LmsApiService.enterpriseGroupListUrl}`;
return LmsApiService.apiClient().post(createEnterpriseGroupUrl, postParams);
return camelCaseObject(LmsApiService.apiClient().post(createEnterpriseGroupUrl, postParams));
}

static fetchEnterpriseSsoOrchestrationRecord(configurationUuid) {
Expand Down Expand Up @@ -428,7 +445,7 @@ class LmsApiService {
);
};

static async fetchData(url, linkedEnterprises = []) {
static async fetchData(url, linkedEnterprises: any[] = []) {
const response = await getAuthenticatedHttpClient().get(url);
const responseData = camelCaseObject(response.data);
const linkedEnterprisesCopy = [...linkedEnterprises];
Expand All @@ -449,14 +466,18 @@ class LmsApiService {
return response;
};

static fetchEnterpriseGroup = async (groupUuid) => {
static fetchEnterpriseGroup = async (groupUuid: string): EnterpriseGroupResponse => {
const groupEndpoint = `${LmsApiService.enterpriseGroupListUrl}${groupUuid}/`;
return LmsApiService.apiClient().get(groupEndpoint);
const response = LmsApiService.apiClient().get(groupEndpoint);
response.data = camelCaseObject(response.data);
return response;
};

static fetchEnterpriseGroups = async () => {
static fetchEnterpriseGroups = async (): EnterpriseGroupListResponse => {
const url = `${LmsApiService.enterpriseGroupUrl}`;
return LmsApiService.apiClient().get(url);
const response = LmsApiService.apiClient().get(url);
response.data = camelCaseObject(response.data);
return response;
};

static inviteEnterpriseLearnersToGroup = async (groupUuid, formData) => {
Expand All @@ -475,21 +496,26 @@ class LmsApiService {

static fetchAllEnterpriseGroupLearners = async (groupUuid) => {
const queryParams = new URLSearchParams({
page: 1,
page: '1',
});
const url = `${LmsApiService.enterpriseGroupUrl}${groupUuid}/learners?${queryParams.toString()}`;
const response = await LmsApiService.fetchData(url);
return response;
};

static removeEnterpriseGroup = async (groupUuid) => {
static removeEnterpriseGroup = async (groupUuid: string): Promise<AxiosResponse> => {
const removeGroupEndpoint = `${LmsApiService.enterpriseGroupListUrl}${groupUuid}/`;
return LmsApiService.apiClient().delete(removeGroupEndpoint);
};

static updateEnterpriseGroup = async (groupUuid, formData) => {
static updateEnterpriseGroup = async (
groupUuid: string,
formData: UpdateEnterpriseGroupArgs,
): EnterpriseGroupResponse => {
const updateGroupEndpoint = `${LmsApiService.enterpriseGroupListUrl}${groupUuid}/`;
return LmsApiService.apiClient().patch(updateGroupEndpoint, formData);
const response = LmsApiService.apiClient().patch(updateGroupEndpoint, formData);
response.data = camelCaseObject(response.data);
return response;
};

static removeEnterpriseLearnersFromGroup = async (groupUuid, formData) => {
Expand Down
2 changes: 1 addition & 1 deletion src/data/services/tests/LmsApiService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('LmsApiService', () => {
data: {
uuid: 'test-uuid',
name: 'test-name',
enterprise_customer: 'test-enterprise-customer',
enterpriseCustomer: 'test-enterprise-customer',
members: [],
},
});
Expand Down
30 changes: 30 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export type Paginated<ResultItem> = {
next: string?,
previous: string?,
count: number,
results: ResultItem[],
};

export type PaginatedCurrentPage<ResultItem> = Paginated<ResultItem> & {
currentPage: number,
start: number,
};

export type EnterpriseGroupType = 'budget' | 'flex';

export type EnterpriseGroup = {
/* uuid of enterprise customer */
enterpriseCustomer: string,
/* Group name */
name: string,
/* Group uuid */
uuid: string,
/* Number of accepted Group members */
acceptedMembersCount: number,
/* Type of group */
groupType: EnterpriseGroupType,
/* Date group was created */
created: string,
};

export as namespace Types;
24 changes: 3 additions & 21 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
{
"extends": "@edx/typescript-config",
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": ["dom", "es6", "dom.iterable"],
"isolatedModules": true,
"module": "ES6",
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": false,
"noImplicitThis": true,
"noUnusedParameters": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"strictFunctionTypes": false,
"target": "ES6",
"rootDir": ".",
"outDir": "dist"
"outDir": "dist",
},
"include": ["src/**/*", "__mocks__/**/*"],
"exclude": ["dist", "src/icons/*"]
"exclude": ["dist", "src/icons/*"],
}

0 comments on commit d5fef09

Please sign in to comment.