Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
0037354
server-side pagination and search for contract codes
daniellefrappier18 Jun 26, 2026
6b20878
add isLoadingSeats to AssignSeatsSection test renders and drop page_s…
daniellefrappier18 Jun 26, 2026
fe34517
export CSV guards, totalPages div-by-zero, and tab filter TODO
daniellefrappier18 Jun 26, 2026
181110d
move contract codes tab filtering server-side and fix CSV pagination
daniellefrappier18 Jun 26, 2026
d7edf36
replace this-alias in anchor click spy with mock.instances
daniellefrappier18 Jun 26, 2026
4c1c03c
fix whitespace
daniellefrappier18 Jun 26, 2026
e40f92d
copilot suggestions
daniellefrappier18 Jun 26, 2026
79cb0f0
add sample CSV template and wire up download link for seat assignment…
daniellefrappier18 Jun 26, 2026
c6b101f
simplify contractCodes query key
daniellefrappier18 Jun 29, 2026
49f6e70
remove not helpful comment
daniellefrappier18 Jun 29, 2026
f5ae439
fix pagination flicker
daniellefrappier18 Jun 29, 2026
51f7bc9
fix tests: add page_size to codes mock URLs and paginate CSV expor
daniellefrappier18 Jun 29, 2026
ce50670
remove unused id and name columns from seat assignment CSV template
daniellefrappier18 Jun 30, 2026
9ad2d54
removed unused export
daniellefrappier18 Jun 30, 2026
e66b992
bump @mitodl/mitxonline-api-axios to published 2026.6.30-1
daniellefrappier18 Jul 1, 2026
7761d2a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 1, 2026
2210dbf
format fix
daniellefrappier18 Jul 1, 2026
bc2e362
update manager orgs mocks to paginated response shape
daniellefrappier18 Jul 1, 2026
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 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