Skip to content
Merged
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
7 changes: 7 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Release Notes
=============

Version 0.72.3
--------------

- feat: server-side pagination and search for contract codes (#3530)
- Log missing/invalid edx_module_id in content-file API requests (#3539)
- Add course enrollment gtm (#3524)

Version 0.72.2 (Released July 01, 2026)
--------------

Expand Down
2 changes: 1 addition & 1 deletion frontends/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"ol-test-utilities": "0.0.0"
},
"dependencies": {
"@mitodl/mitxonline-api-axios": "2026.6.17",
"@mitodl/mitxonline-api-axios": "2026.6.30-1",
"@tanstack/react-query": "^5.66.0",
"axios": "^1.12.2",
"tiny-invariant": "^1.3.3"
Expand Down
37 changes: 20 additions & 17 deletions frontends/api/src/mitxonline/hooks/organizations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ const useBulkAssignSeats = () => {
) => b2bApi.b2bManagerOrganizationsContractsCodesBulkAssignCreate(opts),
onSettled: (_data, _err, vars) => {
queryClient.invalidateQueries({
queryKey: managerOrganizationKeys.contractCodes({
id: vars.id,
parent_lookup_organization: vars.parent_lookup_organization,
}),
queryKey: managerOrganizationKeys.contractCodesForContract(
vars.id,
vars.parent_lookup_organization,
),
})
},
})
Expand All @@ -57,10 +57,10 @@ const useRemindCode = () => {
) => b2bApi.b2bManagerOrganizationsContractsCodesRemindCreate(opts),
onSettled: (_data, _err, vars) => {
queryClient.invalidateQueries({
queryKey: managerOrganizationKeys.contractCodes({
id: vars.id,
parent_lookup_organization: vars.parent_lookup_organization,
}),
queryKey: managerOrganizationKeys.contractCodesForContract(
vars.id,
vars.parent_lookup_organization,
),
})
},
})
Expand All @@ -75,10 +75,10 @@ const useRevokeCode = () => {
) => b2bApi.b2bManagerOrganizationsContractsCodesRevokeDestroy(opts),
onSettled: (_data, _err, vars) => {
queryClient.invalidateQueries({
queryKey: managerOrganizationKeys.contractCodes({
id: vars.id,
parent_lookup_organization: vars.parent_lookup_organization,
}),
queryKey: managerOrganizationKeys.contractCodesForContract(
vars.id,
vars.parent_lookup_organization,
),
})
},
})
Expand All @@ -97,10 +97,10 @@ const useReassignCode = () => {
) => b2bApi.b2bManagerOrganizationsContractsCodesReassignUpdate(opts),
onSettled: (_data, _err, vars) => {
queryClient.invalidateQueries({
queryKey: managerOrganizationKeys.contractCodes({
id: vars.id,
parent_lookup_organization: vars.parent_lookup_organization,
}),
queryKey: managerOrganizationKeys.contractCodesForContract(
vars.id,
vars.parent_lookup_organization,
),
})
},
})
Expand All @@ -115,4 +115,7 @@ export {
useRemindCode,
useRevokeCode,
}
export type { ContractCode } from "./queries"
export type {
ManagerEnrollmentCode,
PaginatedManagerEnrollmentCodeList,
} from "@mitodl/mitxonline-api-axios/v2"
20 changes: 10 additions & 10 deletions frontends/api/src/mitxonline/hooks/organizations/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@ import { b2bApi } from "../../clients"
import {
OrganizationPage,
ManagerContractDetail,
ManagerEnrollmentCode,
PaginatedManagerEnrollmentCodeList,
B2bApiB2bOrganizationsRetrieveRequest,
B2bApiB2bManagerOrganizationsContractsRetrieveRequest,
B2bApiB2bManagerOrganizationsContractsCodesListRequest,
} from "@mitodl/mitxonline-api-axios/v2"

type ContractCode = ManagerEnrollmentCode & {
redemption_status: "unassigned" | "assigned" | "redeemed"
}

const organizationKeys = {
root: ["mitxonline", "organizations"],
organizationsRetrieve: (opts?: B2bApiB2bOrganizationsRetrieveRequest) => [
Expand Down Expand Up @@ -50,14 +46,20 @@ const managerOrganizationKeys = {
contractCodes: (
opts: B2bApiB2bManagerOrganizationsContractsCodesListRequest,
) => [...managerOrganizationKeys.contractCodesRoot(), opts] as const,
// Prefix key used for invalidation — matches all pages/search states for one contract
contractCodesForContract: (id: number, orgId: number) =>
managerOrganizationKeys.contractCodes({
id,
parent_lookup_organization: orgId,
}),
}

const managerOrganizationQueries = {
managerOrganizationsList: () =>
queryOptions({
queryKey: managerOrganizationKeys.list(),
queryFn: async (): Promise<OrganizationPage[]> =>
b2bApi.b2bManagerOrganizationsList().then((res) => res.data),
b2bApi.b2bManagerOrganizationsList().then((res) => res.data.results),
}),
managerContractDetail: (
opts: B2bApiB2bManagerOrganizationsContractsRetrieveRequest,
Expand All @@ -74,10 +76,10 @@ const managerOrganizationQueries = {
) =>
queryOptions({
queryKey: managerOrganizationKeys.contractCodes(opts),
queryFn: async (): Promise<ContractCode[]> =>
queryFn: async (): Promise<PaginatedManagerEnrollmentCodeList> =>
b2bApi
.b2bManagerOrganizationsContractsCodesList(opts)
.then((res) => res.data as ContractCode[]),
.then((res) => res.data),
}),
}

Expand All @@ -87,5 +89,3 @@ export {
managerOrganizationQueries,
managerOrganizationKeys,
}

export type { ContractCode }
27 changes: 23 additions & 4 deletions frontends/api/src/mitxonline/test-utils/factories/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import type {
BulkAssignError,
BulkAssignResult,
ContractPage,
ManagerEnrollmentCode,
PaginatedManagerEnrollmentCodeList,
} from "@mitodl/mitxonline-api-axios/v2"
import { makePaginatedFactory } from "ol-test-utilities"
import type { ContractCode } from "../../hooks/organizations"

const contract = (overrides: Partial<ContractPage> = {}): ContractPage => ({
id: faker.number.int(),
contract_end: faker.date.future().toISOString(),
contract_start: faker.date.past().toISOString(),
description: faker.lorem.sentence(),
integration_type: "non-sso" as const,
name: faker.company.name(),
organization: faker.number.int(),
slug: faker.lorem.slug(),
Expand All @@ -26,7 +26,19 @@ const contract = (overrides: Partial<ContractPage> = {}): ContractPage => ({

const contracts = makePaginatedFactory(contract)

const contractCode = (overrides: Partial<ContractCode> = {}): ContractCode => {
const paginatedContractCodes = (
results: ManagerEnrollmentCode[],
opts: { count?: number; next?: string | null; previous?: string | null } = {},
): PaginatedManagerEnrollmentCodeList => ({
count: opts.count ?? results.length,
next: opts.next ?? null,
previous: opts.previous ?? null,
results,
})

const contractCode = (
overrides: Partial<ManagerEnrollmentCode> = {},
): ManagerEnrollmentCode => {
const status = overrides.redemption_status ?? "assigned"
const isAssigned = status !== "unassigned"
const isRedeemed = status === "redeemed"
Expand Down Expand Up @@ -61,4 +73,11 @@ const bulkAssignResult = (
...overrides,
})

export { contract, contracts, contractCode, bulkAssignError, bulkAssignResult }
export {
contract,
contracts,
contractCode,
paginatedContractCodes,
bulkAssignError,
bulkAssignResult,
}
20 changes: 18 additions & 2 deletions frontends/api/src/mitxonline/test-utils/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,24 @@ const contracts = {
contractsList: () => `${getApiBaseUrl()}/api/v0/b2b/contracts/`,
managerContractDetail: (orgId: number, contractId: number) =>
`${getApiBaseUrl()}/api/v0/b2b/manager/organizations/${orgId}/contracts/${contractId}/`,
managerContractCodes: (orgId: number, contractId: number) =>
`${getApiBaseUrl()}/api/v0/b2b/manager/organizations/${orgId}/contracts/${contractId}/codes/`,
managerContractCodes: (
orgId: number,
contractId: number,
params?: {
page?: number
page_size?: number
search_term?: string
status?: string
},
) => {
// queryify does not filter undefined values, so strip them first to avoid e.g. search_term=undefined in the URL
const clean = params
? Object.fromEntries(
Object.entries(params).filter(([, v]) => v !== undefined),
)
: undefined
return `${getApiBaseUrl()}/api/v0/b2b/manager/organizations/${orgId}/contracts/${contractId}/codes/${queryify(clean)}`
},
managerContractBulkAssign: (orgId: number, contractId: number) =>
`${getApiBaseUrl()}/api/v0/b2b/manager/organizations/${orgId}/contracts/${contractId}/codes/bulk_assign/`,
managerContractCodeRemind: (
Expand Down
2 changes: 1 addition & 1 deletion frontends/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@floating-ui/react": "^0.27.16",
"@mitodl/arithmix": "^0.2.2",
"@mitodl/course-search-utils": "^3.5.2",
"@mitodl/mitxonline-api-axios": "2026.6.17",
"@mitodl/mitxonline-api-axios": "2026.6.30-1",
"@mitodl/smoot-design": "^6.27.0",
"@mui/base": "5.0.0-beta.70",
"@mui/material": "^6.4.5",
Expand Down
6 changes: 6 additions & 0 deletions frontends/main/public/sample-seat-assignments.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
email
testuser1@example.com
testuser2@example.com
testuser3@example.com
testuser4@example.com
testuser5@example.com
Loading
Loading