Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/TableFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type TableFooterProps = {
};

const TableFooter = ({
pageSizeOptions = [10, 20, 30, 40],
pageSizeOptions = [10, 25, 50, 100],
}: TableFooterProps) => {
const intl = useIntl();
const { setPageSize, state } = useContext<DataTableContextValue>(DataTableContext);
Expand Down
2 changes: 1 addition & 1 deletion src/app/TableName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const TableName = ({
destination={destination}
variant="muted"
>
<Row>
<Row className="align-items-center mx-auto">
{image && (
<Image
alt={`${name} logo`}
Expand Down
9 changes: 9 additions & 0 deletions src/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,12 @@ export interface CellValue<T> {
original: T;
};
}

export interface ApiResponse<T = any> {
count: number;
next?: string | null;
previous?: string | null;
results: T[];
currentPage?: number;
numPages?: number;
}
4 changes: 2 additions & 2 deletions src/catalogs/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const getPartnerCatalogs = async (
pageSize: number,
): Promise<PaginatedResponse<CorporateCatalog>> => {
try {
const url = new URL(`${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/${partnerId}/catalogs/`);
const url = new URL(`${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/${partnerId}/catalogs/`);
url.searchParams.append('page', page.toString());
url.searchParams.append('page_size', pageSize.toString());

Expand All @@ -35,7 +35,7 @@ export const getCatalogDetails = async (
catalogId: string | number,
): Promise<CorporateCatalog | null> => {
try {
const url = `${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/${partnerId}/catalogs/${catalogId}/`;
const url = `${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/${partnerId}/catalogs/${catalogId}/`;
const response = await getAuthenticatedHttpClient().get(url);
return camelCaseObject(response.data);
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions src/courses/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CorporateCourse, PaginatedResponse } from '@src/app/types';
export const getCourses = async (partnerId: string, catalogId: string, pageIndex, pageSize)
: Promise<PaginatedResponse<CorporateCourse>> => {
try {
const url = new URL(`${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/${partnerId}/catalogs/${catalogId}/courses/`);
const url = new URL(`${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/${partnerId}/catalogs/${catalogId}/courses/`);
url.searchParams.append('page', pageIndex);
url.searchParams.append('page_size', pageSize);
const { data } = await getAuthenticatedHttpClient().get(url);
Expand All @@ -21,7 +21,7 @@ export const getCourses = async (partnerId: string, catalogId: string, pageIndex

export const deleteCourse = async (partnerId: string, catalogId: string, courseId: number) => {
try {
await getAuthenticatedHttpClient().delete(`${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/${partnerId}/catalogs/${catalogId}/courses/${courseId}/`);
await getAuthenticatedHttpClient().delete(`${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/${partnerId}/catalogs/${catalogId}/courses/${courseId}/`);
} catch (error) {
logError(error);
throw error;
Expand Down
4 changes: 2 additions & 2 deletions src/partner/CorporatePartnerPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import AppLayout from '../app/AppLayout';
import CorpotatePartnerList from './components/CorporatePartnerList';
import CorporatePartnerList from './components/CorporatePartnerList';
import messages from './messages';

const CorpotatePartnerPage = () => {
const intl = useIntl();
return (
<AppLayout title={intl.formatMessage(messages.titleCorporatePage)}>
<CorpotatePartnerList />
<CorporatePartnerList />
</AppLayout>
);
};
Expand Down
15 changes: 9 additions & 6 deletions src/partner/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ import { getConfig, camelCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { logError } from '@edx/frontend-platform/logging';

import { CorporatePartner } from '../app/types';
import { CorporatePartner, ApiResponse } from '../app/types';

export const getPartners = async (): Promise<CorporatePartner[]> => {
const url = `${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/`;
interface PartnersApiResponse extends ApiResponse {
results: CorporatePartner[];
}
export const getPartners = async ({ pageSize, pageIndex }): Promise<PartnersApiResponse> => {
const url = `${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/?page_size=${pageSize}&page=${pageIndex}`;
try {
const response = await getAuthenticatedHttpClient().get(url);
return camelCaseObject(response.data.results);
return camelCaseObject(response.data);
} catch (error) {
logError(error);
return [];
return { results: [], count: 0 };
}
};

export const getPartnerDetails = async (partnerId?: string): Promise<CorporatePartner> => {
try {
const url = `${getConfig().LMS_BASE_URL}/corporate_access/api/v1/partners/${partnerId}/`;
const url = `${getConfig().LMS_BASE_URL}/partner_catalog/api/v1/partners/${partnerId}/`;
const response = await getAuthenticatedHttpClient().get(url);
return camelCaseObject(response.data);
} catch (error) {
Expand Down
57 changes: 31 additions & 26 deletions src/partner/components/CorporatePartnerList.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { screen } from '@testing-library/react';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import { renderWrapper } from '@src/setupTest';
import CorporatePartnerList from './CorporatePartnerList';

Expand All @@ -14,33 +14,38 @@ jest.mock('../../app/TableFooter', () => function TableFooter() {
return <div data-testid="table-footer" />;
});

const mockPartners = [
{
code: 1,
name: 'Example University',
homepage: 'https://exampleu.com/university',
logo: 'https://exampleu.com/logo.png',
catalogs: 5,
courses: 12,
enrollments: 1000,
certified: 400,
},
{
code: 2,
name: 'Test Institute',
homepage: 'https://test.com/institute',
logo: 'https://test.com/logo.png',
catalogs: 2,
courses: 8,
enrollments: 700,
certified: 300,
},
];
const mockApiResponse = {
results: [
{
code: 1,
name: 'Example University',
homepage: 'https://exampleu.com/university',
logo: 'https://exampleu.com/logo.png',
catalogs: 5,
courses: 12,
enrollments: 1000,
certified: 400,
},
{
code: 2,
name: 'Test Institute',
homepage: 'https://test.com/institute',
logo: 'https://test.com/logo.png',
catalogs: 2,
courses: 8,
enrollments: 700,
certified: 300,
},
],
count: 2,
next: null,
previous: null,
};

describe('CorporatePartnerList', () => {
beforeEach(() => {
(useSuspenseQuery as jest.Mock).mockReturnValue({
data: mockPartners,
(useQuery as jest.Mock).mockReturnValue({
data: mockApiResponse,
isLoading: false,
});
});
Expand Down Expand Up @@ -72,7 +77,7 @@ describe('CorporatePartnerList', () => {
});

it('shows loading state if data is still loading', () => {
(useSuspenseQuery as jest.Mock).mockReturnValue({
(useQuery as jest.Mock).mockReturnValue({
data: [],
isLoading: true,
});
Expand Down
38 changes: 26 additions & 12 deletions src/partner/components/CorporatePartnerList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useSuspenseQuery } from '@tanstack/react-query';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
DataTable, TextFilter,
Expand All @@ -8,11 +7,12 @@ import { CorporatePartner } from '@src/app/types';
import TableName from '@src/app/TableName';
import { useNavigate } from '@src/hooks';
import { paths } from '@src/constants';
import { getPartners } from '../api';
import { useCallback, useState } from 'react';
import TableFooter from '../../app/TableFooter';

import messages from '../messages';
import ActionItem from '../../app/ActionItem';
import { usePartners } from '../hooks';

type CellValue = {
row: {
Expand All @@ -22,13 +22,24 @@ type CellValue = {

const tableActions = ['view'];

const CorpotatePartnerList = () => {
const CorporatePartnerList = () => {
const navigate = useNavigate();
const intl = useIntl();
const { data, isLoading } = useSuspenseQuery({
queryKey: ['partners'],
queryFn: () => getPartners(),
});
const [pageSize, setPageSize] = useState(10);
const [pageIndex, setPageIndex] = useState(0);
const {
partners, isLoading, count, pages,
} = usePartners({ pageSize, pageIndex: pageIndex + 1 });

// This function will be called by DataTable when pagination, filters, or sorting change
const fetchData = useCallback((tableState) => {
if (pageIndex !== tableState.pageIndex) {
setPageIndex(tableState.pageIndex);
}
if (pageSize !== tableState.pageSize) {
setPageSize(tableState.pageSize);
}
}, [pageIndex, pageSize]);

return (
<DataTable
Expand All @@ -37,9 +48,14 @@ const CorpotatePartnerList = () => {
isFilterable
defaultColumnValues={{ Filter: TextFilter }}
initialState={{
pageSize: 30,
pageIndex: 0,
pageSize,
pageIndex,
}}
data={partners}
itemCount={count}
pageCount={pages}
fetchData={fetchData}
manualPagination
additionalColumns={[
{
id: 'action',
Expand All @@ -53,8 +69,6 @@ const CorpotatePartnerList = () => {
)),
},
]}
itemCount={data.length}
data={data}
columns={[
{
Header: intl.formatMessage(messages.headerName),
Expand Down Expand Up @@ -94,4 +108,4 @@ const CorpotatePartnerList = () => {
);
};

export default CorpotatePartnerList;
export default CorporatePartnerList;
26 changes: 25 additions & 1 deletion src/partner/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CorporatePartner } from '@src/app/types';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { getPartnerDetails } from './api';
import { getPartnerDetails, getPartners } from './api';

export const usePartnerDetails = ({ partnerId }) => {
const queryClient = useQueryClient();
Expand All @@ -20,3 +20,27 @@ export const usePartnerDetails = ({ partnerId }) => {
isLoadingPartnerDetails: isLoading,
};
};

interface UsePartnersOptions {
pageSize: number;
pageIndex: number;
}

export function usePartners({ pageSize, pageIndex }: UsePartnersOptions) {
const {
data,
isLoading,
error,
} = useQuery({
queryKey: ['partners', pageSize, pageIndex],
queryFn: () => getPartners({ pageSize, pageIndex }),
});

return {
isLoading,
partners: data?.results || [],
count: data?.count || 0,
pages: data?.numPages || 1,
error,
};
}
Loading